Francesco Pistone
/
Viaro_SpandiConcime_V3_inizio
copia12092018
CB1.h@13:4d6114864f2d, 2018-11-16 (annotated)
- Committer:
- root@developer-sjc-indigo-compiler.local.mbed.org
- Date:
- Fri Nov 16 10:55:45 2018 +0000
- Revision:
- 13:4d6114864f2d
- Parent:
- 0:b0a79a3a9da8
Added tag fine for changeset dde73cf20353
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
nerit | 0:b0a79a3a9da8 | 1 | /* |
nerit | 0:b0a79a3a9da8 | 2 | CB1.h - Circular buffer library for Arduino. |
nerit | 0:b0a79a3a9da8 | 3 | Copyright (c) 2017 Roberto Lo Giacco. All right reserved. |
nerit | 0:b0a79a3a9da8 | 4 | |
nerit | 0:b0a79a3a9da8 | 5 | This library is free software; you can redistribute it and/or |
nerit | 0:b0a79a3a9da8 | 6 | modify it under the terms of the GNU Lesser General Public |
nerit | 0:b0a79a3a9da8 | 7 | License as published by the Free Software Foundation; either |
nerit | 0:b0a79a3a9da8 | 8 | version 2.1 of the License, or (at your option) any later version. |
nerit | 0:b0a79a3a9da8 | 9 | |
nerit | 0:b0a79a3a9da8 | 10 | This library is distributed in the hope that it will be useful, |
nerit | 0:b0a79a3a9da8 | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
nerit | 0:b0a79a3a9da8 | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
nerit | 0:b0a79a3a9da8 | 13 | Lesser General Public License for more details. |
nerit | 0:b0a79a3a9da8 | 14 | |
nerit | 0:b0a79a3a9da8 | 15 | You should have received a copy of the GNU Lesser General Public |
nerit | 0:b0a79a3a9da8 | 16 | License along with this library; if not, write to the Free Software |
nerit | 0:b0a79a3a9da8 | 17 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
nerit | 0:b0a79a3a9da8 | 18 | */ |
nerit | 0:b0a79a3a9da8 | 19 | #ifndef __CIRCULAR_BUFFER__ |
nerit | 0:b0a79a3a9da8 | 20 | #define __CIRCULAR_BUFFER__ |
nerit | 0:b0a79a3a9da8 | 21 | #include <inttypes.h> |
nerit | 0:b0a79a3a9da8 | 22 | |
nerit | 0:b0a79a3a9da8 | 23 | #ifndef CIRCULAR_BUFFER_XS |
nerit | 0:b0a79a3a9da8 | 24 | #define __CB_ST__ uint16_t |
nerit | 0:b0a79a3a9da8 | 25 | #else |
nerit | 0:b0a79a3a9da8 | 26 | #define __CB_ST__ uint8_t |
nerit | 0:b0a79a3a9da8 | 27 | #endif |
nerit | 0:b0a79a3a9da8 | 28 | |
nerit | 0:b0a79a3a9da8 | 29 | #ifdef CIRCULAR_BUFFER_DEBUG |
nerit | 0:b0a79a3a9da8 | 30 | #include <Print.h> |
nerit | 0:b0a79a3a9da8 | 31 | #endif |
nerit | 0:b0a79a3a9da8 | 32 | |
nerit | 0:b0a79a3a9da8 | 33 | #include <string.h> |
nerit | 0:b0a79a3a9da8 | 34 | |
nerit | 0:b0a79a3a9da8 | 35 | template<typename T, __CB_ST__ S> class CB1 { |
nerit | 0:b0a79a3a9da8 | 36 | public: |
nerit | 0:b0a79a3a9da8 | 37 | |
nerit | 0:b0a79a3a9da8 | 38 | CB1(); |
nerit | 0:b0a79a3a9da8 | 39 | |
nerit | 0:b0a79a3a9da8 | 40 | ~CB1(); |
nerit | 0:b0a79a3a9da8 | 41 | |
nerit | 0:b0a79a3a9da8 | 42 | /** |
nerit | 0:b0a79a3a9da8 | 43 | * Adds an element to the beginning of buffer: the operation returns `false` if the addition caused overwriting an existing element. |
nerit | 0:b0a79a3a9da8 | 44 | */ |
nerit | 0:b0a79a3a9da8 | 45 | bool unshift(T value); |
nerit | 0:b0a79a3a9da8 | 46 | |
nerit | 0:b0a79a3a9da8 | 47 | /** |
nerit | 0:b0a79a3a9da8 | 48 | * Adds an element to the end of buffer: the operation returns `false` if the addition caused overwriting an existing element. |
nerit | 0:b0a79a3a9da8 | 49 | */ |
nerit | 0:b0a79a3a9da8 | 50 | bool push(T value); |
nerit | 0:b0a79a3a9da8 | 51 | |
nerit | 0:b0a79a3a9da8 | 52 | /** |
nerit | 0:b0a79a3a9da8 | 53 | * Removes an element from the beginning of the buffer. |
nerit | 0:b0a79a3a9da8 | 54 | */ |
nerit | 0:b0a79a3a9da8 | 55 | T shift(); |
nerit | 0:b0a79a3a9da8 | 56 | |
nerit | 0:b0a79a3a9da8 | 57 | /** |
nerit | 0:b0a79a3a9da8 | 58 | * Removes an element from the end of the buffer. |
nerit | 0:b0a79a3a9da8 | 59 | */ |
nerit | 0:b0a79a3a9da8 | 60 | T pop(); |
nerit | 0:b0a79a3a9da8 | 61 | |
nerit | 0:b0a79a3a9da8 | 62 | /** |
nerit | 0:b0a79a3a9da8 | 63 | * Returns the element at the beginning of the buffer. |
nerit | 0:b0a79a3a9da8 | 64 | */ |
nerit | 0:b0a79a3a9da8 | 65 | T inline first(); |
nerit | 0:b0a79a3a9da8 | 66 | |
nerit | 0:b0a79a3a9da8 | 67 | /** |
nerit | 0:b0a79a3a9da8 | 68 | * Returns the element at the end of the buffer. |
nerit | 0:b0a79a3a9da8 | 69 | */ |
nerit | 0:b0a79a3a9da8 | 70 | T inline last(); |
nerit | 0:b0a79a3a9da8 | 71 | |
nerit | 0:b0a79a3a9da8 | 72 | /** |
nerit | 0:b0a79a3a9da8 | 73 | * Array-like access to buffer |
nerit | 0:b0a79a3a9da8 | 74 | */ |
nerit | 0:b0a79a3a9da8 | 75 | T operator [] (__CB_ST__ index); |
nerit | 0:b0a79a3a9da8 | 76 | |
nerit | 0:b0a79a3a9da8 | 77 | /** |
nerit | 0:b0a79a3a9da8 | 78 | * Returns how many elements are actually stored in the buffer. |
nerit | 0:b0a79a3a9da8 | 79 | */ |
nerit | 0:b0a79a3a9da8 | 80 | __CB_ST__ inline size(); |
nerit | 0:b0a79a3a9da8 | 81 | |
nerit | 0:b0a79a3a9da8 | 82 | /** |
nerit | 0:b0a79a3a9da8 | 83 | * Returns how many elements can be safely pushed into the buffer. |
nerit | 0:b0a79a3a9da8 | 84 | */ |
nerit | 0:b0a79a3a9da8 | 85 | __CB_ST__ inline available(); |
nerit | 0:b0a79a3a9da8 | 86 | |
nerit | 0:b0a79a3a9da8 | 87 | /** |
nerit | 0:b0a79a3a9da8 | 88 | * Returns how many elements can be potentially stored into the buffer. |
nerit | 0:b0a79a3a9da8 | 89 | */ |
nerit | 0:b0a79a3a9da8 | 90 | __CB_ST__ inline capacity(); |
nerit | 0:b0a79a3a9da8 | 91 | |
nerit | 0:b0a79a3a9da8 | 92 | /** |
nerit | 0:b0a79a3a9da8 | 93 | * Returns `true` if no elements can be removed from the buffer. |
nerit | 0:b0a79a3a9da8 | 94 | */ |
nerit | 0:b0a79a3a9da8 | 95 | bool inline isEmpty(); |
nerit | 0:b0a79a3a9da8 | 96 | |
nerit | 0:b0a79a3a9da8 | 97 | /** |
nerit | 0:b0a79a3a9da8 | 98 | * Returns `true` if no elements can be added to the buffer without overwriting existing elements. |
nerit | 0:b0a79a3a9da8 | 99 | */ |
nerit | 0:b0a79a3a9da8 | 100 | bool inline isFull(); |
nerit | 0:b0a79a3a9da8 | 101 | |
nerit | 0:b0a79a3a9da8 | 102 | /** |
nerit | 0:b0a79a3a9da8 | 103 | * Resets the buffer to a clean status, dropping any reference to current elements |
nerit | 0:b0a79a3a9da8 | 104 | * and making all buffer positions available again. |
nerit | 0:b0a79a3a9da8 | 105 | */ |
nerit | 0:b0a79a3a9da8 | 106 | void inline clear(); |
nerit | 0:b0a79a3a9da8 | 107 | |
nerit | 0:b0a79a3a9da8 | 108 | #ifdef CIRCULAR_BUFFER_DEBUG |
nerit | 0:b0a79a3a9da8 | 109 | void inline debug(Print* out); |
nerit | 0:b0a79a3a9da8 | 110 | void inline debugFn(Print* out, void (*printFunction)(Print*, T)); |
nerit | 0:b0a79a3a9da8 | 111 | #endif |
nerit | 0:b0a79a3a9da8 | 112 | |
nerit | 0:b0a79a3a9da8 | 113 | private: |
nerit | 0:b0a79a3a9da8 | 114 | T buffer[S]; |
nerit | 0:b0a79a3a9da8 | 115 | T *head; |
nerit | 0:b0a79a3a9da8 | 116 | T *tail; |
nerit | 0:b0a79a3a9da8 | 117 | uint16_t count; |
nerit | 0:b0a79a3a9da8 | 118 | }; |
nerit | 0:b0a79a3a9da8 | 119 | |
nerit | 0:b0a79a3a9da8 | 120 | |
nerit | 0:b0a79a3a9da8 | 121 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 122 | CB1<T,S>::CB1() : |
nerit | 0:b0a79a3a9da8 | 123 | head(buffer), tail(buffer), count(0) { |
nerit | 0:b0a79a3a9da8 | 124 | } |
nerit | 0:b0a79a3a9da8 | 125 | |
nerit | 0:b0a79a3a9da8 | 126 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 127 | CB1<T,S>::~CB1() { |
nerit | 0:b0a79a3a9da8 | 128 | } |
nerit | 0:b0a79a3a9da8 | 129 | |
nerit | 0:b0a79a3a9da8 | 130 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 131 | bool CB1<T,S>::unshift(T value) { |
nerit | 0:b0a79a3a9da8 | 132 | if (head == buffer) { |
nerit | 0:b0a79a3a9da8 | 133 | head = buffer + S; |
nerit | 0:b0a79a3a9da8 | 134 | } |
nerit | 0:b0a79a3a9da8 | 135 | *--head = value; |
nerit | 0:b0a79a3a9da8 | 136 | if (count == S) { |
nerit | 0:b0a79a3a9da8 | 137 | if (tail-- == buffer) { |
nerit | 0:b0a79a3a9da8 | 138 | tail = buffer + S - 1; |
nerit | 0:b0a79a3a9da8 | 139 | } |
nerit | 0:b0a79a3a9da8 | 140 | return false; |
nerit | 0:b0a79a3a9da8 | 141 | } else { |
nerit | 0:b0a79a3a9da8 | 142 | if (count++ == 0) { |
nerit | 0:b0a79a3a9da8 | 143 | tail = head; |
nerit | 0:b0a79a3a9da8 | 144 | } |
nerit | 0:b0a79a3a9da8 | 145 | return true; |
nerit | 0:b0a79a3a9da8 | 146 | } |
nerit | 0:b0a79a3a9da8 | 147 | } |
nerit | 0:b0a79a3a9da8 | 148 | |
nerit | 0:b0a79a3a9da8 | 149 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 150 | bool CB1<T,S>::push(T value) { |
nerit | 0:b0a79a3a9da8 | 151 | if (++tail == buffer + S) { |
nerit | 0:b0a79a3a9da8 | 152 | tail = buffer; |
nerit | 0:b0a79a3a9da8 | 153 | } |
nerit | 0:b0a79a3a9da8 | 154 | *tail = value; |
nerit | 0:b0a79a3a9da8 | 155 | if (count == S) { |
nerit | 0:b0a79a3a9da8 | 156 | if (++head == buffer + S) { |
nerit | 0:b0a79a3a9da8 | 157 | head = buffer; |
nerit | 0:b0a79a3a9da8 | 158 | } |
nerit | 0:b0a79a3a9da8 | 159 | return false; |
nerit | 0:b0a79a3a9da8 | 160 | } else { |
nerit | 0:b0a79a3a9da8 | 161 | if (count++ == 0) { |
nerit | 0:b0a79a3a9da8 | 162 | head = tail; |
nerit | 0:b0a79a3a9da8 | 163 | } |
nerit | 0:b0a79a3a9da8 | 164 | return true; |
nerit | 0:b0a79a3a9da8 | 165 | } |
nerit | 0:b0a79a3a9da8 | 166 | } |
nerit | 0:b0a79a3a9da8 | 167 | |
nerit | 0:b0a79a3a9da8 | 168 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 169 | T CB1<T,S>::shift() { |
nerit | 0:b0a79a3a9da8 | 170 | void(* crash) (void) = 0; |
nerit | 0:b0a79a3a9da8 | 171 | if (count <= 0) crash(); |
nerit | 0:b0a79a3a9da8 | 172 | T result = *head++; |
nerit | 0:b0a79a3a9da8 | 173 | if (head >= buffer + S) { |
nerit | 0:b0a79a3a9da8 | 174 | head = buffer; |
nerit | 0:b0a79a3a9da8 | 175 | } |
nerit | 0:b0a79a3a9da8 | 176 | count--; |
nerit | 0:b0a79a3a9da8 | 177 | return result; |
nerit | 0:b0a79a3a9da8 | 178 | } |
nerit | 0:b0a79a3a9da8 | 179 | |
nerit | 0:b0a79a3a9da8 | 180 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 181 | T CB1<T,S>::pop() { |
nerit | 0:b0a79a3a9da8 | 182 | void(* crash) (void) = 0; |
nerit | 0:b0a79a3a9da8 | 183 | if (count <= 0) crash(); |
nerit | 0:b0a79a3a9da8 | 184 | T result = *tail--; |
nerit | 0:b0a79a3a9da8 | 185 | if (tail < buffer) { |
nerit | 0:b0a79a3a9da8 | 186 | tail = buffer + S - 1; |
nerit | 0:b0a79a3a9da8 | 187 | } |
nerit | 0:b0a79a3a9da8 | 188 | count--; |
nerit | 0:b0a79a3a9da8 | 189 | return result; |
nerit | 0:b0a79a3a9da8 | 190 | } |
nerit | 0:b0a79a3a9da8 | 191 | |
nerit | 0:b0a79a3a9da8 | 192 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 193 | T inline CB1<T,S>::first() { |
nerit | 0:b0a79a3a9da8 | 194 | return *head; |
nerit | 0:b0a79a3a9da8 | 195 | } |
nerit | 0:b0a79a3a9da8 | 196 | |
nerit | 0:b0a79a3a9da8 | 197 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 198 | T inline CB1<T,S>::last() { |
nerit | 0:b0a79a3a9da8 | 199 | return *tail; |
nerit | 0:b0a79a3a9da8 | 200 | } |
nerit | 0:b0a79a3a9da8 | 201 | |
nerit | 0:b0a79a3a9da8 | 202 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 203 | T CB1<T,S>::operator [](__CB_ST__ index) { |
nerit | 0:b0a79a3a9da8 | 204 | return *(buffer + ((head - buffer + index) % S)); |
nerit | 0:b0a79a3a9da8 | 205 | } |
nerit | 0:b0a79a3a9da8 | 206 | |
nerit | 0:b0a79a3a9da8 | 207 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 208 | __CB_ST__ inline CB1<T,S>::size() { |
nerit | 0:b0a79a3a9da8 | 209 | return count; |
nerit | 0:b0a79a3a9da8 | 210 | } |
nerit | 0:b0a79a3a9da8 | 211 | |
nerit | 0:b0a79a3a9da8 | 212 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 213 | __CB_ST__ inline CB1<T,S>::available() { |
nerit | 0:b0a79a3a9da8 | 214 | return S - count; |
nerit | 0:b0a79a3a9da8 | 215 | } |
nerit | 0:b0a79a3a9da8 | 216 | |
nerit | 0:b0a79a3a9da8 | 217 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 218 | __CB_ST__ inline CB1<T,S>::capacity() { |
nerit | 0:b0a79a3a9da8 | 219 | return S; |
nerit | 0:b0a79a3a9da8 | 220 | } |
nerit | 0:b0a79a3a9da8 | 221 | |
nerit | 0:b0a79a3a9da8 | 222 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 223 | bool inline CB1<T,S>::isEmpty() { |
nerit | 0:b0a79a3a9da8 | 224 | return count == 0; |
nerit | 0:b0a79a3a9da8 | 225 | } |
nerit | 0:b0a79a3a9da8 | 226 | |
nerit | 0:b0a79a3a9da8 | 227 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 228 | bool inline CB1<T,S>::isFull() { |
nerit | 0:b0a79a3a9da8 | 229 | return count == S; |
nerit | 0:b0a79a3a9da8 | 230 | } |
nerit | 0:b0a79a3a9da8 | 231 | |
nerit | 0:b0a79a3a9da8 | 232 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 233 | void inline CB1<T,S>::clear() { |
nerit | 0:b0a79a3a9da8 | 234 | memset(buffer, 0, sizeof(buffer)); |
nerit | 0:b0a79a3a9da8 | 235 | head = tail = buffer; |
nerit | 0:b0a79a3a9da8 | 236 | count = 0; |
nerit | 0:b0a79a3a9da8 | 237 | } |
nerit | 0:b0a79a3a9da8 | 238 | |
nerit | 0:b0a79a3a9da8 | 239 | #ifdef CIRCULAR_BUFFER_DEBUG |
nerit | 0:b0a79a3a9da8 | 240 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 241 | void inline CB1<T,S>::debug(Print* out) { |
nerit | 0:b0a79a3a9da8 | 242 | for (__CB_ST__ i = 0; i < S; i++) { |
nerit | 0:b0a79a3a9da8 | 243 | int hex = (int)buffer + i; |
nerit | 0:b0a79a3a9da8 | 244 | out->print(hex, HEX); |
nerit | 0:b0a79a3a9da8 | 245 | out->print(" "); |
nerit | 0:b0a79a3a9da8 | 246 | out->print(*(buffer + i)); |
nerit | 0:b0a79a3a9da8 | 247 | if (head == buffer + i) { |
nerit | 0:b0a79a3a9da8 | 248 | out->print(" head"); |
nerit | 0:b0a79a3a9da8 | 249 | } |
nerit | 0:b0a79a3a9da8 | 250 | if (tail == buffer + i) { |
nerit | 0:b0a79a3a9da8 | 251 | out->print(" tail"); |
nerit | 0:b0a79a3a9da8 | 252 | } |
nerit | 0:b0a79a3a9da8 | 253 | out->println(); |
nerit | 0:b0a79a3a9da8 | 254 | } |
nerit | 0:b0a79a3a9da8 | 255 | } |
nerit | 0:b0a79a3a9da8 | 256 | |
nerit | 0:b0a79a3a9da8 | 257 | template<typename T, __CB_ST__ S> |
nerit | 0:b0a79a3a9da8 | 258 | void inline CB1<T,S>::debugFn(Print* out, void (*printFunction)(Print*, T)) { |
nerit | 0:b0a79a3a9da8 | 259 | for (__CB_ST__ i = 0; i < S; i++) { |
nerit | 0:b0a79a3a9da8 | 260 | int hex = (int)buffer + i; |
nerit | 0:b0a79a3a9da8 | 261 | out->print(hex, HEX); |
nerit | 0:b0a79a3a9da8 | 262 | out->print(" "); |
nerit | 0:b0a79a3a9da8 | 263 | printFunction(out, *(buffer + i)); |
nerit | 0:b0a79a3a9da8 | 264 | if (head == buffer + i) { |
nerit | 0:b0a79a3a9da8 | 265 | out->print(" head"); |
nerit | 0:b0a79a3a9da8 | 266 | } |
nerit | 0:b0a79a3a9da8 | 267 | if (tail == buffer + i) { |
nerit | 0:b0a79a3a9da8 | 268 | out->print(" tail"); |
nerit | 0:b0a79a3a9da8 | 269 | } |
nerit | 0:b0a79a3a9da8 | 270 | out->println(); |
nerit | 0:b0a79a3a9da8 | 271 | } |
nerit | 0:b0a79a3a9da8 | 272 | } |
nerit | 0:b0a79a3a9da8 | 273 | #endif |
nerit | 0:b0a79a3a9da8 | 274 | |
nerit | 0:b0a79a3a9da8 | 275 | #endif |