#ifndef RINGBUF_H #define RINGBUF_H #include #include // NOTE: buffer size must be 2^n and up to 255. size_mask should be 2^n - 1 due to using &(AND) instead of %(modulo) typedef struct { uint8_t *buffer; uint8_t head; uint8_t tail; uint8_t size_mask; } ringbuf_t; static inline void ringbuf_init(ringbuf_t *buf, uint8_t *array, uint8_t size); static inline int16_t ringbuf_get(ringbuf_t *buf); static inline bool ringbuf_put(ringbuf_t *buf, uint8_t data); static inline void ringbuf_write(ringbuf_t *buf, uint8_t data); static inline bool ringbuf_is_empty(ringbuf_t *buf); static inline bool ringbuf_is_full(ringbuf_t *buf); static inline void ringbuf_reset(ringbuf_t *buf); static inline void ringbuf_init(ringbuf_t *buf, uint8_t *array, uint8_t size) { buf->buffer = array; buf->head = 0; buf->tail = 0; buf->size_mask = size - 1; } static inline int16_t ringbuf_get(ringbuf_t *buf) { if (ringbuf_is_empty(buf)) return -1; uint8_t data = buf->buffer[buf->tail]; buf->tail++; buf->tail &= buf->size_mask; return data; } static inline bool ringbuf_put(ringbuf_t *buf, uint8_t data) { if (ringbuf_is_full(buf)) { return false; } buf->buffer[buf->head] = data; buf->head++; buf->head &= buf->size_mask; return true; } // this overrides data in buffer when it is full static inline void ringbuf_write(ringbuf_t *buf, uint8_t data) { buf->buffer[buf->head] = data; buf->head++; buf->head &= buf->size_mask; // eat tail: override data yet to be consumed if (buf->head == buf->tail) { buf->tail++; buf->tail &= buf->size_mask; } } static inline bool ringbuf_is_empty(ringbuf_t *buf) { return (buf->head == buf->tail); } static inline bool ringbuf_is_full(ringbuf_t *buf) { return (((buf->head + 1) & buf->size_mask) == buf->tail); } static inline void ringbuf_reset(ringbuf_t *buf) { buf->head = 0; buf->tail = 0; } #endif