145 lines
3.1 KiB
C++
145 lines
3.1 KiB
C++
#ifndef RINGBUFFER_H
|
|
#define RINGBUFFER_H
|
|
|
|
#include "../Debug.h"
|
|
#include "../Platforms.h"
|
|
|
|
typedef void (*RingBufferFullCallback)();
|
|
|
|
|
|
template <typename Scalar, int size> 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;
|
|
--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
|