///////////////////////////////////////////////////////////////////////////// // //! @file ring_buffer.c //! @author Nathan Miller //! @version 1.1 // //! @description Implements a Ring Buffer in C. // // External dependencies: // // mip.h // //!@copyright 2014 Lord Microstrain Sensing Systems. // //!@section CHANGES //! // //!@section LICENSE //! //! THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING //! CUSTOMERS WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER //! FOR THEM TO SAVE TIME. AS A RESULT, LORD MICROSTRAIN SENSING SYSTEMS //! SHALL NOT BE HELD LIABLE FOR ANY DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES //! WITH RESPECT TO ANY CLAIMS ARISING FROM THE CONTENT OF SUCH SOFTWARE AND/OR //! THE USE MADE BY CUSTOMERS OF THE CODING INFORMATION CONTAINED HEREIN IN CONNECTION //! WITH THEIR PRODUCTS. // ///////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// // //Include Files // //////////////////////////////////////////////////////////////////////////////// #include "ring_buffer.h" ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_init_static(ring_buffer *buffer, u8 *data_buffer_ptr, //! u32 max_entries, u8 entry_size) // //! @section DESCRIPTION //! Initialize a ring buffer with a static memory location. // //! @section DETAILS //! //! @param [out] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u8 *data_buffer_ptr - data pointer (must be allocated and size = \c max_entries * \c entry_size). //! @param [in] u32 max_entries - maximum entries the ring buffer may contain. //! @param [in] u32 entry_size - size of each entry (bytes). // //! @retval RING_BUFFER_ERROR Buffer not initialized.\n //! @retval RING_BUFFER_OK Buffer initialized.\n // //! @section NOTES //! //! None //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_init_static(ring_buffer *buffer, u8 *data_buffer_ptr, u32 max_entries, u32 entry_size) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Set the buffer to the uninitialized state buffer->state = RING_BUFFER_UNINITIALIZED; //Null check the data buffer pointer if(data_buffer_ptr == 0) return RING_BUFFER_ERROR; //Reset buffer variables and stats __ring_buffer_reset(buffer); buffer->entries = data_buffer_ptr; buffer->max_entries = max_entries; buffer->entry_size = entry_size; buffer->type = RING_BUFFER_STATIC_TYPE; //Set the buffer to the initialized state buffer->state = RING_BUFFER_INITIALIZED; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_init_malloc(ring_buffer *buffer, u32 max_entries, u8 entry_size) // //! @section DESCRIPTION //! Initialize a ring buffer using malloc to allocate the buffer from the heap. // //! @section DETAILS //! //! @param [out] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u32 max_entries - maximum entries the ring buffer may contain. //! @param [in] u32 entry_size - size of each entry (bytes). // //! @retval RING_BUFFER_ERROR Buffer not initialized.\n //! @retval RING_BUFFER_OK Buffer initialized.\n // //! @section NOTES //! //! None //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_init_malloc(ring_buffer *buffer, u32 max_entries, u32 entry_size) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Set the buffer to the uninitialized state buffer->state = RING_BUFFER_UNINITIALIZED; //Attempt to allocate the needed space buffer->entries = (u8 *)malloc(max_entries*entry_size); //If the pointer is null, malloc failed if(buffer->entries == 0) return RING_BUFFER_MEMORY_ERROR; //Reset buffer variables and stats __ring_buffer_reset(buffer); buffer->max_entries = max_entries; buffer->entry_size = entry_size; buffer->type = RING_BUFFER_MALLOC_TYPE; //Set the buffer to the initialized state buffer->state = RING_BUFFER_INITIALIZED; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u32 ring_buffer_count(ring_buffer *buffer) // //! @section DESCRIPTION //! Returns the number of entries in the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @returns Number of entries in the buffer, if initialized.\n //! 0 Otherwise. // //! @section NOTES //! //! None //! // ///////////////////////////////////////////////////////////////////////////// u32 ring_buffer_count(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return 0; //Check that the buffer was initialized if(buffer->state != RING_BUFFER_INITIALIZED) return 0; return buffer->current_count; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u32 ring_buffer_remaining_entries(ring_buffer *buffer) // //! @section DESCRIPTION //! Returns the number of empty entries in the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @returns Number of empty entries in the buffer, if initialized.\n //! 0 Otherwise. // //! @section NOTES //! //! None //! // ///////////////////////////////////////////////////////////////////////////// u32 ring_buffer_remaining_entries(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return 0; //Check that the buffer was initialized if(buffer->state != RING_BUFFER_INITIALIZED) return 0; return buffer->max_entries - buffer->current_count; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_flush(ring_buffer *buffer) // //! @section DESCRIPTION //! Flushes the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @retval RING_BUFFER_ERROR Buffer not initialized.\n //! @retval RING_BUFFER_OK Buffer flushed.\n // //! @section NOTES //! //! None //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_flush(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check that the buffer was initialized if(buffer->state != RING_BUFFER_INITIALIZED) return RING_BUFFER_ERROR; //Flush the buffer buffer->position = 0; buffer->current_count = 0; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_write(ring_buffer *buffer, u8 *entry, u32 num_bytes) // //! @section DESCRIPTION //! Write \c num_bytes of a single entry to the ring buffer. // //! @section DETAILS //! //! @param [out] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u8 *entry - pointer to memory buffer holding the entry. //! @param [in] u32 num_bytes - number of bytes to write. // //! @retval RING_BUFFER_ERROR Entry not written, buffer not initialized.\n //! @retval RING_BUFFER_FULL Entry not written, the buffer is full.\n //! @retval RING_BUFFER_MEMORY_ERROR Entry not written, num_bytes is larger than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entry written.\n // //! @section NOTES //! //! \c num_bytes included for ring buffers with variable entry sizes (e.g. strings). //! \c num_bytes must be less than the max entry size. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_write(ring_buffer *buffer, u8 *entry, u32 num_bytes) { u32 entry_pos = 0, i; //Null check the pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check for a full ring buffer if(buffer->current_count >= buffer->max_entries) { buffer->total_overruns++; return RING_BUFFER_FULL; } //Zero byte short circuit if(num_bytes == 0) return RING_BUFFER_OK; //Check entry size if(num_bytes > buffer->entry_size) return RING_BUFFER_MEMORY_ERROR; //Calculate the write position entry_pos = buffer->position + buffer->current_count; if(entry_pos >= buffer->max_entries) entry_pos -= buffer->max_entries; //Write the entry for(i=0;ientries[entry_pos*buffer->entry_size + i] = entry[i]; //Update the ring buffer buffer->current_count++; buffer->total_entries_written++; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_write_multi(ring_buffer *buffer, u8 *entry_buff, u32 num_entries) // //! @section DESCRIPTION //! Write \c num_entries to the ring buffer. // //! @section DETAILS //! //! @param [out] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u8 *entry_buff - pointer to memory buffer holding the entries. //! @param [in] u32 num_entries - number of entries to write. // //! @retval RING_BUFFER_ERROR Entries not written, buffer not initialized.\n //! @retval RING_BUFFER_FULL Entries not written, the buffer is full.\n //! @retval RING_BUFFER_MEMORY_ERROR Entries not written, num_bytes is larger than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entries written.\n // //! @section NOTES //! //! All entries are assumed to be of size \c entry_size, which is set by the ring_buffer_init_xxxxxx call. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_write_multi(ring_buffer *buffer, u8 *entry_buff, u32 num_entries, u32 *num_written) { u32 entry_pos = 0, i, j; *num_written = 0; //Null check the pointer if(buffer == 0) return RING_BUFFER_ERROR; //Zero entry short circuit if(num_entries == 0) return RING_BUFFER_OK; //Loop through the requested entries for(i=0; icurrent_count >= buffer->max_entries) { buffer->total_overruns += num_entries - i; return RING_BUFFER_FULL; } //Calculate the write position entry_pos = buffer->position + buffer->current_count; if(entry_pos >= buffer->max_entries) entry_pos -= buffer->max_entries; //Write the entry for(j=0;jentry_size;j++) buffer->entries[entry_pos*buffer->entry_size + j] = entry_buff[i*buffer->entry_size + j]; //Update the ring buffer buffer->current_count++; buffer->total_entries_written++; (*num_written)++; } return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_read(ring_buffer *buffer, u8 *entry, u32 max_bytes) // //! @section DESCRIPTION //! Read a single entry from the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [out] u8 *entry - pointer to data buffer where the entry will be stored. //! @param [in] u32 max_bytes - maximum size of the data buffer. // //! @retval RING_BUFFER_ERROR Entry not read, buffer not initialized.\n //! @retval RING_BUFFER_FULL Entry not read, the buffer is empty.\n //! @retval RING_BUFFER_MEMORY_ERROR Entry not read, max_bytes is smaller than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entry read.\n // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_read(ring_buffer *buffer, u8 *entry, u32 max_bytes) { u32 i; //Check for an empty buffer if(buffer->current_count == 0) return RING_BUFFER_EMPTY; //Copy the entry for(i=0;ientry_size;i++) entry[i] = buffer->entries[buffer->position*buffer->entry_size + i]; //Update the ring buffer if(++buffer->position >= buffer->max_entries) buffer->position -= buffer->max_entries; buffer->current_count--; buffer->total_entries_read++; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_lookahead_read(ring_buffer *buffer, u32 offset, u8 *entry, u32 max_bytes) // //! @section DESCRIPTION //! Read an entry from the ring buffer without consuming it. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u32 offset - offset from the head of the ring buffer to read. //! @param [out] u8 *entry - pointer to data buffer where the entry will be stored. //! @param [in] u32 max_bytes - maximum size of the data buffer. // //! @retval RING_BUFFER_ERROR Entry not read, buffer not initialized.\n //! @retval RING_BUFFER_FULL Entry not read, the buffer is empty.\n //! @retval RING_BUFFER_MEMORY_ERROR Entry not read, max_bytes is smaller than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entries read.\n // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_lookahead_read(ring_buffer *buffer, u32 offset, u8 *entry, u32 max_bytes) { u32 local_position, i; //Null check the pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return RING_BUFFER_ERROR; //Check for an empty buffer if(buffer->current_count == 0) return RING_BUFFER_EMPTY; //Check for buffer size if(max_bytes < buffer->entry_size) return RING_BUFFER_MEMORY_ERROR; //Check that there are the expected number of entries (that count > offset) if(buffer->current_count <= offset) return RING_BUFFER_ERROR; //Assign the temporary position local_position = buffer->position + offset; //Temporary position loop logic the ring buffer if(local_position >= buffer->max_entries) local_position -= buffer->max_entries; //Copy the entry for(i=0;ientry_size;i++) entry[i] = buffer->entries[local_position*buffer->entry_size + i]; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_read_multi(ring_buffer *buffer, u8 *entry_buff, u32 entry_buff_size, //! u32 num_requested, u32 *num_read) // //! @section DESCRIPTION //! Read \c num_requested entries from the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [out] u8 *entry - pointer to data buffer where the entries will be stored. //! @param [in] u32 entry_buff_size - maximum size of the data buffer in bytes. //! @param [in] u32 num_requested - the number of entries requested. //! @param [out] u32 num_read - the number of entries actually read. // //! @retval RING_BUFFER_ERROR Entry not read, buffer not initialized.\n //! @retval RING_BUFFER_EMPTY Entry not read, the buffer is empty.\n //! @retval RING_BUFFER_MEMORY_ERROR Entry not read, max_bytes is smaller than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entries read.\n // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_read_multi(ring_buffer *buffer, u8 *entry_buff, u32 entry_buff_size, u32 num_requested, u32 *num_read) { u32 i, j; //Reset number of entries read *num_read = 0; //Check the buffer size if(entry_buff_size < num_requested*buffer->entry_size) return RING_BUFFER_MEMORY_ERROR; //Copy the entry for(i=0; icurrent_count == 0) return RING_BUFFER_EMPTY; for(j=0;jentry_size;j++) entry_buff[i*buffer->entry_size + j] = buffer->entries[buffer->position*buffer->entry_size + j]; //Update the ring buffer if(++buffer->position >= buffer->max_entries) buffer->position -= buffer->max_entries; buffer->current_count--; buffer->total_entries_read++; (*num_read) += 1; } return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_lookahead_read_multi(ring_buffer *buffer, u32 offset, u8 *entry_buff, //! u32 entry_buff_size, u32 num_requested, u32 *num_read) // //! @section DESCRIPTION //! Read \c num_requested entries from the ring buffer without consuming them. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] u32 offset - offset from the head of the ring buffer to read. //! @param [out] u8 *entry_buff - pointer to data buffer where the entries will be stored. //! @param [in] u32 entry_buff_size - maximum size of the data buffer in bytes. //! @param [in] u32 num_requested - the number of entries requested. //! @param [out] u32 num_read - the number of entries actually read. // //! @retval RING_BUFFER_ERROR Entry not read, buffer not initialized.\n //! @retval RING_BUFFER_EMPTY Entry not read, the buffer is empty.\n //! @retval RING_BUFFER_MEMORY_ERROR Entry not read, max_bytes is smaller than the ring buffer entry size.\n //! @retval RING_BUFFER_OK Entries read.\n // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_lookahead_read_multi(ring_buffer *buffer, u32 offset, u8 *entry_buff, u32 entry_buff_size, u32 num_requested, u32 *num_read) { u32 local_position, i, j; //Reset number of entries read *num_read = 0; //Null check the pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return RING_BUFFER_ERROR; //Check for an empty buffer if(buffer->current_count == 0) return RING_BUFFER_EMPTY; //Check for buffer size if(entry_buff_size < num_requested*buffer->entry_size) return RING_BUFFER_MEMORY_ERROR; //Check that there are the expected number of entries (that count > offset) if(buffer->current_count < offset + num_requested) return RING_BUFFER_ERROR; for(i=0; iposition + offset + i; //Temporary position loop logic the ring buffer if(local_position >= buffer->max_entries) local_position -= buffer->max_entries; //Copy the entry for(j=0; jentry_size; j++) entry_buff[i*buffer->entry_size + j] = buffer->entries[local_position*buffer->entry_size + j]; //Increment number read (*num_read) += 1; } return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_copy(ring_buffer *to, ring_buffer *from, u32 num_entries) // //! @section DESCRIPTION //! Copy \c num_entries between two ring buffers. // //! @section DETAILS //! //! @param [out] ring_buffer *to - pointer to a ring buffer structure to copy to. //! @param [in] ring_buffer *from - pointer to a ring buffer structure to copy from. //! @param [in] num_entries - the number of entries to copy. // //! @returns Number of entries copied // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u32 ring_buffer_copy(ring_buffer *to, ring_buffer *from, u32 num_entries) { u32 i, j, write_pos, num_copied = 0; //Check that the entry size is the same if(from->entry_size != to->entry_size) return 0; //Loop through num_entries, copying each for(i=0; icurrent_count == 0) return num_copied; //Check if to buffer is full if(to->current_count >= to->max_entries) return num_copied; //Calculate the write position write_pos = to->position + to->current_count; if(write_pos >= to->max_entries) write_pos -= to->max_entries; //Copy the entry for(j=0; j < to->entry_size; j++) to->entries[write_pos*to->entry_size + j] = from->entries[from->position*from->entry_size +j]; //Update the 'to' ring buffer to->current_count++; to->total_entries_written++; //Update the 'from' buffer if(++from->position >= from->max_entries) from->position -= from->max_entries; from->current_count--; from->total_entries_read++; num_copied++; } return num_copied; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_lookahead_copy(ring_buffer *to, u32 offset, ring_buffer *from, u32 num_entries) // //! @section DESCRIPTION //! Copy \c num_entries between two ring buffers without consuming the entries. // //! @section DETAILS //! //! @param [out] ring_buffer *to - pointer to a ring buffer structure to copy to. //! @param [in] u32 offset - offset from the first element to start the copy. //! @param [in] ring_buffer *from - pointer to a ring buffer structure to copy from. //! @param [in] num_entries - the number of entries to copy. // //! @returns Number of entries copied // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u32 ring_buffer_lookahead_copy(ring_buffer *to, u32 offset, ring_buffer *from, u32 num_entries) { u32 i, j, write_pos, read_pos; //Null check the 'to' buffer if(to == 0) return 0; //Null check the 'from' buffer if(from == 0) return 0; //Check if the 'to' ring buffer is initialized if(to->state != RING_BUFFER_INITIALIZED) return 0; //Check if the 'from' ring buffer is initialized if(from->state != RING_BUFFER_INITIALIZED) return 0; //Check that the entry size is the same if(from->entry_size != to->entry_size) return 0; //Check the offset and number of requested entries if(num_entries + offset > ring_buffer_count(from)) return 0; //Loop through num_entries, copying each for(i=0; icurrent_count == 0) return i; //Check if to buffer is full if(to->current_count >= to->max_entries) return i; //Calculate the write position write_pos = to->position + to->current_count; if(write_pos >= to->max_entries) write_pos -= to->max_entries; //Calculate the read position read_pos = from->position + offset + i; if(read_pos >= from->max_entries) read_pos -= from->max_entries; //Copy the entry for(j=0;jentry_size;j++) to->entries[write_pos*to->entry_size +j] = from->entries[read_pos*from->entry_size + j]; //Update the 'to' ring buffer to->current_count++; to->total_entries_written++; } return i; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_consume_entries(ring_buffer *buffer, u32 num_entries) // //! @section DESCRIPTION //! Removes \c num_entries from the buffer if they exist. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. //! @param [in] num_entries - the number of entries to remove. // //! @returns Number of entries removed // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_consume_entries(ring_buffer *buffer, u32 num_entries) { u32 num_consume; //Calculate the total number of entries to consume //(cannot consume more than current number of entries) if(num_entries > buffer->current_count) num_consume = buffer->current_count; else num_consume = num_entries; //Remove the entries buffer->position += num_consume; if(buffer->position >= buffer->max_entries) buffer->position -= buffer->max_entries; buffer->current_count -= num_consume; //Update the stats buffer->total_entries_read += num_consume; return num_consume; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_malloc_free(ring_buffer *buffer) // //! @section DESCRIPTION //! Return the allocated memory to the heap. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @retval RING_BUFFER_ERROR Buffer not initialized or not malloc'd.\n //! @retval RING_BUFFER_OK Buffer freed.\n // //! @section NOTES //! //! None. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_malloc_free(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check that the buffer did use malloc if(buffer->type != RING_BUFFER_MALLOC_TYPE) return RING_BUFFER_ERROR; free(buffer->entries); return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u8 *ring_buffer_get_first_element_ptr(ring_buffer *buffer) // //! @section DESCRIPTION //! Return a pointer to the first element in the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @returns NULL (0) If the ring buffer pointer is invalid or there are no elements.\n //! Otherwise, the pointer to first element. // //! @section NOTES //! //! This routine should only be used for single-element access!!!\n //! Attempting to access multiple elements using this can cause access\n //! outside of the array boundaries! //! // ///////////////////////////////////////////////////////////////////////////// u8 *ring_buffer_get_first_element_ptr(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return 0; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return 0; //Check for an empty buffer if(buffer->current_count == 0) return 0; return &buffer->entries[buffer->position*buffer->entry_size]; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_remove_first_element(ring_buffer *buffer) // //! @section DESCRIPTION //! Removes the first element of the ring buffer if it exists. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @retval RING_BUFFER_ERROR Ring buffer invalid.\n //! @retval RING_BUFFER_EMPTY Ring buffer empty.\n //! @retval RING_BUFFER_OK Element removed.\n // //! @section NOTES //! //! Used in conjunction with ring_buffer_get_first_element_ptr\n //! for pointer read access to ring buffer elements. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_remove_first_element(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return RING_BUFFER_ERROR; //Check for an empty buffer if(buffer->current_count == 0) return RING_BUFFER_EMPTY; //Remove the first element if(++buffer->position >= buffer->max_entries) buffer->position -= buffer->max_entries; buffer->current_count--; //Update the stats buffer->total_entries_read++; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u8 *ring_buffer_get_available_element_ptr(ring_buffer *buffer) // //! @section DESCRIPTION //! Return a pointer to the next available element in the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @returns NULL (0) If the ring buffer pointer is invalid or there are no elements.\n //! Otherwise, the pointer to first available element. // //! @section NOTES //! //! This routine should only be used for single-element access!!!\n //! Attempting to access multiple elements using this can cause access\n //! outside of the array boundaries! //! // ///////////////////////////////////////////////////////////////////////////// u8 *ring_buffer_get_available_element_ptr(ring_buffer *buffer) { u32 entry_pos; //Null check the ring buffer pointer if(buffer == 0) return 0; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return 0; //Check for an full buffer if(buffer->current_count >= buffer->max_entries) return 0; //Calculate the write position entry_pos = buffer->position + buffer->current_count; if(entry_pos >= buffer->max_entries) entry_pos -= buffer->max_entries; return &buffer->entries[entry_pos*buffer->entry_size]; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! u16 ring_buffer_increment_count(ring_buffer *buffer) // //! @section DESCRIPTION //! Increments the number of elements in the ring buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @retval RING_BUFFER_ERROR Ring buffer invalid.\n //! @retval RING_BUFFER_EMPTY Ring buffer full.\n //! @retval RING_BUFFER_OK Element added.\n // //! @section NOTES //! //! Used in conjunction with ring_buffer_get_available_element_ptr\n //! for pointer write access to ring buffer elements. //! // ///////////////////////////////////////////////////////////////////////////// u16 ring_buffer_increment_count(ring_buffer *buffer) { //Null check the ring buffer pointer if(buffer == 0) return RING_BUFFER_ERROR; //Check if the ring buffer is initialized if(buffer->state != RING_BUFFER_INITIALIZED) return RING_BUFFER_ERROR; //Check for a full buffer if(buffer->current_count >= buffer->max_entries) return RING_BUFFER_FULL; //Add the next element buffer->current_count++; //Update the stats buffer->total_entries_written++; return RING_BUFFER_OK; } ///////////////////////////////////////////////////////////////////////////// // //! @fn //! void __ring_buffer_reset(ring_buffer *buffer) // //! @section DESCRIPTION //! Reset the ring buffer state, stats, and buffer. // //! @section DETAILS //! //! @param [in] ring_buffer *buffer - pointer to a ring buffer structure. // //! @section NOTES //! //! Internal Function. //! // ///////////////////////////////////////////////////////////////////////////// void __ring_buffer_reset(ring_buffer *buffer) { //State buffer->state = RING_BUFFER_UNINITIALIZED; //Ring buffer variables buffer->position = 0; buffer->current_count = 0; //Stats buffer->total_entries_written = 0; buffer->total_entries_read = 0; buffer->total_overruns = 0; }