/** \file * \brief This file implements a circular buffer. * */ /* Include Files */ #include #include #include #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 modulus */ 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; }