diff --git a/firmware/slavechip/ringbuf_test.c b/firmware/slavechip/ringbuf_test.c new file mode 100644 index 0000000..38bb9c6 --- /dev/null +++ b/firmware/slavechip/ringbuf_test.c @@ -0,0 +1,11 @@ +#include "ringbuffer.h" + + +ringbuf_t foo; +char buf[22]; + + +int main(){ + ringbuf_init(&foo,buf,sizeof(buf)); +} + diff --git a/firmware/slavechip/ringbuffer.c b/firmware/slavechip/ringbuffer.c new file mode 100644 index 0000000..c352d0c --- /dev/null +++ b/firmware/slavechip/ringbuffer.c @@ -0,0 +1,77 @@ +#include "ringbuffer.h" + +#include + + +/* Very generic implementation of an interrupt-safe ringbuffer + * + * Contention handling: + * - writing of pointers only with interrupt lock + * - reading of pointers allowed at any time + * - volatile not really necessary, unless you really need the functions to + * react to freespace/newdata while they're running + * + * PUT AND GET ARE NOT REENTRANT! + */ + +void ringbuf_init(ringbuf_t *rb, char* buf, int size){ + rb->startptr = buf; + rb->endptr = buf+size; + rb->readpos = buf; + rb->writepos = buf; +} + +/* pushes a value onto the ringbuffer + * returns 0 on success, 1 on buffer full + */ +uint8_t ringbuf_put(ringbuf_t *rb, uint8_t value){ + // calculate next ptr pos + char* next = rb->writepos + 1; + char* readpos; + if(next >= rb->endptr){ + next = rb->startptr; + } + // check for space + ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ + readpos = rb->readpos; + } + if(next == readpos){ + return(1); // give up + } + *(rb->writepos) = value; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ + rb->writepos = next; + } + return(0); +} + +/* gets a value from the ringbuffer + * returns value on success, -1 on buffer empty + */ +int16_t ringbuf_get(ringbuf_t *rb){ + uint8_t value; + char* next; + char* writepos; + // calculate next ptr pos + next = rb->readpos + 1; + if(next >= rb->endptr){ + next = rb->startptr; + } + //check for empty + ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ + writepos = rb->writepos; + } + if(rb->readpos == writepos){ + return(-1); + } + value = *(rb->readpos); + ATOMIC_BLOCK(ATOMIC_RESTORESTATE){ + rb->readpos = next; + } + return(value); +} + + + + + diff --git a/firmware/slavechip/ringbuffer.h b/firmware/slavechip/ringbuffer.h new file mode 100644 index 0000000..5993691 --- /dev/null +++ b/firmware/slavechip/ringbuffer.h @@ -0,0 +1,12 @@ +#include + +typedef struct { + char* startptr; + char* endptr; // points beyond last element + char* readpos; + char* writepos; +} ringbuf_t; + + +void ringbuf_init(ringbuf_t* rb, char* buf, int size); +