Added Javadoc to fifo module and header file.

This commit is contained in:
skarg
2013-02-22 16:19:42 +00:00
parent 2eb8e84f41
commit 7084b9f036
2 changed files with 274 additions and 210 deletions
+239 -155
View File
@@ -1,56 +1,107 @@
/*####COPYRIGHTBEGIN####
-------------------------------------------
Copyright (C) 2004 by Steve Karg
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 2
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, write to:
The Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307
USA.
As a special exception, if other files instantiate templates or
use macros or inline functions from this file, or you compile
this file and link it with other works to produce a work based
on this file, this file does not by itself cause the resulting
work to be covered by the GNU General Public License. However
the source code for this file must still be made available in
accordance with section (3) of the GNU General Public License.
This exception does not invalidate any other reasons why a work
based on this file might be covered by the GNU General Public
License.
-------------------------------------------
####COPYRIGHTEND####*/
/** @file fifo.c Generic FIFO library for deeply embedded system */
/* Functional Description: Generic FIFO library for deeply
embedded system. See the unit tests for usage examples. */
/**
* @file
* @author Steve Karg
* @date 2004
* @brief Generic interrupt safe FIFO library for deeply embedded system.
*
* @section LICENSE
*
* 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 2
* 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, write to:
* The Free Software Foundation, Inc.
* 59 Temple Place - Suite 330
* Boston, MA 02111-1307
* USA.
*
* As a special exception, if other files instantiate templates or
* use macros or inline functions from this file, or you compile
* this file and link it with other works to produce a work based
* on this file, this file does not by itself cause the resulting
* work to be covered by the GNU General Public License. However
* the source code for this file must still be made available in
* accordance with section (3) of the GNU General Public License.
*
* This exception does not invalidate any other reasons why a work
* based on this file might be covered by the GNU General Public
* License.
*
* @section DESCRIPTION
*
* Generic interrupt safe FIFO library for deeply embedded system
* This library only uses a byte sized chunk for a data element.
* It uses a data store whose size is a power of 2 (8, 16, 32, 64, ...)
* and doesn't waste any data bytes. It has very low overhead, and
* utilizes modulo for indexing the data in the data store.
*
* To use this library, first declare a data store, sized for a power of 2:
* {@code
* static volatile uint8_t data_store[64];
* }
*
* Then declare the FIFO tracking structure:
* {@code
* static FIFO_BUFFER queue;
* }
*
* Initialize the queue with the data store:
* {@code
* FIFO_Init(&queue, data_store, sizeof(data_store));
* }
*
* Then begin to use the FIFO queue by giving it data, retreiving data,
* and checking the FIFO queue to see if it is empty or full:
* {@code
* uint8_t in_data = 0;
* uint8_t out_data = 0;
* uint8_t add_data[5] = {0};
* uint8_t pull_data[5] = {0};
* unsigned count = 0;
* bool status = false;
*
* status = FIFO_Put(&queue, in_data);
* if (!FIFO_Empty(&queue)) {
* out_data = FIFO_Get(&queue);
* }
* if (FIFO_Available(&queue, sizeof(add_data))) {
* status = FIFO_Add(&queue, add_data, sizeof(add_data));
* }
* count = FIFO_Count(&queue);
* if (count == sizeof(add_data)) {
* count = FIFO_Pull(&queue, &pull_data[0], sizeof(pull_data));
* }
*
* }
*
* Normally the FIFO is used by a producer, such as in interrupt service
* routine, which places data into the queue using FIFO_Put(), and a consumer,
* such as a main loop handler, which pulls data from the queue by first
* checking the queue for data using FIFO_Empty(), and then pulling data from
* the queue using FIFO_Get().
*
*/
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "fifo.h"
/****************************************************************************
* DESCRIPTION: Returns the number of elements in the ring buffer
* RETURN: Number of elements in the ring buffer
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
unsigned FIFO_Count(
FIFO_BUFFER const *b)
/**
* Returns the number of bytes in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return Number of bytes in the FIFO
*/
unsigned FIFO_Count(FIFO_BUFFER const *b)
{
unsigned head, tail; /* used to avoid volatile decision */
@@ -63,91 +114,106 @@ unsigned FIFO_Count(
}
}
/****************************************************************************
* DESCRIPTION: Returns the empty/full status of the ring buffer
* RETURN: true if the ring buffer is full, false if it is not.
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Full(
FIFO_BUFFER const *b)
/**
* Returns the full status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return true if the FIFO is full, false if it is not.
*/
bool FIFO_Full(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == b->buffer_len) : true);
}
/****************************************************************************
* DESCRIPTION: Tests to see if space is available
* RETURN: true if the number of bytes is available
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Available(
FIFO_BUFFER const *b,
/**
* Tests to see if space is available in the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param count [in] - number of bytes tested for availability
*
* @return true if the number of bytes sought is available
*/
bool FIFO_Available(FIFO_BUFFER const *b,
unsigned count)
{
return (b ? (count <= (b->buffer_len - FIFO_Count(b))) : false);
}
/****************************************************************************
* DESCRIPTION: Returns the empty/full status of the ring buffer
* RETURN: true if the ring buffer is empty, false if it is not.
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Empty(
FIFO_BUFFER const *b)
/**
* Returns the empty status of the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @return true if the FIFO is empty, false if it is not.
*/
bool FIFO_Empty(FIFO_BUFFER const *b)
{
return (b ? (FIFO_Count(b) == 0) : true);
}
/****************************************************************************
* DESCRIPTION: Looks at the data from the head of the list without removing it
* RETURN: byte of data, or zero if nothing in the list
* ALGORITHM: none
* NOTES: Use Empty function to see if there is data to retrieve
*****************************************************************************/
uint8_t FIFO_Peek(
FIFO_BUFFER const *b)
/**
* Peeks at the data from the front of the FIFO without removing it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return byte of data, or zero if nothing in the list
*/
uint8_t FIFO_Peek(FIFO_BUFFER const *b)
{
unsigned index;
if (b) {
return (b->buffer[b->tail % b->buffer_len]);
index = b->tail % b->buffer_len;
return (b->buffer[index]);
}
return 0;
}
/****************************************************************************
* DESCRIPTION: Gets the data from the front of the list, and removes it
* RETURN: the data, or zero if nothing in the list
* ALGORITHM: none
* NOTES: Use Empty function to see if there is data to retrieve
*****************************************************************************/
uint8_t FIFO_Get(
FIFO_BUFFER * b)
/**
* Gets a byte from the front of the FIFO, and removes it.
* Use FIFO_Empty() or FIFO_Available() function to see if there is
* data to retrieve since this function doesn't return a flag indicating
* success or failure.
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return the data
*/
uint8_t FIFO_Get(FIFO_BUFFER * b)
{
uint8_t data_byte = 0;
unsigned index;
if (!FIFO_Empty(b)) {
data_byte = b->buffer[b->tail % b->buffer_len];
index = b->tail % b->buffer_len;
data_byte = b->buffer[index];
b->tail++;
}
return data_byte;
}
/****************************************************************************
* DESCRIPTION: Pulls the data from the front of the list, and removes it
* RETURN: the data (in parameter) and the number of bytes pulled
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
unsigned FIFO_Pull(
FIFO_BUFFER * b,
uint8_t * data_bytes,
/**
* Pulls one or more bytes from the front of the FIFO, and removes them
* from the FIFO. If less bytes are available, only the available bytes
* are retrieved.
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - buffer to hold the pulled bytes
* @param length [in] - number of bytes to pull from the FIFO
*
* @return the number of bytes actually pulled from the FIFO
*/
unsigned FIFO_Pull(FIFO_BUFFER * b,
uint8_t * buffer,
unsigned length)
{
unsigned count;
uint8_t data_byte;
unsigned index;
count = FIFO_Count(b);
if (count > length) {
@@ -159,32 +225,38 @@ unsigned FIFO_Pull(
length = count;
}
while (count) {
data_byte = b->buffer[b->tail % b->buffer_len];
index = b->tail % b->buffer_len;
data_byte = b->buffer[index];
b->tail++;
*data_bytes = data_byte;
data_bytes++;
if (buffer) {
*buffer = data_byte;
buffer++;
}
count--;
}
return length;
}
/****************************************************************************
* DESCRIPTION: Adds an element of data to the FIFO
* RETURN: true on successful add, false if not added
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Put(
FIFO_BUFFER * b,
/**
* Adds a byte of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param data_byte [in] - data to put into the FIFO
*
* @return true on successful add, false if not added
*/
bool FIFO_Put(FIFO_BUFFER * b,
uint8_t data_byte)
{
bool status = false; /* return value */
unsigned index;
if (b) {
/* limit the ring to prevent overwriting */
/* limit the buffer to prevent overwriting */
if (!FIFO_Full(b)) {
b->buffer[b->head % b->buffer_len] = data_byte;
index = b->head % b->buffer_len;
b->buffer[index] = data_byte;
b->head++;
status = true;
}
@@ -193,25 +265,29 @@ bool FIFO_Put(
return status;
}
/****************************************************************************
* DESCRIPTION: Adds one or more elements of data to the FIFO
* RETURN: true if space available and added, false if not added
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
bool FIFO_Add(
FIFO_BUFFER * b,
uint8_t * data_bytes,
/**
* Adds one or more bytes of data to the FIFO
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [out] - data bytes to add to the FIFO
* @param count [in] - number of bytes to add to the FIFO
*
* @return true if space available and added, false if not added
*/
bool FIFO_Add(FIFO_BUFFER * b,
uint8_t * buffer,
unsigned count)
{
bool status = false; /* return value */
unsigned index;
/* limit the ring to prevent overwriting */
if (FIFO_Available(b, count)) {
/* limit the buffer to prevent overwriting */
if (FIFO_Available(b, count) && buffer) {
while (count) {
b->buffer[b->head % b->buffer_len] = *data_bytes;
index = b->head % b->buffer_len;
b->buffer[index] = *buffer;
b->head++;
data_bytes++;
buffer++;
count--;
}
status = true;
@@ -220,14 +296,14 @@ bool FIFO_Add(
return status;
}
/****************************************************************************
* DESCRIPTION: Flushes any data in the buffer
* RETURN: none
* ALGORITHM: none
* NOTES: none
*****************************************************************************/
void FIFO_Flush(
FIFO_BUFFER * b)
/**
* Flushes any data in the FIFO buffer
*
* @param b - pointer to FIFO_BUFFER structure
*
* @return none
*/
void FIFO_Flush(FIFO_BUFFER * b)
{
unsigned head; /* used to avoid volatile decision */
@@ -237,18 +313,20 @@ void FIFO_Flush(
}
}
/****************************************************************************
* DESCRIPTION: Configures the ring buffer
* RETURN: none
* ALGORITHM: none
* NOTES: buffer_len must be a power of two
*****************************************************************************/
void FIFO_Init(
FIFO_BUFFER * b,
/**
* Initializes the FIFO buffer with a data store
*
* @param b - pointer to FIFO_BUFFER structure
* @param buffer [in] - data bytes used to store bytes used by the FIFO
* @param buffer_len [in] - size of the buffer in bytes - must be power of 2.
*
* @return none
*/
void FIFO_Init(FIFO_BUFFER * b,
volatile uint8_t * buffer,
unsigned buffer_len)
{
if (b) {
if (b && buffer && buffer_len) {
b->head = 0;
b->tail = 0;
b->buffer = buffer;
@@ -262,17 +340,19 @@ void FIFO_Init(
#include <assert.h>
#include <string.h>
#include <stdio.h>
#include "ctest.h"
/* test the FIFO */
/* note: must be a power of two! */
#define FIFO_BUFFER_SIZE 64
void testFIFOBuffer(
Test * pTest)
/**
* Unit Test for the FIFO buffer
*
* @param pTest - test tracking pointer
*/
void testFIFOBuffer(Test * pTest)
{
/* FIFO data structure */
FIFO_BUFFER test_buffer = { 0 };
volatile uint8_t data_store[FIFO_BUFFER_SIZE] = { 0 };
/* FIFO data store. Note: size must be a power of two! */
volatile uint8_t data_store[64] = { 0 };
uint8_t add_data[40] = { "RoseSteveLouPatRachelJessicaDaniAmyHerb" };
uint8_t test_add_data[40] = { 0 };
uint8_t test_data = 0;
@@ -284,7 +364,7 @@ void testFIFOBuffer(
ct_test(pTest, FIFO_Empty(&test_buffer));
/* load the buffer */
for (test_data = 0; test_data < FIFO_BUFFER_SIZE; test_data++) {
for (test_data = 0; test_data < sizeof(data_store); test_data++) {
ct_test(pTest, !FIFO_Full(&test_buffer));
ct_test(pTest, FIFO_Available(&test_buffer, 1));
status = FIFO_Put(&test_buffer, test_data);
@@ -297,7 +377,7 @@ void testFIFOBuffer(
status = FIFO_Put(&test_buffer, 42);
ct_test(pTest, status == false);
/* unload the buffer */
for (index = 0; index < FIFO_BUFFER_SIZE; index++) {
for (index = 0; index < sizeof(data_store); index++) {
ct_test(pTest, !FIFO_Empty(&test_buffer));
test_data = FIFO_Peek(&test_buffer);
ct_test(pTest, test_data == index);
@@ -313,7 +393,7 @@ void testFIFOBuffer(
ct_test(pTest, test_data == 0);
ct_test(pTest, FIFO_Empty(&test_buffer));
/* test the ring around the buffer */
for (index = 0; index < FIFO_BUFFER_SIZE; index++) {
for (index = 0; index < sizeof(data_store); index++) {
ct_test(pTest, FIFO_Empty(&test_buffer));
ct_test(pTest, FIFO_Available(&test_buffer, 4));
for (count = 1; count < 4; count++) {
@@ -381,8 +461,12 @@ void testFIFOBuffer(
}
#ifdef TEST_FIFO_BUFFER
int main(
void)
/**
* Main program entry for Unit Test
*
* @return returns 0 on success, and non-zero on fail.
*/
int main(void)
{
Test *pTest;
bool rc;