/* * ringbuffer.c * * Created on: Sep 14, 2021 * Author: Attila Body */ #include // #include "macro_utils.h" // #include "print_string.h" // #include "taskregistry.h" #include #define __ASSERT(x) assert_param(x) namespace f1ll { ringbuffer::ringbuffer(uint8_t *buffer, uint16_t size) : m_buffer(buffer), m_size(size), m_head(0), m_head_shadow(0), m_tail(0) { // __ASSERT(handle); // __ASSERT(buffer); // __ASSERT(buffer_size); } uint16_t ringbuffer::buffer_used(uint16_t size, uint16_t head, uint16_t tail) { return head >= tail ? head - tail : size - tail + head; } uint16_t ringbuffer::buffer_free(uint16_t size, uint16_t head, uint16_t tail) { return size - buffer_used(size, head, tail) - 1; } uint16_t ringbuffer::buffer_used() const { return m_head_shadow >= m_tail ? m_head_shadow - m_tail : m_size - m_tail + m_head_shadow; } uint16_t ringbuffer::buffer_free() const { return m_size - buffer_used() - 1; } uint16_t ringbuffer::put(uint8_t const *data_buffer, uint16_t len) { uint16_t chunk1 = 0; uint16_t chunk2 = 0; if (!data_buffer || !len) { return 0; } uint16_t max_len = buffer_free(m_size, m_head_shadow, m_tail); len = len < max_len ? len : max_len; chunk1 = m_size - m_head_shadow; if (chunk1 >= len) { chunk1 = len; } else { chunk2 = len - chunk1; } std::memcpy(m_buffer + m_head_shadow, data_buffer, chunk1); m_head_shadow += chunk1; if (m_head_shadow == m_size) { m_head_shadow = 0; } if (chunk2) { std::memcpy(m_buffer, data_buffer + chunk1, chunk2); m_head_shadow += chunk2; if (m_head_shadow == m_size) { m_head_shadow = 0; } } return len; } void ringbuffer::commit() { uint16_t uncommitted = buffer_used(m_size, m_head_shadow, m_head); if (!uncommitted) { return; } m_head = m_head_shadow; } // void ringbuffe::flush() // { // while (handle->m_head != handle->m_tail) { // } // } bool ringbuffer::get_chunk(uint16_t len_requested, uint8_t **data, uint16_t *len) { if (!len_requested || !data || !*data || !len) { return false; } uint16_t head = m_head; uint16_t tail = m_tail; uint16_t chunk_size = head >= tail ? head - tail : m_size - 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 == m_size) { tail = 0; } return tail != head; } void ringbuffer::report_consumption(uint16_t consumed) { if (!consumed) { return; } m_tail += consumed; if (m_tail == m_size) { m_tail = 0; } } uint16_t ringbuffer::commited() const { return buffer_used(m_size, m_head, m_tail); } uint16_t ringbuffer::uncommited() const { return buffer_used(m_size, m_head_shadow, m_head); } void ringbuffer::discard() { m_head_shadow = m_head; } } // namespace f1ll