From a200c36417a8d90315fd90ef983e907eb592417b Mon Sep 17 00:00:00 2001 From: Embedded Innovation Date: Thu, 28 Apr 2016 21:13:03 +0200 Subject: [PATCH] Added circular buffer --- .../drivers/CircularBuffer/CircularBuffer.h | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h diff --git a/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h b/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h new file mode 100644 index 0000000..46ba9a9 --- /dev/null +++ b/libraries/MySensors/drivers/CircularBuffer/CircularBuffer.h @@ -0,0 +1,163 @@ +/* + CircularBuffer - An Arduino circular buffering library for arbitrary types. + + Created by Ivo Pullens, Emmission, 2014-2016 -- www.emmission.nl + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef CircularBuffer_h +#define CircularBuffer_h +#include + +template class CircularBuffer +{ + public: + /** Constructor + * @param buffer Preallocated buffer of at least size records. + * @param size Number of records available in the buffer. + */ + CircularBuffer(T* buffer, const uint8_t size ) + : m_size(size), m_buff(buffer) + { + clear(); + } + + /** Clear all entries in the circular buffer. */ + void clear(void) + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + m_front = 0; + m_fill = 0; + } + } + + /** Test if the circular buffer is empty */ + inline bool empty(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return !m_fill; + } + } + + /** Return the number of records stored in the buffer */ + inline uint8_t available(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return m_fill; + } + } + + /** Test if the circular buffer is full */ + inline bool full(void) const + { + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + return m_fill == m_size; + } + } + + /** Aquire record on front of the buffer, for writing. + * After filling the record, it has to be pushed to actually + * add it to the buffer. + * @return Pointer to record, or NULL when buffer is full. + */ + T* getFront(void) const + { + T* f = NULL; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!full()) + f = get(m_front); + } + return f; + } + + /** Push record to front of the buffer + * @param record Record to push. If record was aquired previously (using getFront) its + * data will not be copied as it is already present in the buffer. + * @return True, when record was pushed successfully. + */ + bool pushFront(T* record) + { + bool ok = false; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!full()) + { + T* f = get(m_front); + if (f != record) + *f = *record; + m_front = (m_front+1) % m_size; + m_fill++; + ok = true; + } + } + return ok; + } + + /** Aquire record on back of the buffer, for reading. + * After reading the record, it has to be pop'ed to actually + * remove it from the buffer. + * @return Pointer to record, or NULL when buffer is empty. + */ + T* getBack(void) const + { + T* b = NULL; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!empty()) + b = get(back()); + } + return b; + } + + /** Remove record from back of the buffer. + * @return True, when record was pop'ed successfully. + */ + bool popBack(void) + { + bool ok = false; + ATOMIC_BLOCK(ATOMIC_RESTORESTATE) + { + if (!empty()) + { + m_fill--; + ok = true; + } + } + return ok; + } + + protected: + inline T * get(const uint8_t idx) const + { + return &(m_buff[idx]); + } + inline uint8_t back(void) const + { + return (m_front - m_fill + m_size) % m_size; + } + + const uint8_t m_size; // Total number of records that can be stored in the buffer. + T* const m_buff; // Ptr to buffer holding all records. + volatile uint8_t m_front; // Index of front element (not pushed yet). + volatile uint8_t m_fill; // Amount of records currently pushed. +}; + +#endif // CircularBuffer_h