2025-06-24 15:18:08 -07:00

175 lines
2.6 KiB
C++

/// © MiroZ 2024
#include <stdint.h>
#include <esp_log.h>
#include <System.h>
#include "app_config.h"
static uint8_t mem[CIRC_BUFFER_SIZE_BYTES];
// template<typename T>
class CircBuffer
{
protected:
uint8_t * m_buffer = (uint8_t *)mem;
size_t head_ = 0;
size_t tail_ = 0;
bool full_ = false;
const uint32_t m_total_size = CIRC_BUFFER_SIZE_BYTES;
Mutex m_mutex; // internal race condition protection mutex
CountingSemaphore m_data_available_semaphore;
public:
CircBuffer() : m_data_available_semaphore(CIRC_BUFFER_SIZE_BYTES/2, 0)
{
// assert(m_buffer = (T*)calloc(size, sizeof(T)));
}
~CircBuffer()
{
// free(m_buffer);
}
CountingSemaphore getSemaphore(){ return m_data_available_semaphore; }
bool putBlock(uint8_t * data, uint8_t len)
{
m_mutex.take();
bool ret_val = true;
if(m_total_size - size(false) >= len)
{
putVal(len);
for(int n = 0; n < len; n++)
putVal(data[n]);
}
else
ret_val = false;
ESP_LOGI("CircBuffer", "Current buffer size: %d", size(false));
m_mutex.give();
m_data_available_semaphore.give();
return ret_val;
}
bool waitForDataAvailable(uint32_t ticks = portMAX_DELAY)
{
return m_data_available_semaphore.take(ticks);
}
bool getBlock(uint8_t * data, uint8_t & len)
{
m_mutex.take();
bool ret_val = true;
if(size(false) >= 2)
{
getVal(len);
for(int n = 0; n < len; n++)
getVal(data[n]);
}
else
ret_val = false;
m_mutex.give();
return ret_val;
}
bool peekBlockLen(uint8_t & len)
{
return peekVal(len);
}
protected:
bool putVal(uint8_t item)
{
if (full_)
return false;
m_buffer[head_++] = item;
if(head_ >= m_total_size)
head_ = 0;
full_ = head_ == tail_;
return true;
}
bool getVal(uint8_t & val)
{
if ((!full_ && (head_ == tail_)))
return false;
full_ = false;
val = m_buffer[tail_++];
if(tail_ >= m_total_size)
tail_ = 0;
return true;
}
bool peekVal(uint8_t & val)
{
if ((!full_ && (head_ == tail_)))
return false;
val = m_buffer[tail_];
return true;
}
public:
void reset()
{
m_mutex.take();
head_ = tail_ = 0;
full_ = false;
m_mutex.give();
}
bool empty()
{
m_mutex.take();
bool ret = (!full_ && (head_ == tail_));
m_mutex.give();
return ret;
}
bool full()
{
return full_;
}
size_t capacity()
{
return m_total_size;
}
size_t size(bool use_mutex = true)
{
if(use_mutex)
m_mutex.take();
size_t size = m_total_size;
if (!full_)
{
if (head_ >= tail_)
size = head_ - tail_;
else
size = m_total_size + head_ - tail_;
}
if(use_mutex)
m_mutex.give();
return size;
}
};