#ifndef RINGBUFFER_H #define RINGBUFFER_H #include "../Debug.h" typedef void (*RingBufferFullCallback)(); template class RingBuffer { private: static constexpr const char* NAME = "RingBuffer"; Scalar data[size]; volatile size_t head; volatile size_t tail; volatile mutable size_t used; public: RingBuffer() { init(); } void init() { head = 0; tail = 0; used = 0; } void clear() { init(); } /** add one value to the buffer. blocks until space is available */ void addBlocking(const Scalar value) { while (used == size) {os_delay_us(1000);} data[head] = value; head = (head + 1) % size; ++used; } /** add one value to the buffer, if there is enough space */ void addOrIgnore(const Scalar value) { if (used == size) {return;} data[head] = value; head = (head + 1) % size; ++used; } /** add one value to the buffer, or call the callback if there is no space available */ void addOrCallback(const Scalar value, RingBufferFullCallback cb) { while(used == size) {cb();} data[head] = value; head = (head + 1) % size; ++used; } /** add multiple values to the buffer. blocks until space is available */ void addBlocking(const Scalar* value, const size_t len) { debugMod1(NAME, "addBlocking(%d)", len); for (size_t i = 0; i < len; ++i) { addBlocking(value[i]); } debugMod1(NAME, "used: %d", used); } /** add multiple values to the buffer, if there is enough space */ void addOrIgnore(const Scalar* value, const size_t len) { debugMod1(NAME, "addOrIgnore(%d)", len); for (size_t i = 0; i < len; ++i) { addOrIgnore(value[i]); } debugMod1(NAME, "used: %d", used); } /** add multiple values to the buffer, if there is enough space */ void addOrCallback(const Scalar* value, const size_t len, RingBufferFullCallback cb) { debugMod1(NAME, "addOrCallback(%d)", len); for (size_t i = 0; i < len; ++i) { addOrCallback(value[i], cb); } debugMod1(NAME, "used: %d", used); } // /** anything available? */ // bool hasNext() const { // return used != 0; // } /** get the next value from the buffer */ Scalar get() { const Scalar res = data[tail]; tail = (tail + 1) % size; --used; return res; } const Scalar& getConst() const { const uint8_t idx = tail; tail = (tail + 1) % size; --used; return data[idx]; } /** true if the buffer is currently empty */ bool empty() const { return used == 0; } /** true if the buffer is currently full */ bool full() const { return size == used; } /** get the number of used elements within the buffer */ size_t getNumUsed() const { return used; } /** get the number of free elements within the buffer */ size_t getNumFree() const { return size-used; } }; #endif // RINGBUFFER_H