diff --git a/lib/M5Utility/boards/m5stack-nanoc6.json b/lib/M5Utility/boards/m5stack-nanoc6.json new file mode 100644 index 0000000..cae742e --- /dev/null +++ b/lib/M5Utility/boards/m5stack-nanoc6.json @@ -0,0 +1,33 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5Stack_NanoC6" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack NanoC6", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194384, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.m5stack.com/en/core/M5NanoC6", + "vendor": "M5Stack" +} diff --git a/lib/M5Utility/platformio.ini b/lib/M5Utility/platformio.ini index 92b1451..bb0591f 100644 --- a/lib/M5Utility/platformio.ini +++ b/lib/M5Utility/platformio.ini @@ -8,8 +8,7 @@ build_flags =-Wall -Wextra -Wreturn-local-addr -Werror=format -Werror=return-loc lib_ldf_mode = deep test_framework = googletest test_build_src = true -;lib_deps=m5stack/M5Unified -lib_deps= https://github.com/m5stack/M5Unified.git#develop +lib_deps=m5stack/M5Unified ; -------------------------------- ;Choose device @@ -46,11 +45,31 @@ borad =m5stack-fire extends = m5base board = m5stack-stamps3 +[AtomS3] +extends = m5base +board = m5stack-atoms3 + +; Using ./boards/m5stack-nanoc6.json +[NanoC6] +extends = m5base +board = m5stack-nanoc6 +platform = https://github.com/platformio/platform-espressif32.git +platform_packages = + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 +board_build.partitions = default.csv + [native] -build_flags = -Os -xc++ -std=c++11 +build_flags = -O3 -xc++ -std=c++14 -lSDL2 + -arch arm64 ; for arm mac + -I"/usr/local/include/SDL2" ; for intel mac homebrew SDL2 + -L"/usr/local/lib" ; for intel mac homebrew SDL2 + -I"${sysenv.HOMEBREW_PREFIX}/include/SDL2" ; for arm mac homebrew SDL2 + -L"${sysenv.HOMEBREW_PREFIX}/lib" ; for arm mac homebrew SDL2 platform = native test_filter= native/* test_ignore= embedded/* +lib_deps = ${env.lib_deps} ; -------------------------------- ;Choose build options @@ -111,3 +130,12 @@ extends=StampS3, option_release extends=StampS3, option_release lib_deps = ${env.lib_deps} m5stack/M5Dial + +[env:test_AtomS3] +extends=AtomS3, option_release +lib_deps = ${env.lib_deps} + +[env:test_NanoC6] +extends=NanoC6, option_release +lib_deps = ${env.lib_deps} + \ No newline at end of file diff --git a/lib/M5Utility/src/M5Utility.hpp b/lib/M5Utility/src/M5Utility.hpp index b0ebd68..5dc4ad7 100644 --- a/lib/M5Utility/src/M5Utility.hpp +++ b/lib/M5Utility/src/M5Utility.hpp @@ -1,13 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /*! @file M5Utility.hpp @brief Main header of M5Utility @mainpage M5Utility Llibrary containing utilities common to M5 products. C++11 or later - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #ifndef M5_UTILITY_HPP #define M5_UTILITY_HPP @@ -20,6 +21,7 @@ #include "m5_utility/log/library_log.hpp" #include "m5_utility/container/circular_buffer.hpp" +//#include "m5_utility/container/fixed_circular_buffer.hpp" #include "m5_utility/bit_segment.hpp" #include "m5_utility/compatibility_feature.hpp" @@ -40,12 +42,20 @@ namespace m5 { @namespace utility @brief For utilities */ -namespace utility {} // namespace utility +namespace utility {} /*! @namespace stl @brief STL compatibility functions and classes */ namespace stl {} + +/*! + @namespace container + @brief Container classes + */ +namespace container {} + } // namespace m5 + #endif diff --git a/lib/M5Utility/src/m5_utility/container/circular_buffer.hpp b/lib/M5Utility/src/m5_utility/container/circular_buffer.hpp index 9d25bcc..bb2357d 100644 --- a/lib/M5Utility/src/m5_utility/container/circular_buffer.hpp +++ b/lib/M5Utility/src/m5_utility/container/circular_buffer.hpp @@ -1,10 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /*! @file circular_buffer.hpp - @brief Circular buffer (Ring buffer) - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT + @brief Circular buffer with STL-like interface */ #ifndef M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP #define M5_UTILITY_CONTAINER_CIRCULAR_BUFFER_HPP @@ -12,7 +13,7 @@ #include #include #include -#include "../stl//optional.hpp" +#include "../stl/optional.hpp" namespace m5 { namespace container { @@ -102,21 +103,20 @@ class CircularBufferIterator { private: CB* _cb{}; - std::size_t _idx{}; + size_t _idx{}; }; /// @endcond /*! @class CircularBuffer - @brief Container called ring buffer or circular buffer + @brief Type CircularBuffer giving size in constructor @tparam T Type of the element - @tparam N Capacity */ -template +template class CircularBuffer { public: using value_type = T; - using size_type = std::size_t; + using size_type = size_t; using reference = T&; using const_reference = const T&; using return_type = m5::stl::optional; @@ -125,16 +125,23 @@ class CircularBuffer { ///@name Constructor ///@{ - CircularBuffer() = default; - CircularBuffer(size_type n, const_reference value) : CircularBuffer() { + CircularBuffer() = delete; + explicit CircularBuffer(const size_t n) { + assert(n != 0 && "Illegal size"); + _cap = n; + _buf.resize(n); + } + CircularBuffer(const size_type n, const_reference value) + : CircularBuffer(n) { assign(n, value); } template - CircularBuffer(InputIter first, InputIter last) : CircularBuffer() { + CircularBuffer(const size_type n, InputIter first, InputIter last) + : CircularBuffer(n) { assign(first, last); } - CircularBuffer(std::initializer_list il) - : CircularBuffer(il.begin(), il.end()) { + CircularBuffer(const size_type n, std::initializer_list il) + : CircularBuffer(n, il.begin(), il.end()) { } CircularBuffer(const CircularBuffer&) = default; @@ -156,10 +163,10 @@ class CircularBuffer { void assign(InputIterator first, InputIterator last) { clear(); size_type sz = last - first; - if (sz > N) { - first += (sz - N); + if (sz > _cap) { + first += (sz - _cap); } - auto n = std::min(N, sz); + auto n = std::min(_cap, sz); while (n--) { push_back(*first++); } @@ -172,14 +179,14 @@ class CircularBuffer { */ void assign(size_type n, const_reference v) { clear(); - n = std::min(N, n); + n = std::min(_cap, n); while (n--) { push_back(v); } } /*! @brief assigns values to the container - @param il Initializer list to copy the values from + @param il Initializer list from which the copy is made */ inline void assign(std::initializer_list il) { assign(il.begin(), il.end()); @@ -201,8 +208,9 @@ class CircularBuffer { @return m5::stl::optional */ inline return_type back() const { - return !empty() ? m5::stl::make_optional(_buf[(_head - 1 + N) % N]) - : m5::stl::nullopt; + return !empty() + ? m5::stl::make_optional(_buf[(_head - 1 + _cap) % _cap]) + : m5::stl::nullopt; } /*! @brief Access specified element @@ -211,7 +219,7 @@ class CircularBuffer { inline const_reference operator[](size_type i) const& { assert(size() > 0 && "container empty"); assert(i < size() && "index overflow"); - return _buf[(_tail + i) % N]; + return _buf[(_tail + i) % _cap]; } /*! @brief Access specified element with bounds checking @@ -219,7 +227,7 @@ class CircularBuffer { */ inline return_type at(size_type i) const { return (!empty() && i < size()) - ? m5::stl::make_optional(_buf[(_tail + i) % N]) + ? m5::stl::make_optional(_buf[(_tail + i) % _cap]) : m5::stl::nullopt; } /*! @@ -228,18 +236,18 @@ class CircularBuffer { @param num Max elements of output buffer @return Number of elements read */ - std::size_t read(value_type* outbuf, const std::size_t num) { - std::size_t sz = std::min(num, size()); + size_t read(value_type* outbuf, const size_t num) { + size_t sz = std::min(num, size()); if (sz == 0) { return sz; } - auto tail = _tail; - auto src = &_buf[tail]; - std::size_t elms = std::min(N - tail, sz); + auto tail = _tail; + auto src = &_buf[tail]; + size_t elms = std::min(_cap - tail, sz); std::copy(src, src + elms, outbuf); - tail = (tail + elms) % N; - std::size_t ret = elms; + tail = (tail + elms) % _cap; + size_t ret = elms; if (elms < sz) { outbuf += elms; @@ -290,15 +298,15 @@ class CircularBuffer { @brief returns the number of elements */ inline size_type size() const { - return full() ? N - : (_head >= _tail ? _head - _tail : N + _head - _tail); + return full() ? _cap + : (_head >= _tail ? _head - _tail : _cap + _head - _tail); } /*! @brief Returns the number of elements that can be held in currently storage */ inline size_type capacity() const { - return N; + return _cap; } ///@} @@ -307,37 +315,37 @@ class CircularBuffer { /*! @brief Clears the contents */ void clear() { _full = false; - _head = _tail; + _head = _tail = 0U; } //! @brief Adds an element to the top void push_front(const value_type& v) { - _tail = (_tail - 1 + N) % N; + _tail = (_tail - 1 + _cap) % _cap; _buf[_tail] = v; if (_full) { - _head = (_head - 1 + N) % N; + _head = (_head - 1 + _cap) % _cap; } _full = (_head == _tail); } //! @brief Adds an element to the end void push_back(const value_type& v) { _buf[_head] = v; - _head = (_head + 1) % N; + _head = (_head + 1) % _cap; if (_full) { - _tail = (_tail + 1) % N; + _tail = (_tail + 1) % _cap; } _full = (_head == _tail); } //! @brief removes the top element inline void pop_front() { if (!empty()) { - _tail = (_tail + 1) % N; + _tail = (_tail + 1) % _cap; _full = false; } } //! @brief removes the end element inline void pop_back() { if (!empty()) { - _head = (_head - 1 + N) % N; + _head = (_head - 1 + _cap) % _cap; _full = false; } } @@ -351,7 +359,7 @@ class CircularBuffer { */ void fill(const value_type& v) { clear(); - _buf.fill(v); + std::fill(_buf.begin(), _buf.end(), v); _full = true; } /*! @@ -361,6 +369,7 @@ class CircularBuffer { void swap(CircularBuffer& o) { if (this != &o) { std::swap(_buf, o._buf); + std::swap(_cap, o._cap); std::swap(_head, o._head); std::swap(_tail, o._tail); std::swap(_full, o._full); @@ -368,12 +377,50 @@ class CircularBuffer { } ///@} - private: - std::array _buf{}; - std::size_t _head{}, _tail{}; + // private: + std::vector _buf{}; + size_t _cap{}, _head{}, _tail{}; bool _full{}; }; +/*! + @class FixedCircularBuffer + @brief Type CircularBuffer giving size in template parameter + @tparam T Type of the element + @tpatam N Capacity of the buffer +*/ +template +class FixedCircularBuffer : public CircularBuffer { + public: + using value_type = T; + using size_type = size_t; + using reference = T&; + using const_reference = const T&; + using return_type = m5::stl::optional; + friend class CircularBufferIterator>; + using const_iterator = CircularBufferIterator>; + + FixedCircularBuffer() : CircularBuffer(N) { + } + FixedCircularBuffer(const size_type n, const_reference value) + : CircularBuffer(N) { + CircularBuffer::assign(n, value); + } + template + FixedCircularBuffer(InputIter first, InputIter last) + : CircularBuffer(N, first, last) { + } + FixedCircularBuffer(std::initializer_list il) + : CircularBuffer(N, il) { + } + + FixedCircularBuffer(const FixedCircularBuffer&) = default; + FixedCircularBuffer(FixedCircularBuffer&&) = default; + + FixedCircularBuffer& operator=(const FixedCircularBuffer&) = default; + FixedCircularBuffer& operator=(FixedCircularBuffer&&) = default; +}; + } // namespace container } // namespace m5 @@ -383,9 +430,9 @@ namespace std { @related m5::container::CircularBuffer @param a,b Containers whose contents to swap */ -template -inline void swap(m5::container::CircularBuffer& a, - m5::container::CircularBuffer& b) { +template +inline void swap(m5::container::CircularBuffer& a, + m5::container::CircularBuffer& b) { a.swap(b); } } // namespace std diff --git a/lib/M5Utility/src/m5_utility/crc.hpp b/lib/M5Utility/src/m5_utility/crc.hpp index 46ca76e..b9af15b 100644 --- a/lib/M5Utility/src/m5_utility/crc.hpp +++ b/lib/M5Utility/src/m5_utility/crc.hpp @@ -1,10 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /*! @file crc.hpp @brief Calculate CRC - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #ifndef M5_UTILITY_CRC_HPP #define M5_UTILITY_CRC_HPP @@ -18,34 +19,60 @@ namespace utility { /*! @class CRC8 - @brief Base + @brief Base class of the CRC8 calculator */ class CRC8 { public: - ///@name Constructor - //@{ CRC8() = delete; + /*! + @param init Initial value + @param polynormal Generated polynomial + @param refIn Inverted input? + @param refOut Inverted output? + @param xorout Exclusive OR output + */ CRC8(const uint8_t init, const uint8_t polynomial, const bool refIn, const bool refOut, const uint8_t xorout) - : _init{init}, + : _crc{init}, _polynomial{polynomial}, + _xorout{xorout}, _refIn{refIn}, - _refOut{refOut}, - _xorout{xorout} { + _refOut{refOut} { } - ///@} - - //! @brief Gets the CRC8 - inline uint8_t get(const uint8_t* data, size_t len) const { - return calculate(data, len, _init, _polynomial, _refIn, _refOut, - _xorout); + /*! + @brief Stores the CRC of the specified array using the current internal + information + @param data Pointer of the array + @param len Length of the array + @return CRC value + */ + inline uint8_t update(const uint8_t* data, size_t len) { + _crc = calculate(data, len, _crc, _polynomial, _refIn, _refOut, _xorout, + false); + return finalize(_crc, _refOut, _xorout); } - - //! @brief Calculate CRC-8 + /*! + @brief CRC value at the time of the call + @return CRC value + */ + inline uint8_t value() const { + return finalize(_crc, _refOut, _xorout); + } + /*! + @brief Calculate CRC8 + @param data Pointer of the array + @param len Length of the array + @param polynormal Generated polynomial + @param refIn Inverted input? + @param refOut Inverted output? + @param xorout Exclusive OR output + @param do_finalize Apply processing to output values?(true as defaut) + @return CRC value + */ static uint8_t calculate(const uint8_t* data, size_t len, const uint8_t init, const uint8_t polynomial, const bool refIn, const bool refOut, - const uint8_t xorout) { + const uint8_t xorout, bool do_finalize = true) { uint8_t crc{init}; while (len--) { uint8_t e = refIn ? reverseBitOrder(*data) : *data; @@ -60,59 +87,76 @@ class CRC8 { } } } - if (refOut) { - crc = reverseBitOrder(crc); - } - return crc ^ xorout; + return do_finalize ? finalize(crc, refOut, xorout) : crc; + } + + protected: + static inline uint8_t finalize(const uint8_t value, const bool refOut, + const uint8_t xorout) { + return (refOut ? reverseBitOrder(value) : value) ^ xorout; } private: - uint8_t _init{0x00}; - uint8_t _polynomial{0x07}; + uint8_t _crc{}, _polynomial{}, _xorout{}; bool _refIn{}, _refOut{}; - uint8_t _xorout{0x00}; -}; - -/*! - @class CRC8_Maxim - @brief 1-Wire bus -*/ -class CRC8_Maxim : public CRC8 { - public: - CRC8_Maxim() : CRC8(0xFF, 0x31, false, false, 0x00) { - } }; /*! @class CRC16 - @brief Base + @brief Base class of the CRC16 calculator */ class CRC16 { public: - ///@name Constructor - //@{ CRC16() = delete; + /*! + @param init Initial value + @param polynormal Generated polynomial + @param refIn Inverted input? + @param refOut Inverted output? + @param xorout Exclusive OR output + */ CRC16(const uint16_t init, const uint16_t polynomial, const bool refIn, const bool refOut, const uint16_t xorout) - : _init{init}, + : _crc{init}, _polynomial{polynomial}, + _xorout{xorout}, _refIn{refIn}, - _refOut{refOut}, - _xorout{xorout} { + _refOut{refOut} { } - ///@} - - //! @brief Gets the CRC16 - inline uint16_t get(const uint8_t* data, size_t len) const { - return calculate(data, len, _init, _polynomial, _refIn, _refOut, - _xorout); + /*! + @brief Stores the CRC of the specified array using the current internal + information + @param data Pointer of the array + @param len Length of the array + @return CRC value + */ + inline uint16_t update(const uint8_t* data, size_t len) { + _crc = calculate(data, len, _crc, _polynomial, _refIn, _refOut, _xorout, + false); + return finalize(_crc, _refOut, _xorout); } - - //! @brief Calculate CRC-16 + /*! + @brief CRC value at the time of the call + @return CRC value + */ + inline uint16_t value() const { + return finalize(_crc, _refOut, _xorout); + } + /*! + @brief Calculate CRC16 + @param data Pointer of the array + @param len Length of the array + @param polynormal Generated polynomial + @param refIn Inverted input? + @param refOut Inverted output? + @param xorout Exclusive OR output + @param do_finalize Apply processing to output values?(true as defaut) + @return CRC value + */ static uint16_t calculate(const uint8_t* data, size_t len, const uint16_t init, const uint16_t polynomial, const bool refIn, const bool refOut, - const uint16_t xorout) { + const uint16_t xorout, bool do_finalize = true) { uint16_t crc{init}; while (len--) { uint8_t e{refIn ? reverseBitOrder(*data) : *data}; @@ -127,17 +171,28 @@ class CRC16 { } } } - if (refOut) { - crc = reverseBitOrder(crc); - } - return crc ^ xorout; + return do_finalize ? finalize(crc, refOut, xorout) : crc; + } + + protected: + static inline uint16_t finalize(const uint16_t value, const bool refOut, + const uint16_t xorout) { + return (refOut ? reverseBitOrder(value) : value) ^ xorout; } private: - uint16_t _init{0x0000}; - uint16_t _polynomial{0x1021}; + uint16_t _crc{}, _polynomial{}, _xorout{}; bool _refIn{}, _refOut{}; - uint16_t _xorout{0x0000}; +}; + +/*! + @class CRC8_CheckSum + @brief Typical CRC8 calculator used for read and write data with the chip +*/ +class CRC8_Checksum : public CRC8 { + public: + CRC8_Checksum() : CRC8(0xFF, 0x31, false, false, 0x00) { + } }; } // namespace utility diff --git a/lib/M5Utility/src/m5_utility/misc.hpp b/lib/M5Utility/src/m5_utility/misc.hpp index 7bccae5..22977c7 100644 --- a/lib/M5Utility/src/m5_utility/misc.hpp +++ b/lib/M5Utility/src/m5_utility/misc.hpp @@ -1,10 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /*! @file misc.hpp @brief Miscellaneous features - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #ifndef M5_UTILITY_MISC_HPP #define M5_UTILITY_MISC_HPP diff --git a/lib/M5Utility/src/m5_utility/types.hpp b/lib/M5Utility/src/m5_utility/types.hpp index 57f58c1..88f20cb 100644 --- a/lib/M5Utility/src/m5_utility/types.hpp +++ b/lib/M5Utility/src/m5_utility/types.hpp @@ -1,10 +1,11 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /*! @file types.hpp @brief Type and enumerator definitions - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #ifndef M5_UTILITY_TYPES_HPP #define M5_UTILITY_TYPES_HPP @@ -27,8 +28,10 @@ template union U16 { /// @name Constrcutor ///@{ + /*! @brief default constructor */ constexpr U16() : u16{0} { } + //!@brief from uint16_t #if 0 template constexpr explicit U16(const uint16_t v) : u8{ @@ -43,10 +46,17 @@ union U16 { } #endif + /*! + @brief from uint8_t pointer + @warning The area pointed to by the pointer must be at least 2 bytes + */ + constexpr explicit U16(const uint8_t* p) : u8{*p, *(p + 1)} { + } + //! @brief Stored in order of high and low constexpr U16(const uint8_t high, const uint8_t low) : u8{high, low} { } - constexpr U16(const U16&) = default; - constexpr U16(U16&& o) = default; + constexpr U16(const U16&) = default; //!< @brief as default + constexpr U16(U16&& o) = default; //!< @brief as default ///@} ///@name Assignment diff --git a/lib/M5Utility/test/container_test.cpp b/lib/M5Utility/test/container_test.cpp index d55c2f0..e84a88a 100644 --- a/lib/M5Utility/test/container_test.cpp +++ b/lib/M5Utility/test/container_test.cpp @@ -7,6 +7,7 @@ */ #include #include +#include namespace { @@ -15,7 +16,7 @@ using namespace m5::container; void cb_basic_test() { SCOPED_TRACE("Basic"); - CircularBuffer rbuf; + FixedCircularBuffer rbuf; EXPECT_TRUE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); @@ -36,6 +37,9 @@ void cb_basic_test() { EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 1U); EXPECT_EQ(rbuf[0], 1); + EXPECT_EQ(rbuf.front(), 1); + EXPECT_EQ(rbuf.back(), 1); + M5_LOGW("1> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); // H // | | | | | @@ -48,6 +52,9 @@ void cb_basic_test() { EXPECT_TRUE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 0U); + EXPECT_FALSE(rbuf.front()); + EXPECT_FALSE(rbuf.back()); + M5_LOGW("2> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); // H // | 2 | | | | @@ -57,6 +64,9 @@ void cb_basic_test() { EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 1U); EXPECT_EQ(rbuf[0], 2); + EXPECT_EQ(rbuf.front(), 2); + EXPECT_EQ(rbuf.back(), 2); + M5_LOGW("3> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); // H // | | | | | @@ -69,26 +79,35 @@ void cb_basic_test() { EXPECT_TRUE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 0U); + EXPECT_FALSE(rbuf.front()); + EXPECT_FALSE(rbuf.back()); + M5_LOGW("3> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); // H // | 4 | 5 | 6 | 3 | // T - rbuf.push_front(3); + rbuf.push_front(3); // to front EXPECT_FALSE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 1U); - - rbuf.push_back(4); + EXPECT_EQ(rbuf.front(), 3); + EXPECT_EQ(rbuf.back(), 3); + + rbuf.push_back(4); // to back EXPECT_FALSE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 2U); - - rbuf.push_back(5); + EXPECT_EQ(rbuf.front(), 3); + EXPECT_EQ(rbuf.back(), 4); + + rbuf.push_back(5); // to back EXPECT_FALSE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 3U); - - rbuf.push_front(6); + EXPECT_EQ(rbuf.front(), 3); + EXPECT_EQ(rbuf.back(), 5); + + rbuf.push_front(6); // to front EXPECT_FALSE(rbuf.empty()); EXPECT_TRUE(rbuf.full()); EXPECT_EQ(rbuf.size(), 4U); @@ -96,7 +115,10 @@ void cb_basic_test() { EXPECT_EQ(rbuf[1], 3); EXPECT_EQ(rbuf[2], 4); EXPECT_EQ(rbuf[3], 5); - + EXPECT_EQ(rbuf.front(), 6); + EXPECT_EQ(rbuf.back(), 5); + M5_LOGW("4> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // | 4 | 7 | 6 | 3 | // T @@ -105,7 +127,13 @@ void cb_basic_test() { EXPECT_TRUE(rbuf.full()); EXPECT_EQ(rbuf.size(), 4U); EXPECT_EQ(rbuf[0], 7); - + EXPECT_EQ(rbuf[1], 6); + EXPECT_EQ(rbuf[2], 3); + EXPECT_EQ(rbuf[3], 4); + EXPECT_EQ(rbuf.front(), 7); + EXPECT_EQ(rbuf.back(), 4); + M5_LOGW("5> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // | 4 | 8 | 6 | 3 | // T @@ -117,7 +145,10 @@ void cb_basic_test() { EXPECT_EQ(rbuf[1], 3); EXPECT_EQ(rbuf[2], 4); EXPECT_EQ(rbuf[3], 8); - + EXPECT_EQ(rbuf.front(), 6); + EXPECT_EQ(rbuf.back(), 8); + M5_LOGW("5> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // | | | | | // T @@ -131,7 +162,10 @@ void cb_basic_test() { EXPECT_TRUE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 0U); - + EXPECT_FALSE(rbuf.front()); + EXPECT_FALSE(rbuf.back()); + M5_LOGW("6> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // | 11| 12| 13| 10 | // T @@ -147,19 +181,26 @@ void cb_basic_test() { EXPECT_EQ(rbuf[1], 11); EXPECT_EQ(rbuf[2], 12); EXPECT_EQ(rbuf[3], 13); - + EXPECT_EQ(rbuf.front(), 10); + EXPECT_EQ(rbuf.back(), 13); + M5_LOGW("7> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // | | | 13| | // T - EXPECT_EQ(rbuf.front(), 10); rbuf.pop_front(); EXPECT_EQ(rbuf.front(), 11); + EXPECT_EQ(rbuf.back(), 13); rbuf.pop_front(); EXPECT_EQ(rbuf.front(), 12); + EXPECT_EQ(rbuf.back(), 13); rbuf.pop_front(); EXPECT_FALSE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 1U); + EXPECT_EQ(rbuf.front(), 13); + EXPECT_EQ(rbuf.back(), 13); + M5_LOGW("8> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); // H // | | | | | @@ -168,15 +209,23 @@ void cb_basic_test() { EXPECT_TRUE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.size(), 0U); - + EXPECT_FALSE(rbuf.front()); + EXPECT_FALSE(rbuf.back()); + M5_LOGW("9> %zu/%zu/%u", rbuf._head, rbuf._tail, rbuf._full); + // H // |111|111|111|111| // T rbuf.fill(111); EXPECT_TRUE(rbuf.full()); EXPECT_EQ(rbuf.size(), 4U); + EXPECT_EQ(rbuf[0], 111); + EXPECT_EQ(rbuf[1], 111); + EXPECT_EQ(rbuf[2], 111); + EXPECT_EQ(rbuf[3], 111); EXPECT_EQ(rbuf.front(), 111); EXPECT_EQ(rbuf.back(), 111); + } void cb_constructor_test() { @@ -188,7 +237,7 @@ void cb_constructor_test() { } { - CircularBuffer rbuf(2U, 52); + FixedCircularBuffer rbuf(2U, 52); EXPECT_FALSE(rbuf.empty()); EXPECT_FALSE(rbuf.full()); EXPECT_EQ(rbuf.capacity(), 8U); @@ -197,7 +246,7 @@ void cb_constructor_test() { EXPECT_EQ(rbuf[1], 52); } { - CircularBuffer rbuf(100U, 52); + FixedCircularBuffer rbuf(100U, 52); EXPECT_FALSE(rbuf.empty()); EXPECT_TRUE(rbuf.full()); EXPECT_EQ(rbuf.capacity(), 8U); @@ -207,7 +256,7 @@ void cb_constructor_test() { } { - CircularBuffer rbuf2({9, 8, 7, 6, 5}); + FixedCircularBuffer rbuf2({9, 8, 7, 6, 5}); EXPECT_FALSE(rbuf2.empty()); EXPECT_FALSE(rbuf2.full()); EXPECT_EQ(rbuf2.capacity(), 10U); @@ -219,7 +268,7 @@ void cb_constructor_test() { EXPECT_EQ(rbuf2[4], 5); } { - CircularBuffer rbuf2(table.begin(), table.end()); + FixedCircularBuffer rbuf2(table.begin(), table.end()); EXPECT_FALSE(rbuf2.empty()); EXPECT_TRUE(rbuf2.full()); EXPECT_EQ(rbuf2.capacity(), 8U); @@ -228,7 +277,7 @@ void cb_constructor_test() { EXPECT_EQ(rbuf2.back(), 99); } - CircularBuffer rbuf3 = {1.1f, 2.2f, 3.3f}; + FixedCircularBuffer rbuf3 = {1.1f, 2.2f, 3.3f}; EXPECT_FALSE(rbuf3.empty()); EXPECT_TRUE(rbuf3.full()); EXPECT_EQ(rbuf3.capacity(), 3U); @@ -241,7 +290,7 @@ void cb_constructor_test() { void cb_read() { SCOPED_TRACE("Read"); - CircularBuffer rb; + FixedCircularBuffer rb; int buf[128] = {}; size_t rcnt = 0; @@ -318,8 +367,8 @@ void cb_read() { void cb_iterator_test() { SCOPED_TRACE("Iterators"); - CircularBuffer rb = {0, 1, 2}; - CircularBuffer rb2; + FixedCircularBuffer rb = {0, 1, 2}; + FixedCircularBuffer rb2; int c = 0; for (auto it = rb.cbegin(); it != rb.cend(); ++it) { EXPECT_EQ(*it, c++); @@ -350,7 +399,7 @@ void cb_iterator_test() { } #endif - using Iter = CircularBuffer::const_iterator; + using Iter = FixedCircularBuffer::const_iterator; { Iter it = rb.begin(); EXPECT_EQ(*it++, 9); diff --git a/lib/M5Utility/test/crc_test.cpp b/lib/M5Utility/test/crc_test.cpp index 9fec610..813d430 100644 --- a/lib/M5Utility/test/crc_test.cpp +++ b/lib/M5Utility/test/crc_test.cpp @@ -1,12 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /* UnitTest for M5Utility - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #include #include +#include namespace { struct CRCType { @@ -19,6 +21,7 @@ struct CRCType { const uint32_t xorout; }; +// See also // https://crccalc.com/?crc=0123456789abcdef&method=crc8&datatype=hex&outtype=0 CRCType crc8_table[] = { // name, result, poly, init, refIn, refOut, xorout @@ -71,14 +74,56 @@ using namespace m5::utility; TEST(Utility, CRC8) { for (auto&& e : crc8_table) { + SCOPED_TRACE(e.name); CRC8 crc(e.init, e.poly, e.refIn, e.refOut, e.xorout); - EXPECT_EQ(crc.get(tdata.data(), tdata.size()), e.result) << e.name; + auto v = crc.update(tdata.data(), tdata.size()); + EXPECT_EQ(crc.value(), e.result); + EXPECT_EQ(v, crc.value()); } } TEST(Utility, CRC16) { for (auto&& e : crc16_table) { + SCOPED_TRACE(e.name); + CRC16 crc(e.init, e.poly, e.refIn, e.refOut, e.xorout); + auto v = crc.update(tdata.data(), tdata.size()); + EXPECT_EQ(crc.value(), e.result); + EXPECT_EQ(v, crc.value()); + } +} + +// Test whether calculation from the whole and calculation from split chunks are +// equivalent +TEST(Utility, Chunk) { + // CRC8 + constexpr uint8_t d8[32] = {0x04, 0x67, 0xfc, 0x4d, 0xf4, 0xe7, 0x9c, 0x3b, + 0x05, 0xb8, 0xad, 0x31, 0x97, 0xb1, 0x21, 0x72, + 0x59, 0x5d, 0x80, 0x26, 0x66, 0xc, 0x12, 0x9a, + 0x53, 0xa6, 0x70, 0x87, 0x91, 0x5d, 0xa4, 0x9a}; + for (auto&& e : crc8_table) { + SCOPED_TRACE(e.name); + uint8_t crc_all = CRC8::calculate(d8, m5::stl::size(d8), e.init, e.poly, + e.refIn, e.refOut, e.xorout); + + CRC8 crc(e.init, e.poly, e.refIn, e.refOut, e.xorout); + uint8_t crc_chunk{}; + for (int i = 0; i < 4; ++i) { + crc_chunk = crc.update(d8 + (i * 8), 8); + } + EXPECT_EQ(crc_all, crc_chunk); + } + + // CRC16 + for (auto&& e : crc16_table) { + SCOPED_TRACE(e.name); + uint16_t crc_all = CRC16::calculate( + d8, m5::stl::size(d8), e.init, e.poly, e.refIn, e.refOut, e.xorout); + CRC16 crc(e.init, e.poly, e.refIn, e.refOut, e.xorout); - EXPECT_EQ(crc.get(tdata.data(), tdata.size()), e.result) << e.name; + uint16_t crc_chunk{}; + for (int i = 0; i < 4; ++i) { + crc_chunk = crc.update(d8 + (i * 8), 8); + } + EXPECT_EQ(crc_all, crc_chunk); } } diff --git a/lib/M5Utility/test/types_test.cpp b/lib/M5Utility/test/types_test.cpp index b4bed9c..2b48cd7 100644 --- a/lib/M5Utility/test/types_test.cpp +++ b/lib/M5Utility/test/types_test.cpp @@ -1,9 +1,10 @@ +/* + * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD + * + * SPDX-License-Identifier: MIT + */ /* UnitTest for M5Utility - - SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD - - SPDX-License-Identifier: MIT */ #include #include @@ -11,6 +12,8 @@ using namespace m5::types; TEST(Utility, Types_U16) { + constexpr uint8_t u8array[2] = {0x12, 0x34}; + // Constructor constexpr big_uint16_t bg0; constexpr little_uint16_t lt0; @@ -45,6 +48,13 @@ TEST(Utility, Types_U16) { EXPECT_EQ(lt4.u8[0], 0x34); EXPECT_EQ(lt4.u8[1], 0x12); + constexpr big_uint16_t bg8(u8array); + constexpr little_uint16_t lt8(u8array); + EXPECT_EQ(bg8.u8[0], 0x12); + EXPECT_EQ(bg8.u8[1], 0x34); + EXPECT_EQ(lt8.u8[0], 0x12); + EXPECT_EQ(lt8.u8[1], 0x34); + // Assignment big_uint16_t bg5; little_uint16_t lt5;