mirror of https://github.com/lumapu/ahoy.git
				
				
			
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							158 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							158 lines
						
					
					
						
							4.3 KiB
						
					
					
				
								/*
							 | 
						|
								  CircularBuffer - An Arduino circular buffering library for arbitrary types.
							 | 
						|
								
							 | 
						|
								  Created by Ivo Pullens, Emmission, 2014 -- 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
							 | 
						|
								
							 | 
						|
								#ifdef ESP8266
							 | 
						|
								#define DISABLE_IRQ noInterrupts()
							 | 
						|
								#define RESTORE_IRQ interrupts()
							 | 
						|
								#else
							 | 
						|
								#define DISABLE_IRQ       \
							 | 
						|
								  uint8_t sreg = SREG;    \
							 | 
						|
								  cli();
							 | 
						|
								
							 | 
						|
								#define RESTORE_IRQ        \
							 | 
						|
								  SREG = sreg;
							 | 
						|
								#endif
							 | 
						|
								
							 | 
						|
								template <class T> 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)
							 | 
						|
								    {
							 | 
						|
								      m_front = 0;
							 | 
						|
								      m_fill  = 0;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /** Test if the circular buffer is empty */
							 | 
						|
								    inline bool empty(void) const
							 | 
						|
								    {
							 | 
						|
								      return !m_fill;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /** Return the number of records stored in the buffer */
							 | 
						|
								    inline uint8_t available(void) const
							 | 
						|
								    {
							 | 
						|
								      return m_fill;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /** Test if the circular buffer is full */
							 | 
						|
								    inline bool full(void) const
							 | 
						|
								    {
							 | 
						|
								      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
							 | 
						|
								    {
							 | 
						|
								      DISABLE_IRQ;
							 | 
						|
								      T* f = NULL;
							 | 
						|
								      if (!full())
							 | 
						|
								        f = get(m_front);
							 | 
						|
								      RESTORE_IRQ;
							 | 
						|
								      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;
							 | 
						|
								      DISABLE_IRQ;
							 | 
						|
								      if (!full())
							 | 
						|
								      {
							 | 
						|
								        T* f = get(m_front);
							 | 
						|
								        if (f != record)
							 | 
						|
								          *f = *record;
							 | 
						|
								        m_front = (m_front+1) % m_size;
							 | 
						|
								        m_fill++;
							 | 
						|
								        ok = true;
							 | 
						|
								      }
							 | 
						|
								      RESTORE_IRQ;
							 | 
						|
								      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;
							 | 
						|
								      DISABLE_IRQ;
							 | 
						|
								      if (!empty())
							 | 
						|
								        b = get(back());
							 | 
						|
								      RESTORE_IRQ;
							 | 
						|
								      return b;
							 | 
						|
								    }
							 | 
						|
								
							 | 
						|
								    /** Remove record from back of the buffer.
							 | 
						|
								     * @return True, when record was pop'ed successfully.
							 | 
						|
								     */
							 | 
						|
								    bool popBack(void)
							 | 
						|
								    {
							 | 
						|
								      bool ok = false;
							 | 
						|
								      DISABLE_IRQ;
							 | 
						|
								      if (!empty())
							 | 
						|
								      {
							 | 
						|
								        m_fill--;
							 | 
						|
								        ok = true;
							 | 
						|
								      }
							 | 
						|
								      RESTORE_IRQ;
							 | 
						|
								      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
							 | 
						|
								
							 |