diff --git a/CMakeLists.txt b/CMakeLists.txt index 0664851..b71828d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,7 @@ add_library(f4ll STATIC src/fault.cpp src/memcpy_dma.cpp src/packet_usart.cpp + src/ringbuffer.cpp src/str_util.cpp src/usart_core.cpp ) diff --git a/inc/f4ll/ringbuffer.h b/inc/f4ll/ringbuffer.h index acf39d1..9ba2ccc 100644 --- a/inc/f4ll/ringbuffer.h +++ b/inc/f4ll/ringbuffer.h @@ -72,10 +72,11 @@ public: virtual size_type unused() const = 0; }; -template class ringbuffer : public iringbuffer +// +class ringbuffer_ext : public iringbuffer { public: - ringbuffer() = default; + ringbuffer_ext(uint8_t *bptr, size_type bsize); size_type put(uint8_t const *data, size_type len) override; void commit() override; @@ -89,7 +90,8 @@ public: size_type unused() const override; private: - uint8_t m_buffer[SZ]; //!< Data bufer + uint8_t *m_buffer; //!< Data bufer + size_type const m_bsize; //!< Data buffer size size_type m_head = 0; //!< Write position size_type m_head_shadow = 0; //!< Shadowed write position for collecting data //!< before committing it @@ -99,120 +101,20 @@ private: }; // -template iringbuffer::size_type ringbuffer::put(uint8_t const *data, size_type len) +template class ringbuffer : public ringbuffer_ext { - size_type chunk1 = 0; - size_type chunk2 = 0; +public: + ringbuffer(); - if (!data || !len) { - return 0; - } - - size_type max_len = unused(); - len = len < max_len ? len : max_len; - - chunk1 = sizeof(m_buffer) - m_head_shadow; - if (chunk1 >= len) { - chunk1 = len; - } else { - chunk2 = len - chunk1; - } - - std::memcpy(m_buffer + m_head_shadow, data, chunk1); - m_head_shadow += chunk1; - if (m_head_shadow == sizeof(m_buffer)) { - m_head_shadow = 0; - } - - if (chunk2) { - std::memcpy(m_buffer, data + chunk1, chunk2); - m_head_shadow += chunk2; - if (m_head_shadow == sizeof(m_buffer)) { - m_head_shadow = 0; - } - } - - return len; -} - -template void ringbuffer::commit() -{ - m_head = m_head_shadow; +private: + uint8_t m_buffer[SZ]; }; -template bool ringbuffer::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const +// +template +ringbuffer::ringbuffer() + : ringbuffer_ext(m_buffer, SZ) { - if (!len_requested) { - return false; - } - - size_type head = m_head; - size_type tail = m_tail; - size_type chunk_size = head >= tail ? head - tail : sizeof(m_buffer) - tail; - - if (!chunk_size) { - len = 0; - return false; - } - - if (chunk_size > len_requested) { - chunk_size = len_requested; - } - data = m_buffer + tail; - len = chunk_size; - - tail += chunk_size; - if (tail == sizeof(m_buffer)) { - tail = 0; - } - - return tail != head; -} - -template void ringbuffer::consumed(size_type len) -{ - if (!len) { - return; - } - m_tail += len; - if (m_tail == sizeof(m_buffer)) { - m_tail = 0; - } -} - -template iringbuffer::size_type ringbuffer::uncommited() const -{ - return marker_diff(m_head_shadow, m_head); -} - -template iringbuffer::size_type ringbuffer::commited() const -{ - return marker_diff(m_head, m_tail); -} - -template void ringbuffer::discard() -{ - m_head_shadow = m_head; -} - -template iringbuffer::size_type ringbuffer::size() const -{ - return SZ; -} - -template iringbuffer::size_type ringbuffer::used() const -{ - return marker_diff(m_head_shadow, m_tail); -} - -template iringbuffer::size_type ringbuffer::unused() const -{ - return SZ - used() - 1; -} - -template iringbuffer::size_type ringbuffer::marker_diff(size_type m1, size_type m2) const -{ - return (m1 >= m2) ? (m1 - m2) : (SZ - m2 + m1); } } // namespace f1ll \ No newline at end of file diff --git a/src/ringbuffer.cpp b/src/ringbuffer.cpp new file mode 100644 index 0000000..5354f95 --- /dev/null +++ b/src/ringbuffer.cpp @@ -0,0 +1,128 @@ +#include + +namespace f4ll { + +ringbuffer_ext::ringbuffer_ext(uint8_t *bptr, size_type bsize) + : m_buffer(bptr), + m_bsize(bsize) +{ +} + +iringbuffer::size_type ringbuffer_ext::put(uint8_t const *data, size_type len) +{ + size_type chunk1 = 0; + size_type chunk2 = 0; + + if (!data || !len) { + return 0; + } + + size_type max_len = unused(); + len = len < max_len ? len : max_len; + + chunk1 = m_bsize - m_head_shadow; + if (chunk1 >= len) { + chunk1 = len; + } else { + chunk2 = len - chunk1; + } + + std::memcpy(m_buffer + m_head_shadow, data, chunk1); + m_head_shadow += chunk1; + if (m_head_shadow == m_bsize) { + m_head_shadow = 0; + } + + if (chunk2) { + std::memcpy(m_buffer, data + chunk1, chunk2); + m_head_shadow += chunk2; + if (m_head_shadow == m_bsize) { + m_head_shadow = 0; + } + } + + return len; +} + +void ringbuffer_ext::commit() +{ + m_head = m_head_shadow; +} + +bool ringbuffer_ext::get_chunk(size_type len_requested, uint8_t const *&data, size_type &len) const +{ + if (!len_requested) { + return false; + } + + size_type head = m_head; + size_type tail = m_tail; + size_type chunk_size = head >= tail ? head - tail : m_bsize - tail; + + if (!chunk_size) { + len = 0; + return tail != head; + } + + if (chunk_size > len_requested) { + chunk_size = len_requested; + } + data = m_buffer + tail; + len = chunk_size; + + tail += chunk_size; + if (tail == m_bsize) { + tail = 0; + } + + return tail != head; +} + +void ringbuffer_ext::consumed(size_type len) +{ + if (!len) { + return; + } + m_tail += len; + if (m_tail == m_bsize) { + m_tail = 0; + } +} + +iringbuffer::size_type ringbuffer_ext::uncommited() const +{ + return marker_diff(m_head_shadow, m_head); +} + +iringbuffer::size_type ringbuffer_ext::commited() const +{ + return marker_diff(m_head, m_tail); +} + +void ringbuffer_ext::discard() +{ + m_head_shadow = m_head; +} + +iringbuffer::size_type ringbuffer_ext::size() const +{ + return m_bsize; +} + +iringbuffer::size_type ringbuffer_ext::used() const +{ + return marker_diff(m_head_shadow, m_tail); +} + +iringbuffer::size_type ringbuffer_ext::unused() const +{ + return m_bsize - used() - 1; +} + +iringbuffer::size_type ringbuffer_ext::marker_diff(size_type m1, size_type m2) const +{ + return (m1 >= m2) ? (m1 - m2) : (m_bsize - m2 + m1); +} + +// +} \ No newline at end of file