You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
78 lines
1.7 KiB
78 lines
1.7 KiB
#include "ringbuffer.h"
|
|
|
|
#include <util/atomic.h>
|
|
|
|
|
|
/* 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);
|
|
}
|
|
|
|
|
|
|
|
|
|
|