160 lines
No EOL
2.9 KiB
C++
160 lines
No EOL
2.9 KiB
C++
/*
|
|
* ringbuffer.c
|
|
*
|
|
* Created on: Sep 14, 2021
|
|
* Author: Attila Body
|
|
*/
|
|
|
|
#include <f1ll/ringbuffer.h>
|
|
// #include "macro_utils.h"
|
|
// #include "print_string.h"
|
|
// #include "taskregistry.h"
|
|
|
|
#include <cstring>
|
|
|
|
#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
|