2012-11-05 00:29:29 -04:00
|
|
|
/// @file AP_Buffer.h
|
2013-07-25 12:35:31 -03:00
|
|
|
/// @brief fifo (queue) buffer template class
|
2016-02-17 21:25:16 -04:00
|
|
|
#pragma once
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2012-11-19 20:57:50 -04:00
|
|
|
#include <stdint.h>
|
2012-11-05 00:29:29 -04:00
|
|
|
|
|
|
|
/// @class AP_Buffer
|
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
class AP_Buffer {
|
|
|
|
public:
|
2013-07-25 12:35:31 -03:00
|
|
|
|
|
|
|
/// Constructor
|
|
|
|
///
|
2012-11-05 00:29:29 -04:00
|
|
|
AP_Buffer();
|
|
|
|
|
2013-07-25 12:35:31 -03:00
|
|
|
/// clear - removes all elements from the queue
|
|
|
|
///
|
2013-04-21 07:56:08 -03:00
|
|
|
void clear();
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2013-07-25 12:35:31 -03:00
|
|
|
/// push_back - adds an item to the end of the buffer.
|
|
|
|
/// If the buffer is full, the oldest element (i.e. the element at the begin) is removed
|
|
|
|
/// @param item
|
|
|
|
void push_back( const T &item );
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2014-10-19 16:28:45 -03:00
|
|
|
/// pop_front - removes an element from the beginning of the
|
|
|
|
/// buffer (i.e. the oldest element) and returns it in ret.
|
|
|
|
/// @param ret : the removed element, if exists
|
|
|
|
/// @return : true if successful, false if not
|
|
|
|
bool pop_front(T &ret);
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2013-07-25 12:35:31 -03:00
|
|
|
/// peek - returns a reference to an element of the buffer
|
|
|
|
/// if position isn't valid (i.e. >= size()) 0 is returned
|
|
|
|
/// @param position : index of the element
|
|
|
|
/// "0" is the oldest, size()-1 is the newest
|
|
|
|
/// @return
|
|
|
|
const T& peek(uint8_t position) const;
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2014-05-12 18:56:11 -03:00
|
|
|
T& peek_mutable(uint8_t position);
|
|
|
|
|
2013-07-25 12:35:31 -03:00
|
|
|
/// front - return a reference to the element at the begin of the queue (i.e. the oldest element)
|
|
|
|
/// If the queue is empty, 0 is returned.
|
|
|
|
/// @return : oldest element
|
|
|
|
const T& front() const { return this->peek(0); }
|
|
|
|
|
|
|
|
/// size - returns the number of elements in the queue
|
|
|
|
/// @return
|
|
|
|
uint8_t size() const { return _num_items; }
|
|
|
|
|
|
|
|
/// is_full - return true if the queue is full (i.e. size() == SIZE)
|
|
|
|
/// @return
|
|
|
|
bool is_full() const { return _num_items >= SIZE; }
|
|
|
|
|
|
|
|
/// is_empty - returns true if the queue is empty
|
|
|
|
/// @return
|
|
|
|
bool is_empty() const { return _num_items == 0; }
|
2012-11-05 00:29:29 -04:00
|
|
|
|
2013-04-21 07:56:08 -03:00
|
|
|
private:
|
2012-11-05 00:29:29 -04:00
|
|
|
uint8_t _num_items; // number of items in the buffer
|
2013-07-25 12:35:31 -03:00
|
|
|
uint8_t _head; // first item in the buffer (will be returned with the next pop_front call)
|
2012-11-05 00:29:29 -04:00
|
|
|
T _buff[SIZE]; // x values of each point on the curve
|
|
|
|
};
|
|
|
|
|
2013-04-21 07:56:08 -03:00
|
|
|
// Typedef for convenience - add more as needed
|
2012-12-09 11:41:59 -04:00
|
|
|
typedef AP_Buffer<float,5> AP_BufferFloat_Size5;
|
2012-11-05 00:29:29 -04:00
|
|
|
typedef AP_Buffer<float,15> AP_BufferFloat_Size15;
|
|
|
|
|
2013-07-30 12:56:33 -03:00
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
AP_Buffer<T,SIZE>::AP_Buffer() :
|
|
|
|
_num_items(0), _head(0)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
void AP_Buffer<T,SIZE>::clear() {
|
|
|
|
// clear the curve
|
|
|
|
_num_items = 0;
|
|
|
|
_head = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
void AP_Buffer<T,SIZE>::push_back( const T &item )
|
|
|
|
{
|
|
|
|
// determine position of new item
|
|
|
|
uint8_t tail = _head + _num_items;
|
|
|
|
if( tail >= SIZE ) {
|
|
|
|
tail -= SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// add item to buffer
|
|
|
|
_buff[tail] = item;
|
|
|
|
|
|
|
|
// increment number of items
|
|
|
|
if( _num_items < SIZE ) {
|
|
|
|
_num_items++;
|
|
|
|
}else{
|
|
|
|
// no room for new items so drop oldest item
|
|
|
|
_head++;
|
|
|
|
if( _head >= SIZE ) {
|
|
|
|
_head = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, uint8_t SIZE>
|
2014-10-19 16:28:45 -03:00
|
|
|
bool AP_Buffer<T,SIZE>::pop_front(T &ret)
|
2013-07-30 12:56:33 -03:00
|
|
|
{
|
2014-05-12 18:55:37 -03:00
|
|
|
if(_num_items == 0) {
|
2014-10-19 16:28:45 -03:00
|
|
|
// buffer is empty
|
|
|
|
return false;
|
2014-05-12 18:55:37 -03:00
|
|
|
}
|
|
|
|
|
2014-10-19 16:28:45 -03:00
|
|
|
// get next value in buffer
|
|
|
|
ret = _buff[_head];
|
|
|
|
|
2013-07-30 12:56:33 -03:00
|
|
|
// increment to next point
|
|
|
|
_head++;
|
|
|
|
if( _head >= SIZE )
|
|
|
|
_head = 0;
|
|
|
|
|
|
|
|
// reduce number of items
|
|
|
|
_num_items--;
|
|
|
|
|
2014-10-19 16:28:45 -03:00
|
|
|
// success
|
|
|
|
return true;
|
2013-07-30 12:56:33 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
const T& AP_Buffer<T,SIZE>::peek(uint8_t position) const
|
|
|
|
{
|
|
|
|
uint8_t j = _head + position;
|
|
|
|
|
|
|
|
// wrap around if necessary
|
|
|
|
if( j >= SIZE )
|
|
|
|
j -= SIZE;
|
|
|
|
|
|
|
|
// return desired value
|
|
|
|
return _buff[j];
|
|
|
|
}
|
|
|
|
|
2014-05-12 18:56:11 -03:00
|
|
|
template <class T, uint8_t SIZE>
|
|
|
|
T& AP_Buffer<T,SIZE>::peek_mutable(uint8_t position)
|
|
|
|
{
|
|
|
|
uint8_t j = _head + position;
|
|
|
|
|
|
|
|
// wrap around if necessary
|
|
|
|
if( j >= SIZE )
|
|
|
|
j -= SIZE;
|
|
|
|
|
|
|
|
// return desired value
|
|
|
|
return _buff[j];
|
|
|
|
}
|