#ifndef RINGBUFFER_H #define RINGBUFFER_H #include "../Debug.h" #include "../Platforms.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 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); } /** add as many entries as possible */ size_t addOrIgnore(const Scalar* value, const size_t len) { const size_t toAdd = min(len, getNumFree()); for (size_t i = 0; i < toAdd; ++i) { data[head] = value[i]; head = (head + 1) % size; } used += toAdd; debugMod3(NAME, "addOrIgnore(%d) added %d bytes. used: %d", len, toAdd, used); return toAdd; } // /** 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; if (used>0) {--used;} return res; } const Scalar& getConst() { 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