]> git.friedersdorff.com Git - max/tmk_keyboard.git/commitdiff
core: Add ring buffer file
authortmk <hasu@tmk-kbd.com>
Wed, 25 Jul 2018 09:53:38 +0000 (18:53 +0900)
committertmk <hasu@tmk-kbd.com>
Sun, 23 Sep 2018 03:36:18 +0000 (12:36 +0900)
tmk_core/common/ringbuf.h [new file with mode: 0644]

diff --git a/tmk_core/common/ringbuf.h b/tmk_core/common/ringbuf.h
new file mode 100644 (file)
index 0000000..23bb41e
--- /dev/null
@@ -0,0 +1,73 @@
+#ifndef RINGBUF_H
+#define RINGBUF_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+// 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