/// © MiroZ 2024 #include #include #include #include "app_config.h" static uint8_t mem[CIRC_BUFFER_SIZE_BYTES]; // template 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; } };