160 lines
4 KiB
C
160 lines
4 KiB
C
/** \file
|
|
* \brief This file implements a circular buffer.
|
|
*
|
|
*/
|
|
|
|
/* Include Files */
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <project.h>
|
|
|
|
#include "FreeRTOS.h"
|
|
#include "task.h"
|
|
|
|
#include "UTIL_CircularBuffer.h"
|
|
|
|
/* Local Definitions */
|
|
|
|
/* Public Functions */
|
|
|
|
/* Public Data */
|
|
|
|
/* ******************* Module Level Information ********************* */
|
|
|
|
/* Private Function Prototypes */
|
|
|
|
/* Private Data */
|
|
|
|
/* Module Level Code */
|
|
|
|
//! Increments a value using modular arithmetic.
|
|
/*!
|
|
* \param value the value to be incremented
|
|
* \param modulus the modulus to use
|
|
* \return (value + 1) modulo <i>modulus</i>
|
|
*/
|
|
inline uint16_t ModuloIncrement(const uint16_t value, const uint16_t modulus)
|
|
{
|
|
uint16_t nextValue = value + 1;
|
|
if (nextValue >= modulus)
|
|
{
|
|
nextValue = 0;
|
|
}
|
|
return (nextValue);
|
|
}
|
|
|
|
//! Initializes the circular buffer, and clears the flags.
|
|
/*!
|
|
* \param this pointer to the circular buffer in question
|
|
* \param buffer pointer to the memory allocated to store this circular buffer
|
|
* \param size size (in bytes) of this circular buffer
|
|
*/
|
|
void UTIL_InitCircularBuffer(UTIL_CircularBuffer_T * const this, uint8_t * buffer, uint16_t size)
|
|
{
|
|
this->buffer = buffer;
|
|
this->size = size;
|
|
this->head = 0;
|
|
this->tail = 0;
|
|
this->count = 0;
|
|
// Note that there is no need to zero out the actual buffer,
|
|
// since it will be overwritten when values are added.
|
|
}
|
|
|
|
//! Adds a value to the end of the circular buffer.
|
|
/*!
|
|
* If the buffer is full, the value is dropped and the overflow flag is set.
|
|
*
|
|
* \param this pointer to the circular buffer in question
|
|
* \param value the value to be added to the buffer
|
|
*/
|
|
UTIL_CircularBufferResult_T UTIL_PushToCircularBuffer(UTIL_CircularBuffer_T * const this, uint8_t value)
|
|
{
|
|
UTIL_CircularBufferResult_T result = UTIL_CIRCULARBUFFERRESULT_UNKNOWN;
|
|
|
|
//UBaseType_t uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
if (this->count < this->size)
|
|
{
|
|
this->buffer[this->head] = value;
|
|
this->head = ModuloIncrement(this->head, this->size);
|
|
this->count++;
|
|
result = UTIL_CIRCULARBUFFERRESULT_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
result = UTIL_CIRCULARBUFFERRESULT_ERROR_OVERFLOW;
|
|
}
|
|
|
|
portENABLE_INTERRUPTS();
|
|
//taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
|
|
|
|
return result;
|
|
}
|
|
|
|
//! Retrieves a value from the beginning of the circular buffer (FIFO).
|
|
/*!
|
|
* If the buffer is empty, zero is returned and the underflow flag is set.
|
|
*
|
|
* \param this pointer to the circular buffer in question
|
|
* \return the oldest value in the buffer
|
|
*/
|
|
UTIL_CircularBufferResult_T UTIL_PopFromCircularBuffer(UTIL_CircularBuffer_T * const this, uint8_t * const value)
|
|
{
|
|
UTIL_CircularBufferResult_T result = UTIL_CIRCULARBUFFERRESULT_UNKNOWN;
|
|
|
|
//UBaseType_t uxSavedInterruptStatus = taskENTER_CRITICAL_FROM_ISR();
|
|
portDISABLE_INTERRUPTS();
|
|
|
|
if (this->count > 0)
|
|
{
|
|
*value = this->buffer[this->tail];
|
|
this->tail = ModuloIncrement(this->tail, this->size);
|
|
this->count--;
|
|
result = UTIL_CIRCULARBUFFERRESULT_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
*value = 0;
|
|
result = UTIL_CIRCULARBUFFERRESULT_ERROR_UNDERFLOW;
|
|
}
|
|
|
|
portENABLE_INTERRUPTS();
|
|
//taskEXIT_CRITICAL_FROM_ISR(uxSavedInterruptStatus);
|
|
|
|
return result;
|
|
}
|
|
|
|
//! Determines whether or not the circular buffer is empty.
|
|
/*!
|
|
* \param this pointer to the circular buffer in question
|
|
* \return true if the buffer is empty; false otherwise
|
|
*/
|
|
bool UTIL_IsCircularBufferEmpty(UTIL_CircularBuffer_T * const this)
|
|
{
|
|
bool result = false;
|
|
|
|
if (this->count == 0)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//! Determines whether or not the circular buffer is full.
|
|
/*!
|
|
* \param this pointer to the circular buffer in question
|
|
* \return true if the buffer is full; false otherwise
|
|
*/
|
|
bool UTIL_IsCircularBufferFull(UTIL_CircularBuffer_T * const this)
|
|
{
|
|
bool result = false;
|
|
|
|
if (this->count >= this->size)
|
|
{
|
|
result = true;
|
|
}
|
|
|
|
return result;
|
|
}
|