#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); }