// can handle one buffer for a start. // later make it reentrant and manage multiple buffers! // todo: syncing access to buffer. #define FOOLOS_MODULE_NAME "ringbuffer" #include "lib/bool/bool.h" #include "lib/logger/log.h" static volatile int front; static volatile int back; static volatile int size; #define RINGBUFFER_SIZE 10 static volatile char buf[RINGBUFFER_SIZE]; bool ringbuffer_selftest(); void ringbuffer_init() { size=RINGBUFFER_SIZE; front=size-1; back=size-1; // ringbuffer_selftest(); // while(1); } bool ringbuffer_put(char c) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"put wants lock)"); lock_spin(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"locked by put)"); if((back-1+size)%size==front) { lock_release(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"unlocked by put)"); return false; } buf[back]=c; log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"put %d %d (%c)", back, front,c); back--; back+=size; back%=size; lock_release(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"unlocked by put)"); return true; } bool ringbuffer_get(char *c) { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"get wants lock)"); lock_spin(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"locked by get)"); if(front==back) { lock_release(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"unlocked by get)"); return false; } *c=buf[front]; log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"get %d %d (%c)", back, front,*c); front--; front+=size; front%=size; lock_release(3); log(FOOLOS_MODULE_NAME,FOOLOS_LOG_FINE,"unlocked by get)"); return true; } bool ringbuffer_selftest() { log(FOOLOS_MODULE_NAME,FOOLOS_LOG_INFO,"ringbuffer selftest"); char c; ringbuffer_put('a'); ringbuffer_put('b'); ringbuffer_put('c'); ringbuffer_put('d'); ringbuffer_put('e'); ringbuffer_get(&c); ringbuffer_get(&c); ringbuffer_get(&c); ringbuffer_get(&c); ringbuffer_get(&c); ringbuffer_get(&c); ringbuffer_get(&c); }