ENTS-tock
Environmental NeTworked Sensor firmware on Tock OS
Loading...
Searching...
No Matches
fifo.c
Go to the documentation of this file.
1#include "fifo.h"
2
4static const uint16_t FRAM_BUFFER_SIZE =
6
7static const uint16_t FRAM_BUFFER_READ_ADDR = 0x06F0; // 1776
8static const uint16_t FRAM_BUFFER_WRITE_ADDR = 0x06F2; // 1778
9static const uint16_t FRAM_BUFFER_LEN_ADDR = 0x06F4; // 1780
10
11// head and tail
12static uint16_t read_addr = 0;
13static uint16_t write_addr = 0;
14static uint16_t buffer_len = 0;
15
22static inline void update_addr(uint16_t* addr, const uint16_t num_bytes) {
23 *addr = (*addr + num_bytes) % FRAM_BUFFER_SIZE;
24}
25
35static uint16_t get_remaining_space(void) {
36 uint16_t space_used = 0;
37 if (write_addr > read_addr) {
38 space_used = write_addr - read_addr;
39 } else if (write_addr < read_addr) {
40 space_used = FRAM_BUFFER_SIZE - (read_addr - write_addr);
41 } else {
42 // if anything is stored in buffer than entire capacity is used
43 // otherwise buffer is empty and all free space is available
44 if (buffer_len > 0) {
45 space_used = FRAM_BUFFER_SIZE;
46 } else {
47 space_used = 0;
48 }
49 }
50
51 uint16_t remaining_space = FRAM_BUFFER_SIZE - space_used;
52 return remaining_space;
53}
54
55fram_status fifo_put(const uint8_t* data, const uint8_t num_bytes) {
56 // check remaining space
57 if (num_bytes > get_remaining_space()) {
58 return FRAM_BUFFER_FULL;
59 }
60
61 fram_status status = FRAM_OK;
62
63 // write single byte length to buffer
64 status = fram_write(write_addr, &num_bytes, 1);
65 if (status != FRAM_OK) {
66 return status;
67 }
68 update_addr(&write_addr, 1);
69
70 // Write data to FRAM circular buffer
71 // if the data must wraparound, then make two writes
72 if (write_addr + num_bytes > (FRAM_BUFFER_END + 1)) {
73 // write up to the buffer end
74 size_t num_bytes_first_half = (FRAM_BUFFER_END + 1) - write_addr;
75 status = fram_write(write_addr, data, num_bytes_first_half);
76 if (status != FRAM_OK) {
77 return status;
78 }
79 update_addr(&write_addr, num_bytes_first_half);
80 // write from the buffer start
81 status = fram_write(write_addr, data + num_bytes_first_half,
82 num_bytes - num_bytes_first_half);
83 if (status != FRAM_OK) {
84 return status;
85 }
86 update_addr(&write_addr, num_bytes - num_bytes_first_half);
87 } else {
88 status = fram_write(write_addr, data, num_bytes);
89 if (status != FRAM_OK) {
90 return status;
91 }
92 update_addr(&write_addr, num_bytes);
93 }
94
95 // increment buffer length
96 ++buffer_len;
97
99 return FRAM_OK;
100}
101
102fram_status fifo_get(uint8_t* data, uint8_t* len) {
103 // Check if buffer is empty
104 if (buffer_len == 0) {
105 return FRAM_BUFFER_EMPTY;
106 }
107
108 fram_status status = FRAM_OK;
109 status = fram_read(read_addr, 1, len);
110
111 if (status != FRAM_OK) {
112 return status;
113 }
114 update_addr(&read_addr, 1);
115
116 // Read data from FRAM circular buffer
117 // if the data must wraparound, then make two reads
118 if (read_addr + *len > (FRAM_BUFFER_END + 1)) {
119 // read up to the buffer end
120 size_t len_first_half = (FRAM_BUFFER_END + 1) - read_addr;
121 status = fram_read(read_addr, len_first_half, data);
122 if (status != FRAM_OK) {
123 return status;
124 }
125 update_addr(&read_addr, len_first_half);
126 // read from the buffer start
127 status = fram_read(read_addr, *len - len_first_half, data + len_first_half);
128 if (status != FRAM_OK) {
129 return status;
130 }
131 update_addr(&read_addr, *len - len_first_half);
132 } else {
133 status = fram_read(read_addr, *len, data);
134 if (status != FRAM_OK) {
135 return status;
136 }
137 update_addr(&read_addr, *len);
138 }
139
140 // Decrement buffer length
141 --buffer_len;
142
144 return FRAM_OK;
145}
146
147fram_status fifo_peek(size_t idx, uint8_t* data, uint8_t* len) {
148 // Check if buffer is empty
149 if (buffer_len == 0) {
150 return FRAM_BUFFER_EMPTY;
151 }
152 if (idx >= buffer_len) {
153 return FRAM_OUT_OF_RANGE;
154 }
155
156 fram_status status = FRAM_OK;
157 uint16_t temp_read_addr = read_addr;
158
159 // advance to idx
160 for (size_t i = 0; i < idx; i++) {
161 uint8_t temp_len;
162 status = fram_read(temp_read_addr, 1, &temp_len);
163 if (status != FRAM_OK) {
164 return status;
165 }
166 update_addr(&temp_read_addr, 1 + temp_len);
167 }
168
169 // read length
170 status = fram_read(temp_read_addr, 1, len);
171 if (status != FRAM_OK) {
172 return status;
173 }
174 update_addr(&temp_read_addr, 1);
175
176 // read data
177 status = fram_read(temp_read_addr, *len, data);
178 if (status != FRAM_OK) {
179 return status;
180 }
181
182 // Read data from FRAM circular buffer
183 // if the data must wraparound, then make two reads
184 if (temp_read_addr + *len > (FRAM_BUFFER_END + 1)) {
185 // read up to the buffer end
186 size_t len_first_half = (FRAM_BUFFER_END + 1) - temp_read_addr;
187 status = fram_read(temp_read_addr, len_first_half, data);
188 if (status != FRAM_OK) {
189 return status;
190 }
191 update_addr(&temp_read_addr, len_first_half);
192 // read from the buffer start
193 status =
194 fram_read(temp_read_addr, *len - len_first_half, data + len_first_half);
195 if (status != FRAM_OK) {
196 return status;
197 }
198 update_addr(&temp_read_addr, *len - len_first_half);
199 } else {
200 status = fram_read(temp_read_addr, *len, data);
201 if (status != FRAM_OK) {
202 return status;
203 }
204 update_addr(&temp_read_addr, *len);
205 }
206
207 return FRAM_OK;
208}
209
211 // Check if buffer is empty
212 if (buffer_len == 0) {
213 return FRAM_BUFFER_EMPTY;
214 }
215
216 fram_status status;
217 uint8_t len;
218
219 // read length
220 status = fram_read(read_addr, 1, &len);
221 if (status != FRAM_OK) {
222 return status;
223 }
224 update_addr(&read_addr, 1 + len);
225
226 // Decrement buffer length
227 --buffer_len;
228
230 return FRAM_OK;
231}
232
233uint16_t fifo_buffer_len(void) { return buffer_len; }
234
236 // Set read and write addresses to their default values
237 read_addr = FRAM_BUFFER_START;
238 write_addr = FRAM_BUFFER_START;
239
240 // reset buffer len
241 buffer_len = 0;
243
244 return FRAM_OK;
245}
246
248 uint8_t buffer[2] = {};
249
250 buffer[1] = read_addr >> 8;
251 buffer[0] = read_addr & 0xFF;
252
253 // Save read_addr
254 fram_status status =
255 fram_write(FRAM_BUFFER_READ_ADDR, buffer, sizeof(read_addr));
256 if (status != FRAM_OK) {
257 // APP_PRINTF("Failed to save read address. FRAM Status: %d\n", status);
258 return status;
259 }
260
261 buffer[1] = write_addr >> 8;
262 buffer[0] = write_addr & 0xFF;
263
264 // Save write_addr
265 status = fram_write(FRAM_BUFFER_WRITE_ADDR, buffer, sizeof(write_addr));
266 if (status != FRAM_OK) {
267 // APP_PRINTF("Failed to save write address. FRAM Status: %d\n", status);
268 return status;
269 }
270
271 buffer[1] = buffer_len >> 8;
272 buffer[0] = buffer_len & 0xFF;
273
274 // Save buffer_len
275 status = fram_write(FRAM_BUFFER_LEN_ADDR, buffer, sizeof(buffer_len));
276 if (status != FRAM_OK) {
277 // APP_PRINTF("Failed to save buffer length. FRAM Status: %d\n", status);
278 return status;
279 }
280
281 // Print a single message summarizing the saved buffer state
282 // APP_PRINTF(
283 // "Buffer State Saved Successfully. Read Address: 0x%04X (%d), Write "
284 // "Address: 0x%04X (%d), Buffer Length: %d\n",
285 // read_addr, read_addr, write_addr, write_addr, buffer_len);
286
287 return status;
288}
289
291 fram_status status = FRAM_OK;
292
293 uint8_t buffer[2] = {};
294
295 // Load read_addr and print each byte
296 status = fram_read(FRAM_BUFFER_READ_ADDR, sizeof(read_addr), buffer);
297 if (status != FRAM_OK) return status;
298
299 read_addr = 0;
300 read_addr = (buffer[1] << 8) | buffer[0];
301 // APP_PRINTF("Loaded Read Address: 0x%02X 0x%02X (%d)\n", ((uint8_t
302 // *)read_addr)[0],
303 // ((uint8_t *)read_addr)[1], *read_addr);
304
305 // Load write_addr and print each byte
306 status = fram_read(FRAM_BUFFER_WRITE_ADDR, sizeof(write_addr), buffer);
307 if (status != FRAM_OK) return status;
308 // APP_PRINTF("Loaded Write Address: 0x%02X 0x%02X (%d)\n",
309 // ((uint8_t *)write_addr)[0], ((uint8_t *)write_addr)[1], *write_addr);
310
311 write_addr = 0;
312 write_addr = (buffer[1] << 8) | buffer[0];
313
314 // Load buffer_len and print each byte
315 status = fram_read(FRAM_BUFFER_LEN_ADDR, sizeof(buffer_len), buffer);
316 if (status != FRAM_OK) return status;
317 // APP_PRINTF("Loaded Buffer Length: 0x%02X 0x%02X (%d)\n",
318 // ((uint8_t *)buffer_len)[0], ((uint8_t *)buffer_len)[1], *buffer_len);
319
320 buffer_len = 0;
321 buffer_len = (buffer[1] << 8) | buffer[0];
322
323 return FRAM_OK;
324}
325
328 if (status != FRAM_OK) {
329 // APP_PRINTF("Failed to load FIFO state. FRAM Status: %d\n", status);
330 // If loading the buffer state fails, assume it's an empty state
331 // APP_PRINTF("Initialized to empty buffer state.\n");
332 return fifo_buffer_clear();
333 } else {
334 if (read_addr == FRAM_BUFFER_START && write_addr == FRAM_BUFFER_START &&
335 buffer_len == 0) {
336 // APP_PRINTF("Buffer is empty or freshly initialized.\n");
337 return FRAM_OK;
338 } else {
339 // APP_PRINTF("Buffer contains data. Ready to resume operations.\n");
340 return FRAM_OK;
341 }
342 }
343 return FRAM_OK;
344}
345
346int fifo_size(void) { return FRAM_BUFFER_SIZE; }
const char data[]
uint8_t buffer[32]
uint8_t i
Circular buffer as FIFO data structure for buffering measurements.
fram_status fifo_get(uint8_t *data, uint8_t *len)
Reads a measurement from the queue.
Definition fifo.c:102
#define FRAM_BUFFER_END
Definition fifo.h:68
int fifo_size(void)
Gets the total number of bytes in the buffer.
Definition fifo.c:346
#define FRAM_BUFFER_START
Definition fifo.h:63
uint16_t fifo_buffer_len(void)
Get the current number of measurements stored in the buffer.
Definition fifo.c:233
fram_status fifo_buffer_clear(void)
Clears the buffer.
Definition fifo.c:235
fram_status fifo_put(const uint8_t *data, const uint8_t num_bytes)
Puts a measurement into the circular buffer.
Definition fifo.c:55
fram_status fifo_drop(void)
Drops the next measurement in the buffer.
Definition fifo.c:210
fram_status fifo_save_buffer_state(void)
Saves the buffer state (read address, write address, and buffer length) to FRAM.
Definition fifo.c:247
fram_status fifo_peek(size_t idx, uint8_t *data, uint8_t *len)
Peeks at the next measurement in the buffer without removing it.
Definition fifo.c:147
fram_status fifo_init(void)
Initializes the buffer.
Definition fifo.c:326
fram_status fifo_load_buffer_state(void)
Loads the buffer state (read address, write address, and buffer length) from FRAM.
Definition fifo.c:290
fram_status fram_write(fram_addr addr, const uint8_t *data, size_t len)
Write bytes at the given address.
Definition fram.c:20
fram_status
Definition fram.h:32
fram_status fram_read(fram_addr addr, size_t len, uint8_t *data)
Read bytes at the given address.
Definition fram.c:28
@ FRAM_BUFFER_EMPTY
Definition fram.h:37
@ FRAM_OK
Definition fram.h:33
@ FRAM_BUFFER_FULL
Definition fram.h:36
@ FRAM_OUT_OF_RANGE
Definition fram.h:35