Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
circular_buffer.c
Go to the documentation of this file.
1/*
2 * General purpose circular buffer
3 *
4 * Copyright (C) 2021 Fabien-B <fabien-b@github.com>
5 *
6 * This file is part of paparazzi. See LICENCE file.
7 */
8
9#include "circular_buffer.h"
10#include <string.h>
11
12
13void circular_buffer_init(struct circular_buffer *cb, uint8_t *buffer, size_t len)
14{
15 cb->_buf = buffer;
16 cb->_buf_len = len;
17 cb->read_offset = 0;
18 cb->write_offset = 0;
19}
20
21
22int circular_buffer_get(struct circular_buffer *cb, uint8_t *buf, size_t len)
23{
24 // buffer empty
25 if (cb->read_offset == cb->write_offset) { return CIR_ERROR_NO_MSG; }
26 // LEN| MSG...| LEN | MSG...
27 uint16_t msg_len_p = cb->_buf[cb->read_offset] | (cb->_buf[(cb->read_offset + 1) % cb->_buf_len] << 8);
28 // output buffer too small
29 if (len < msg_len_p) { return CIR_ERROR_BUFFER_TOO_SMALL; }
30
31 size_t end_offset = cb->read_offset + msg_len_p + 2;
32 if (end_offset >= cb->_buf_len) {
33 end_offset -= cb->_buf_len;
34 }
35 uint8_t *start = cb->_buf + ((cb->read_offset + 2) % cb->_buf_len);
36
37 // No wrapping can be read in one go
38 if (end_offset >= ((cb->read_offset + 2) % cb->_buf_len)) {
39 memcpy(buf, start, msg_len_p);
40 } else {
41 size_t len1 = cb->_buf_len - (cb->read_offset + 2);
42 size_t len2 = len - len1;
43 memcpy(buf, start, len1);
44 memcpy(buf + len1, cb->_buf, len2);
45 }
46
47 int nb_bytes = msg_len_p;
49 return nb_bytes;
50}
51
52int circular_buffer_put(struct circular_buffer *cb, const uint8_t *buf, size_t len)
53{
54 size_t available = circular_buffer_available(cb);
55
56 if (len > available) {
58 }
59
60 size_t end_offset = cb->write_offset + len + 2;
61 if (end_offset >= cb->_buf_len) {
62 end_offset -= cb->_buf_len;
63 }
64
65
66 // Write the length and wrap around if needed
67 cb->_buf[cb->write_offset] = len & 0xFF;
68 cb->_buf[(cb->write_offset + 1) % cb->_buf_len] = (len >> 8) & 0xFF;
69
70 // Write the date no wrapping needed
71 if (end_offset > cb->write_offset) {
72 memcpy(cb->_buf + cb->write_offset + 2, buf, len);
73 }
74 // Wrapping data partially
75 else if ((cb->write_offset + 2) < cb->_buf_len) {
76 size_t len1 = cb->_buf_len - (cb->write_offset + 2);
77 size_t len2 = len - len1;
78 memcpy(cb->_buf + cb->write_offset + 2, buf, len1);
79 memcpy(cb->_buf, buf + len1, len2);
80 }
81 // Only data is wrapped (starting at the beginning or 1 byte in for wrapped length)
82 else {
83 memcpy(&cb->_buf[(cb->write_offset + 2) % cb->_buf_len], buf, len);
84 }
85
87 return 0;
88}
89
91 // buffer empty
92 if (cb->read_offset == cb->write_offset) { return CIR_ERROR_NO_MSG; }
93
95 size_t end_offset = cb->read_offset;
96
97 while(end_offset != cb->write_offset) {
101 if (end_offset >= cb->_buf_len) {
102 end_offset -= cb->_buf_len;
103 }
104 }
105
107 return 0;
108}
109
111 // write_offset == read_offset is considered an empty buffer. => 3= 2 (lenght) + 1 (margin)
112 int available = 0;
113 if (cb->read_offset > cb->write_offset) {
114 available = (int)cb->read_offset - (int)cb->write_offset - 3;
115 } else {
116 available = cb->_buf_len - ((int)cb->write_offset - (int)cb->read_offset) - 3;
117 }
118
119 return available > 0 ? (size_t)available : 0;
120}
121
123 cb->read_offset = 0;
124 cb->write_offset = 0;
125}
int circular_buffer_put(struct circular_buffer *cb, const uint8_t *buf, size_t len)
Copy buf in the circular buffer.
size_t circular_buffer_available(struct circular_buffer *cb)
Get the available sapce for the next buffer.
void circular_buffer_init(struct circular_buffer *cb, uint8_t *buffer, size_t len)
initialize a circular buffer.
void circular_buffer_clear(struct circular_buffer *cb)
Clear buffer.
int circular_buffer_get(struct circular_buffer *cb, uint8_t *buf, size_t len)
copy the next buffer available in cb to buf.
int circular_buffer_drop(struct circular_buffer *cb)
Drop last inserted record.
@ CIR_ERROR_NO_MSG
circular buffer is empty
@ CIR_ERROR_NO_SPACE_AVAILABLE
no space available in the circular buffer
@ CIR_ERROR_BUFFER_TOO_SMALL
destination buffer is too small
This is a general purpose circular buffer for storing variable lenght buffers in a FIFO order.
uint16_t foo
Definition main_demo5.c:58
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.