-
Notifications
You must be signed in to change notification settings - Fork 28
/
RingBuf.h
143 lines (110 loc) · 3.77 KB
/
RingBuf.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
RingBuf.h - Library for implementing a simple Ring Buffer on Arduino boards.
Created by D. Aaron Wisner ([email protected])
January 17, 2015.
Released into the public domain.
*/
#ifndef RingBuf_h
#define RingBuf_h
#ifdef ARDUINO
#include <Arduino.h>
#else
#include <stdint.h>
#endif
#ifndef __cplusplus
#ifndef bool
#define bool uint8_t
#endif
#endif
#ifdef ARDUINO
#if defined(ARDUINO_ARCH_AVR)
#include <util/atomic.h>
#define RB_ATOMIC_START ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
#define RB_ATOMIC_END }
#elif defined(ARDUINO_ARCH_ESP8266) || defined(ARDUINO_ARCH_ESP32)
#ifndef __STRINGIFY
#define __STRINGIFY(a) #a
#endif
#ifndef xt_rsil
#define xt_rsil(level) (__extension__({uint32_t state; __asm__ __volatile__("rsil %0," __STRINGIFY(level) : "=a" (state)); state;}))
#endif
#ifndef xt_wsr_ps
#define xt_wsr_ps(state) __asm__ __volatile__("wsr %0,ps; isync" :: "a" (state) : "memory")
#endif
#define RB_ATOMIC_START do { uint32_t _savedIS = xt_rsil(15) ;
#define RB_ATOMIC_END xt_wsr_ps(_savedIS); } while(0);
#else
#define RB_ATOMIC_START {
#define RB_ATOMIC_END }
#warning "This library only fully supports AVR and ESP8266 Boards."
#warning "Operations on the buffer in ISRs are not safe!"
#endif
#else
#define RB_ATOMIC_START {
#define RB_ATOMIC_END }
#warning "Operations on the buffer in ISRs are not safe!"
#warning "Impliment RB_ATOMIC_START and RB_ATOMIC_END macros for safe ISR operation!"
#endif
typedef struct RingBuf RingBuf;
typedef struct RingBuf
{
// Invariant: end and start is always in bounds
unsigned char *buf;
unsigned int len, size, start, end, elements;
// Private:
int (*next_end_index) (RingBuf*);
int (*incr_end_index) (RingBuf*);
int (*incr_start_index) (RingBuf*);
//public:
// Returns true if full
bool (*isFull) (RingBuf*);
// Returns true if empty
bool (*isEmpty) (RingBuf*);
// Returns number of elemnts in buffer
unsigned int (*numElements)(RingBuf*);
// Add Event, Returns index where added in buffer, -1 on full buffer
int (*add) (RingBuf*, const void*);
// Returns pointer to nth element, NULL when nth element is empty
void *(*peek) (RingBuf*, unsigned int);
// Removes element and copies it to location pointed to by void *
// Returns pointer passed in, NULL on empty buffer
void *(*pull) (RingBuf*, void *);
} RingBuf;
#ifdef __cplusplus
extern "C" {
#endif
RingBuf *RingBuf_new(int size, int len);
int RingBuf_init(RingBuf *self, int size, int len);
int RingBuf_delete(RingBuf *self);
int RingBufNextEndIndex(RingBuf *self);
int RingBufIncrEnd(RingBuf *self);
int RingBufIncrStart(RingBuf *self);
int RingBufAdd(RingBuf *self, const void *object);
void *RingBufPeek(RingBuf *self, unsigned int num);
void *RingBufPull(RingBuf *self, void *object);
bool RingBufIsFull(RingBuf *self);
bool RingBufIsEmpty(RingBuf *self);
unsigned int RingBufNumElements(RingBuf *self);
#ifdef __cplusplus
}
#endif
// For those of you who cant live without pretty C++ objects....
#ifdef __cplusplus
class RingBufC
{
public:
RingBufC(int size, int len) { buf = RingBuf_new(size, len); }
~RingBufC() { RingBuf_delete(buf); }
bool isFull() { return RingBufIsFull(buf); }
bool isEmpty() { return RingBufIsEmpty(buf); }
unsigned int numElements() { return RingBufNumElements(buf); }
unsigned int add(const void *object) { return RingBufAdd(buf, object); }
void *peek(unsigned int num) { return RingBufPeek(buf, num); }
void *pull(void *object) { return RingBufPull(buf, object); }
// Use this to check if memory allocation failed
bool allocFailed() { return !buf; }
private:
RingBuf *buf;
};
#endif
#endif