px-fwlib 0.10.0
Cross-platform embedded library and documentation for 8/16/32-bit microcontrollers generated with Doxygen 1.9.2
px_ring_buf.c
1/* =============================================================================
2 ____ ___ ____ ___ _ _ ___ __ __ ___ __ __ TM
3 | _ \ |_ _| / ___| / _ \ | \ | | / _ \ | \/ | |_ _| \ \/ /
4 | |_) | | | | | | | | | | \| | | | | | | |\/| | | | \ /
5 | __/ | | | |___ | |_| | | |\ | | |_| | | | | | | | / \
6 |_| |___| \____| \___/ |_| \_| \___/ |_| |_| |___| /_/\_\
7
8 Copyright (c) 2006 Pieter Conradie <https://piconomix.com>
9
10 License: MIT
11 https://github.com/piconomix/px-fwlib/blob/master/LICENSE.md
12
13 Title: px_ring_buf.h : FIFO ring buffer
14 Author(s): Pieter Conradie
15 Creation Date: 2008-08-06
16
17============================================================================= */
18
19/* _____STANDARD INCLUDES____________________________________________________ */
20
21/* _____PROJECT INCLUDES_____________________________________________________ */
22#include "px_ring_buf.h"
23#include "px_log.h"
24
25/* _____LOCAL DEFINITIONS____________________________________________________ */
26PX_LOG_NAME("px_ring_buf");
27
28/* _____MACROS_______________________________________________________________ */
29
30/* _____GLOBAL VARIABLES_____________________________________________________ */
31
32/* _____LOCAL VARIABLES______________________________________________________ */
33
34/* _____LOCAL FUNCTION PROTOTYPES____________________________________________ */
35
36/* _____LOCAL FUNCTIONS______________________________________________________ */
37static inline px_ring_buf_idx_t px_ring_buf_idx_next(const px_ring_buf_t * px_ring_buf,
39{
40 if(++idx >= px_ring_buf->buf_size)
41 {
42 // Wrap index to start of buffer
43 idx = 0;
44 }
45 return idx;
46}
47
48/* _____GLOBAL FUNCTIONS_____________________________________________________ */
50 uint8_t * buf,
51 px_ring_buf_idx_t buf_size)
52{
53 // Initialise the ring buffer structure to be empty
54 px_ring_buf->buf = buf;
55 px_ring_buf->buf_size = buf_size;
56 px_ring_buf->idx_wr = 0;
57 px_ring_buf->idx_rd = 0;
58}
59
60bool px_ring_buf_is_empty(const px_ring_buf_t * px_ring_buf)
61{
62 return (px_ring_buf->idx_rd == px_ring_buf->idx_wr);
63}
64
65bool px_ring_buf_is_full(const px_ring_buf_t * px_ring_buf)
66{
67 return (px_ring_buf_idx_next(px_ring_buf, px_ring_buf->idx_wr) == px_ring_buf->idx_rd);
68}
69
70void px_ring_buf_flush(px_ring_buf_t * px_ring_buf, size_t nr_of_bytes)
71{
72 px_ring_buf_idx_t idx_rd;
73
74 // Flush everything?
75 if(nr_of_bytes == 0)
76 {
77 // Yes
78 px_ring_buf->idx_rd = px_ring_buf->idx_wr;
79 return;
80 }
81
82 // Try to flush specified number of bytes
83 idx_rd = px_ring_buf->idx_rd;
84 while(nr_of_bytes != 0)
85 {
86 // Buffer empty?
87 if(idx_rd == px_ring_buf->idx_wr)
88 {
89 // Yes
90 break;
91 }
92 // Advance index
93 idx_rd = px_ring_buf_idx_next(px_ring_buf, idx_rd);
94 // Next byte
95 nr_of_bytes--;
96 }
97
98 // Update read index
99 px_ring_buf->idx_rd = idx_rd;
100}
101
103 const uint8_t data)
104{
105 px_ring_buf_idx_t idx_wr = px_ring_buf->idx_wr;
106
107 // Buffer full?
108 if(px_ring_buf_idx_next(px_ring_buf, idx_wr) == px_ring_buf->idx_rd)
109 {
110 // Yes. Discard byte
111 return false;
112 }
113
114 // Add data to buffer
115 px_ring_buf->buf[idx_wr] = data;
116 // Advance index
117 idx_wr = px_ring_buf_idx_next(px_ring_buf, idx_wr);
118 // Update write index
119 px_ring_buf->idx_wr = idx_wr;
120
121 return true;
122}
123
125 const void * data,
126 size_t nr_of_bytes)
127{
128 px_ring_buf_idx_t idx_wr = px_ring_buf->idx_wr;
129 px_ring_buf_idx_t bytes_written = 0;
130 uint8_t * data_u8 = (uint8_t *)data;
131
132 while(nr_of_bytes != 0)
133 {
134 // Buffer full?
135 if(px_ring_buf_idx_next(px_ring_buf, idx_wr) == px_ring_buf->idx_rd)
136 {
137 // Yes. Discard rest of data
138 break;
139 }
140 // Add data to buffer
141 px_ring_buf->buf[idx_wr] = *data_u8++;
142 // Advance index
143 idx_wr = px_ring_buf_idx_next(px_ring_buf, idx_wr);
144 // Next byte
145 bytes_written++;
146 nr_of_bytes--;
147 }
148
149 // Update write index
150 px_ring_buf->idx_wr = idx_wr;
151
152 return bytes_written;
153}
154
156 uint8_t * data)
157{
158 px_ring_buf_idx_t idx_rd = px_ring_buf->idx_rd;
159
160 // Buffer empty?
161 if(idx_rd == px_ring_buf->idx_wr)
162 {
163 // Yes
164 return false;
165 }
166 // Fetch data
167 *data = px_ring_buf->buf[idx_rd];
168 // Advance index
169 idx_rd = px_ring_buf_idx_next(px_ring_buf, idx_rd);
170 // Update read index
171 px_ring_buf->idx_rd = idx_rd;
172
173 return true;
174}
175
177 void * data,
178 size_t nr_of_bytes)
179{
180 px_ring_buf_idx_t idx_rd = px_ring_buf->idx_rd;
181 px_ring_buf_idx_t bytes_read = 0;
182 uint8_t * data_u8 = (uint8_t *)data;
183
184 while(nr_of_bytes != 0)
185 {
186 // Buffer empty?
187 if(idx_rd == px_ring_buf->idx_wr)
188 {
189 // Yes
190 break;
191 }
192 // Fetch data
193 *data_u8++ = px_ring_buf->buf[idx_rd];
194 // Advance index
195 idx_rd = px_ring_buf_idx_next(px_ring_buf, idx_rd);
196 // Next byte
197 bytes_read++;
198 nr_of_bytes--;
199 }
200
201 // Update read index
202 px_ring_buf->idx_rd = idx_rd;
203
204 return bytes_read;
205}
206
208 void * data,
209 size_t nr_of_bytes)
210{
211 px_ring_buf_idx_t idx_peek = px_ring_buf->idx_rd;
212 px_ring_buf_idx_t bytes_read = 0;
213 uint8_t * data_u8 = (uint8_t *)data;
214
215 while(nr_of_bytes != 0)
216 {
217 // Buffer empty?
218 if(idx_peek == px_ring_buf->idx_wr)
219 {
220 // Yes
221 break;
222 }
223 // Fetch data
224 *data_u8++ = px_ring_buf->buf[idx_peek];
225 // Advance index
226 idx_peek = px_ring_buf_idx_next(px_ring_buf, idx_peek);
227 // Next byte
228 bytes_read++;
229 nr_of_bytes--;
230 }
231
232 return bytes_read;
233}
234
236{
237 px_ring_buf_idx_t count_used;
238 px_ring_buf_idx_t idx_wr = px_ring_buf->idx_wr;
239 px_ring_buf_idx_t idx_rd = px_ring_buf->idx_rd;
240
241 // Buffer empty?
242 if(idx_rd == idx_wr)
243 {
244 count_used = 0;
245 }
246 // |________xxxxxxxxx___________|
247 // R>>>>>>>>W
248 else if(idx_rd < idx_wr)
249 {
250 count_used = idx_wr - idx_rd;
251 }
252 // |xxxxxx___________________xxx|
253 // >>>>>>W R>>
254 else
255 {
256 count_used = px_ring_buf->buf_size - idx_rd + idx_wr;
257 }
258
259 return count_used;
260}
261
263{
264 px_ring_buf_idx_t count_free;
265 px_ring_buf_idx_t idx_wr = px_ring_buf->idx_wr;
266 px_ring_buf_idx_t idx_rd = px_ring_buf->idx_rd;
267
268 // Buffer empty?
269 if(idx_rd == idx_wr)
270 {
271 count_free = px_ring_buf->buf_size - 1;
272 }
273 // |________xxxxxxxxx___________|
274 // R>>>>>>>>W
275 else if(idx_rd < idx_wr)
276 {
277 count_free = px_ring_buf->buf_size - 1 - idx_wr + idx_rd;
278 }
279 // |xxxxxx___________________xxx|
280 // >>>>>>W R>>
281 else
282 {
283 count_free = idx_rd - idx_wr - 1;
284 }
285
286 return count_free;
287}
288
290{
291 PX_LOG_TRACE("WR=%u\n", px_ring_buf->idx_wr);
292 PX_LOG_TRACE("RD=%u\n", px_ring_buf->idx_rd);
293 PX_LOG_TRACE("Size=%u\n", px_ring_buf->buf_size);
294 PX_LOG_TRACE("Used=%u\n", px_ring_buf_get_count_used(px_ring_buf));
295 PX_LOG_TRACE("Free=%u\n", px_ring_buf_get_count_free(px_ring_buf));
296}
297
#define PX_LOG_TRACE(format,...)
Macro to output a user format string if PX_LOG=1.
Definition: px_log.h:458
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
Definition: px_log.h:349
px_ring_buf_idx_t buf_size
Size of fixed-size buffer.
Definition: px_ring_buf.h:109
volatile px_ring_buf_idx_t idx_wr
Index that is next open position to write to in the buffer.
Definition: px_ring_buf.h:110
volatile px_ring_buf_idx_t idx_rd
Index to the next byte to be read from the buffer.
Definition: px_ring_buf.h:111
uint8_t * buf
Pointer to fixed-size buffer.
Definition: px_ring_buf.h:108
px_ring_buf_idx_t px_ring_buf_wr(px_ring_buf_t *px_ring_buf, const void *data, size_t nr_of_bytes)
Write (store) data in the ring buffer.
Definition: px_ring_buf.c:124
void px_ring_buf_init(px_ring_buf_t *px_ring_buf, uint8_t *buf, px_ring_buf_idx_t buf_size)
Initialize the ring buffer.
Definition: px_ring_buf.c:49
bool px_ring_buf_is_full(const px_ring_buf_t *px_ring_buf)
See if the ring buffer is full.
Definition: px_ring_buf.c:65
uint16_t px_ring_buf_idx_t
Ring buffer index size definition.
Definition: px_ring_buf.h:102
px_ring_buf_idx_t px_ring_buf_peek(px_ring_buf_t *px_ring_buf, void *data, size_t nr_of_bytes)
Peek data from the ring buffer, without advancing the read pointer.
Definition: px_ring_buf.c:207
px_ring_buf_idx_t px_ring_buf_get_count_used(px_ring_buf_t *px_ring_buf)
Get number of bytes stored in the buffer.
Definition: px_ring_buf.c:235
bool px_ring_buf_rd_u8(px_ring_buf_t *px_ring_buf, uint8_t *data)
Read (retrieve) a byte from the ring buffer.
Definition: px_ring_buf.c:155
bool px_ring_buf_wr_u8(px_ring_buf_t *px_ring_buf, const uint8_t data)
Write (store) a byte in the ring buffer.
Definition: px_ring_buf.c:102
px_ring_buf_idx_t px_ring_buf_get_count_free(px_ring_buf_t *px_ring_buf)
Get number of free bytes available in buffer.
Definition: px_ring_buf.c:262
px_ring_buf_idx_t px_ring_buf_rd(px_ring_buf_t *px_ring_buf, void *data, size_t nr_of_bytes)
Read (retrieve) data from the ring buffer.
Definition: px_ring_buf.c:176
bool px_ring_buf_is_empty(const px_ring_buf_t *px_ring_buf)
See if the ring buffer is empty.
Definition: px_ring_buf.c:60
void px_ring_buf_flush(px_ring_buf_t *px_ring_buf, size_t nr_of_bytes)
Removed data from ring buffer.
Definition: px_ring_buf.c:70
void px_ring_buf_log_report(px_ring_buf_t *px_ring_buf)
Report status of ring buffer.
Definition: px_ring_buf.c:289
Ring buffer structure.
Definition: px_ring_buf.h:107