-
Notifications
You must be signed in to change notification settings - Fork 201
Expand file tree
/
Copy pathCircularBuffer.h
More file actions
188 lines (159 loc) · 3.63 KB
/
CircularBuffer.h
File metadata and controls
188 lines (159 loc) · 3.63 KB
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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* CircularBuffer.h
*
* This file is part of Mozzi.
*
* Copyright 2014-2024 Tim Barrass and the Mozzi Team
*
* Mozzi is licensed under the GNU Lesser General Public Licence (LGPL) Version 2.1 or later.
*
*/
/*
Modified from https://en.wikipedia.org/wiki/Circular_buffer
Mirroring version
On 18 April 2014, the simplified version on the Wikipedia page for power of 2 sized buffers
doesn't work - cbIsEmpty() returns true whether the buffer is full or empty.
April 2025: modified for different buffer sizes under the suggestion
of Meebleeps (https://github.com/sensorium/Mozzi/issues/281)
*/
/** Circular buffer object. Has a fixed number of cells, set by BUFFER_SIZE.
@tparam ITEM_TYPE the kind of data to store, eg. int, int8_t etc.
@tparam BUFFER_SIZE the size of the circular buffer
*/
template <class ITEM_TYPE, int16_t BUFFER_SIZE>
class CircularBuffer
{
public:
/** Constructor
*/
CircularBuffer(): start(0),end(0),s_msb(0),e_msb(0)
{
}
inline
bool isFull() {
return end == start && e_msb != s_msb;
}
inline
bool isEmpty() {
return end == start && e_msb == s_msb;
}
inline
void write(ITEM_TYPE in) {
items[end] = in;
//if (isFull()) cbIncrStart(); /* full, overwrite moves start pointer */
cbIncrEnd();
}
inline
ITEM_TYPE read() {
ITEM_TYPE out = items[start];
cbIncrStart();
return out;
}
inline
unsigned long count() {
return (num_buffers_read << COUNT_LSHIFT) + start;
}
inline
ITEM_TYPE * address() {
return items;
}
private:
ITEM_TYPE items[BUFFER_SIZE];
uint8_t start; /* index of oldest itement */
uint8_t end; /* index at which to write new itement */
uint8_t s_msb;
uint8_t e_msb;
unsigned long num_buffers_read;
static constexpr unsigned long COUNT_LSHIFT =
(BUFFER_SIZE == 256) ? 8 :
(BUFFER_SIZE == 128) ? 7 :
(BUFFER_SIZE == 64) ? 6 :
(BUFFER_SIZE == 32) ? 5 :
(BUFFER_SIZE == 16) ? 4 :
(BUFFER_SIZE == 8) ? 3 :
(BUFFER_SIZE == 4) ? 2 :
(BUFFER_SIZE == 2) ? 1 : 0;
inline
void cbIncrStart() {
start++;
if (start == BUFFER_SIZE)
{
start = 0;
s_msb ^= 1;
num_buffers_read++;
}
}
inline
void cbIncrEnd()
{
end++;
if (end == BUFFER_SIZE)
{
end = 0;
e_msb ^= 1;
}
}
};
/** Circular buffer object. Specialization for size of 256.
Note: Lot of duplication but C++ does not allow for specialization of the
function member only (partial specialization).
@tparam ITEM_TYPE the kind of data to store, eg. int, int8_t etc.
*/
template <class ITEM_TYPE>
class CircularBuffer<ITEM_TYPE, 256>
{
public:
/** Constructor
*/
CircularBuffer(): start(0),end(0),s_msb(0),e_msb(0)
{
}
inline
bool isFull() {
return end == start && e_msb != s_msb;
}
inline
bool isEmpty() {
return end == start && e_msb == s_msb;
}
inline
void write(ITEM_TYPE in) {
items[end] = in;
//if (isFull()) cbIncrStart(); /* full, overwrite moves start pointer */
cbIncrEnd();
}
inline
ITEM_TYPE read() {
ITEM_TYPE out = items[start];
cbIncrStart();
return out;
}
inline
unsigned long count() {
return (num_buffers_read << 8) + start;
}
inline
ITEM_TYPE * address() {
return items;
}
private:
ITEM_TYPE items[256];
uint8_t start; /* index of oldest itement */
uint8_t end; /* index at which to write new itement */
uint8_t s_msb;
uint8_t e_msb;
unsigned long num_buffers_read;
inline
void cbIncrStart() {
start++;
if (start == 0) {
s_msb ^= 1;
num_buffers_read++;
}
}
inline
void cbIncrEnd() {
end++;
if (end == 0) e_msb ^= 1;
}
};