2020TPC-SW/2020TPCAppNoDFU.cydsn/UTIL/UTIL_CircularBuffer.c
2025-02-01 19:52:04 -06:00

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;
}