175 lines
2.8 KiB
C++
175 lines
2.8 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;
|
|
}
|
|
}; |