copia12092018

Dependencies:   mbed

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?

UserRevisionLine numberNew 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