1 /**
2 *****************************************************************************************
3 *
4 * @file ring_buffer.c
5 *
6 * @brief Ring buffer function Implementation.
7 *
8 *****************************************************************************************
9 * @attention
10 #####Copyright (c) 2019 GOODIX
11 All rights reserved.
12
13 Redistribution and use in source and binary forms, with or without
14 modification, are permitted provided that the following conditions are met:
15 * Redistributions of source code must retain the above copyright
16 notice, this list of conditions and the following disclaimer.
17 * Redistributions in binary form must reproduce the above copyright
18 notice, this list of conditions and the following disclaimer in the
19 documentation and/or other materials provided with the distribution.
20 * Neither the name of GOODIX nor the names of its contributors may be used
21 to endorse or promote products derived from this software without
22 specific prior written permission.
23
24 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
28 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 POSSIBILITY OF SUCH DAMAGE.
35 *****************************************************************************************
36 */
37
38 /*
39 * INCLUDE FILES
40 *****************************************************************************************
41 */
42 #include <string.h>
43 #include "gr55xx_hal.h"
44 #include "utility.h"
45 #include "ring_buffer.h"
46 /*
47 * DEFINES
48 *****************************************************************************************
49 */
50 #define RING_BUFFER_LOCK() GLOBAL_EXCEPTION_DISABLE()
51 #define RING_BUFFER_UNLOCK() GLOBAL_EXCEPTION_ENABLE()
52
53 /*
54 * GLOBAL FUNCTION DEFINITIONS
55 *****************************************************************************************
56 */
ring_buffer_init(ring_buffer_t * p_ring_buff,uint8_t * p_buff,uint32_t buff_size)57 bool ring_buffer_init(ring_buffer_t *p_ring_buff, uint8_t *p_buff, uint32_t buff_size)
58 {
59 if (p_buff == NULL || p_ring_buff == NULL) {
60 return false;
61 } else {
62 p_ring_buff->buffer_size = buff_size;
63 p_ring_buff->p_buffer = p_buff;
64 p_ring_buff->write_index = 0;
65 p_ring_buff->read_index = 0;
66
67 return true;
68 }
69 }
70
ring_buffer_write(ring_buffer_t * p_ring_buff,uint8_t const * p_wr_data,uint32_t length)71 uint32_t ring_buffer_write(ring_buffer_t *p_ring_buff, uint8_t const *p_wr_data, uint32_t length)
72 {
73 uint32_t surplus_space = 0;
74 uint32_t over_flow = 0;
75 uint32_t wr_idx = p_ring_buff->write_index;
76 uint32_t rd_idx = p_ring_buff->read_index;
77 uint32_t ret = 0;
78 uint32_t len = length;
79
80 RING_BUFFER_LOCK();
81
82 if (rd_idx > wr_idx) {
83 surplus_space = rd_idx - wr_idx - 1;
84 len = (len > surplus_space ? surplus_space : len);
85 } else {
86 surplus_space = p_ring_buff->buffer_size - wr_idx + rd_idx - 1;
87 len = (len > surplus_space ? surplus_space : len);
88
89 if (wr_idx + len >= p_ring_buff->buffer_size) {
90 over_flow = wr_idx + len - p_ring_buff->buffer_size;
91 }
92 }
93
94 ret = memcpy_s(p_ring_buff->p_buffer + wr_idx, len - over_flow, p_wr_data, len - over_flow);
95 if (ret < 0) {
96 return ret;
97 }
98 ret = memcpy_s(p_ring_buff->p_buffer, over_flow, p_wr_data + len - over_flow, over_flow);
99 if (ret < 0) {
100 return ret;
101 }
102 wr_idx += len;
103
104 if (wr_idx >= p_ring_buff->buffer_size) {
105 wr_idx -= p_ring_buff->buffer_size;
106 }
107
108 p_ring_buff->write_index = wr_idx;
109
110 RING_BUFFER_UNLOCK();
111
112 return len;
113 }
114
ring_buffer_read(ring_buffer_t * p_ring_buff,uint8_t * p_rd_data,uint32_t length)115 uint32_t ring_buffer_read(ring_buffer_t *p_ring_buff, uint8_t *p_rd_data, uint32_t length)
116 {
117 uint32_t items_avail = 0;
118 uint32_t over_flow = 0;
119 uint32_t wr_idx = p_ring_buff->write_index;
120 uint32_t rd_idx = p_ring_buff->read_index;
121 uint32_t len = length;
122
123 RING_BUFFER_LOCK();
124
125 if (wr_idx >= rd_idx) {
126 items_avail = wr_idx - rd_idx;
127 len = (len > items_avail ? items_avail : len);
128 } else {
129 items_avail = p_ring_buff->buffer_size - rd_idx + wr_idx;
130 len = (len > items_avail ? items_avail : len);
131
132 if (rd_idx + len >= p_ring_buff->buffer_size) {
133 over_flow = len + rd_idx - p_ring_buff->buffer_size;
134 }
135 }
136
137 memcpy_s(p_rd_data, len - over_flow, p_ring_buff->p_buffer + rd_idx, len - over_flow);
138 memcpy_s(p_rd_data + len - over_flow, over_flow, p_ring_buff->p_buffer, over_flow);
139 rd_idx += len;
140
141 if (rd_idx >= p_ring_buff->buffer_size && rd_idx > wr_idx) {
142 rd_idx -= p_ring_buff->buffer_size;
143 }
144
145 p_ring_buff->read_index = rd_idx;
146
147 RING_BUFFER_UNLOCK();
148
149 return len;
150 }
151
ring_buffer_pick(ring_buffer_t * p_ring_buff,uint8_t * p_rd_data,uint32_t length)152 uint32_t ring_buffer_pick(ring_buffer_t *p_ring_buff, uint8_t *p_rd_data, uint32_t length)
153 {
154 uint32_t items_avail = 0;
155 uint32_t over_flow = 0;
156 uint32_t wr_idx = p_ring_buff->write_index;
157 uint32_t rd_idx = p_ring_buff->read_index;
158 uint32_t len = length;
159
160 RING_BUFFER_LOCK();
161
162 if (wr_idx >= rd_idx) {
163 items_avail = wr_idx - rd_idx;
164 len = (len > items_avail ? items_avail : len);
165 } else {
166 items_avail = p_ring_buff->buffer_size - rd_idx + wr_idx;
167 len = (len > items_avail ? items_avail : len);
168
169 if (rd_idx + len >= p_ring_buff->buffer_size) {
170 over_flow = len + rd_idx - p_ring_buff->buffer_size;
171 }
172 }
173
174 memcpy_s(p_rd_data, len - over_flow, p_ring_buff->p_buffer + rd_idx, len - over_flow);
175 memcpy_s(p_rd_data + len - over_flow, over_flow, p_ring_buff->p_buffer, over_flow);
176
177 RING_BUFFER_UNLOCK();
178
179 return len;
180 }
181
ring_buffer_items_count_get(ring_buffer_t * p_ring_buff)182 uint32_t ring_buffer_items_count_get(ring_buffer_t *p_ring_buff)
183 {
184 uint32_t wr_idx = p_ring_buff->write_index;
185 uint32_t rd_idx = p_ring_buff->read_index;
186
187 if (rd_idx <= wr_idx) {
188 return wr_idx - rd_idx;
189 } else {
190 return p_ring_buff->buffer_size - rd_idx + wr_idx;
191 }
192 }
193
ring_buffer_surplus_space_get(ring_buffer_t * p_ring_buff)194 uint32_t ring_buffer_surplus_space_get(ring_buffer_t *p_ring_buff)
195 {
196 uint32_t surplus_space;
197 uint32_t wr_idx = p_ring_buff->write_index;
198 uint32_t rd_idx = p_ring_buff->read_index;
199
200 RING_BUFFER_LOCK();
201
202 if (rd_idx > wr_idx) {
203 surplus_space = rd_idx - wr_idx - 1;
204 } else {
205 surplus_space = p_ring_buff->buffer_size - wr_idx + rd_idx - 1;
206 }
207
208 RING_BUFFER_UNLOCK();
209
210 return surplus_space;
211 }
212
ring_buffer_is_reach_left_threshold(ring_buffer_t * p_ring_buff,uint32_t letf_threshold)213 bool ring_buffer_is_reach_left_threshold(ring_buffer_t *p_ring_buff, uint32_t letf_threshold)
214 {
215 uint32_t surplus_space;
216
217 surplus_space = ring_buffer_surplus_space_get(p_ring_buff);
218 if (letf_threshold >= surplus_space) {
219 return true;
220 } else {
221 return false;
222 }
223 }
224
ring_buffer_clean(ring_buffer_t * p_ring_buff)225 void ring_buffer_clean(ring_buffer_t *p_ring_buff)
226 {
227 RING_BUFFER_LOCK();
228
229 p_ring_buff->write_index = 0;
230 p_ring_buff->read_index = 0;
231
232 RING_BUFFER_UNLOCK();
233 }
234
235