|
|
|
/**************************************************************************//**
|
|
|
|
* @file
|
|
|
|
* @author Steve Lascos
|
|
|
|
* @company Blackaddr Audio
|
|
|
|
*
|
|
|
|
* This file contains some custom types used by the rest of the BALibrary library.
|
|
|
|
*
|
|
|
|
* @copyright This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.*
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*****************************************************************************/
|
|
|
|
#include <Arduino.h>
|
|
|
|
|
|
|
|
#ifndef __BALIBRARY_BATYPES_H
|
|
|
|
#define __BALIBRARY_BATYPES_H
|
|
|
|
|
|
|
|
namespace BALibrary {
|
|
|
|
|
|
|
|
#define UNUSED(x) (void)(x)
|
|
|
|
|
|
|
|
/**************************************************************************//**
|
|
|
|
* Customer RingBuffer with random access
|
|
|
|
*****************************************************************************/
|
|
|
|
template <class T>
|
|
|
|
class RingBuffer {
|
|
|
|
public:
|
|
|
|
RingBuffer() = delete;
|
|
|
|
|
|
|
|
/// Construct a RingBuffer of specified max size
|
|
|
|
/// @param maxSize number of entries in ring buffer
|
|
|
|
RingBuffer(const size_t maxSize) : m_maxSize(maxSize) {
|
|
|
|
m_buffer = new T[maxSize]();
|
|
|
|
}
|
|
|
|
virtual ~RingBuffer(){
|
|
|
|
if (m_buffer) delete [] m_buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Add an element to the back of the queue
|
|
|
|
/// @param element element to add to queue
|
|
|
|
/// returns 0 if success, otherwise error
|
|
|
|
int push_back(T element) {
|
|
|
|
|
|
|
|
//Serial.println(String("RingBuffer::push_back...") + m_head + String(":") + m_tail + String(":") + m_size);
|
|
|
|
if ( (m_head == m_tail) && (m_size > 0) ) {
|
|
|
|
// overflow
|
|
|
|
Serial.println("RingBuffer::push_back: overflow");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_buffer[m_head] = element;
|
|
|
|
if (m_head < (m_maxSize-1) ) {
|
|
|
|
m_head++;
|
|
|
|
} else {
|
|
|
|
m_head = 0;
|
|
|
|
}
|
|
|
|
m_size++;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Remove the element at teh front of the queue
|
|
|
|
/// @returns 0 if success, otherwise error
|
|
|
|
int pop_front() {
|
|
|
|
|
|
|
|
if (m_size == 0) {
|
|
|
|
// buffer is empty
|
|
|
|
//Serial.println("RingBuffer::pop_front: buffer is empty\n");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (m_tail < m_maxSize-1) {
|
|
|
|
m_tail++;
|
|
|
|
} else {
|
|
|
|
m_tail = 0;
|
|
|
|
}
|
|
|
|
m_size--;
|
|
|
|
//Serial.println(String("RingBuffer::pop_front: ") + m_head + String(":") + m_tail + String(":") + m_size);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get the element at the front of the queue
|
|
|
|
/// @returns element at front of queue
|
|
|
|
T front() const {
|
|
|
|
return m_buffer[m_tail];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// get the element at the back of the queue
|
|
|
|
/// @returns element at the back of the queue
|
|
|
|
T back() const {
|
|
|
|
return m_buffer[m_head-1];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Get a previously pushed elememt
|
|
|
|
/// @param offset zero is last pushed, 1 is second last, etc.
|
|
|
|
/// @returns the absolute index corresponding to the requested offset.
|
|
|
|
size_t get_index_from_back(size_t offset = 0) const {
|
|
|
|
// the target at m_head - 1 - offset or m_maxSize + m_head -1 - offset;
|
|
|
|
size_t idx = (m_maxSize + m_head -1 - offset);
|
|
|
|
|
|
|
|
if ( idx >= m_maxSize) {
|
|
|
|
idx -= m_maxSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// get the current size of the queue
|
|
|
|
/// @returns size of the queue
|
|
|
|
size_t size() const {
|
|
|
|
return m_size;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// get the maximum size the queue can hold
|
|
|
|
/// @returns maximum size of the queue
|
|
|
|
size_t max_size() const {
|
|
|
|
return m_maxSize;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// get the element at the specified absolute index
|
|
|
|
/// @param index element to retrieve from absolute queue position
|
|
|
|
/// @returns the request element
|
|
|
|
T& operator[] (size_t index) {
|
|
|
|
return m_buffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// get the element at the specified absolute index
|
|
|
|
/// @param index element to retrieve from absolute queue position
|
|
|
|
/// @returns the request element
|
|
|
|
T at(size_t index) const {
|
|
|
|
return m_buffer[index];
|
|
|
|
}
|
|
|
|
|
|
|
|
/// DEBUG: Prints the status of the Ringbuffer. NOte using this much printing will usually cause audio glitches
|
|
|
|
void print() const {
|
|
|
|
for (int idx=0; idx<m_maxSize; idx++) {
|
|
|
|
Serial.print(idx + String(" address: ")); Serial.print((uint32_t)m_buffer[idx], HEX);
|
|
|
|
Serial.print(" data: "); Serial.println((uint32_t)m_buffer[idx]->data, HEX);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
size_t m_head=0; ///< back of the queue
|
|
|
|
size_t m_tail=0; ///< front of the queue
|
|
|
|
size_t m_size=0; ///< current size of the qeueu
|
|
|
|
T *m_buffer = nullptr; ///< pointer to the allocated buffer array
|
|
|
|
const size_t m_maxSize; ///< maximum size of the queue
|
|
|
|
};
|
|
|
|
|
|
|
|
} // BALibrary
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* __BALIBRARY_BATYPES_H */
|