From 858adac72442c8a6fd2e62ecdcbf9ac82966754d Mon Sep 17 00:00:00 2001 From: skarg Date: Thu, 27 Nov 2008 13:06:29 +0000 Subject: [PATCH] Added FIFO library code. --- bacnet-stack/include/fifo.h | 82 ++++++++++++ bacnet-stack/src/fifo.c | 248 ++++++++++++++++++++++++++++++++++++ bacnet-stack/test/rpm.mak | 1 + 3 files changed, 331 insertions(+) create mode 100755 bacnet-stack/include/fifo.h create mode 100755 bacnet-stack/src/fifo.c diff --git a/bacnet-stack/include/fifo.h b/bacnet-stack/include/fifo.h new file mode 100755 index 00000000..184c9b1c --- /dev/null +++ b/bacnet-stack/include/fifo.h @@ -0,0 +1,82 @@ +/*####COPYRIGHTBEGIN#### + ------------------------------------------- + Copyright (C) 2008 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####*/ + +/* Functional Description: Generic FIFO library for deeply + embedded system. See the unit tests for usage examples. + This library only uses a byte sized chunk. + This library is designed for use in Interrupt Service Routines + and so is declared as "static inline" */ + +#ifndef FIFO_H +#define FIFO_H + +#include +#include + +struct fifo_buffer_t { + volatile unsigned head; /* first byte of data */ + volatile unsigned tail; /* last byte of data */ + volatile uint8_t *buffer; /* block of memory or array of data */ + unsigned buffer_len; /* length of the data */ +}; +typedef struct fifo_buffer_t FIFO_BUFFER; + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +bool FIFO_Empty( + FIFO_BUFFER const *b); + +uint8_t FIFO_Peek( + FIFO_BUFFER const *b); + +uint8_t FIFO_Get( + FIFO_BUFFER * b); + +bool FIFO_Put( + FIFO_BUFFER * b, + uint8_t data_byte); + +/* note: buffer_len must be a power of two */ +void FIFO_Init( + FIFO_BUFFER * b, + volatile uint8_t *buffer, + unsigned buffer_len); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ +#endif diff --git a/bacnet-stack/src/fifo.c b/bacnet-stack/src/fifo.c new file mode 100755 index 00000000..0c124127 --- /dev/null +++ b/bacnet-stack/src/fifo.c @@ -0,0 +1,248 @@ +/*####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####*/ + +/* Functional Description: Generic FIFO library for deeply + embedded system. See the unit tests for usage examples. */ + +#include +#include +#include +#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 +*****************************************************************************/ +static volatile unsigned FIFO_Count ( + FIFO_BUFFER const *b) +{ + return (b ? (b->head - b->tail) : 0); +} + +/**************************************************************************** +* 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 +*****************************************************************************/ +static bool FIFO_Full ( + FIFO_BUFFER const *b) +{ + return (b ? (FIFO_Count(b) == b->buffer_len) : true); +} + +/**************************************************************************** +* 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) +{ + 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) +{ + if (b) { + return (b->buffer[b->tail % b->buffer_len]); + } + + 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) +{ + uint8_t data_byte = 0; + + if (!FIFO_Empty(b)) { + data_byte = b->buffer[b->tail % b->buffer_len]; + b->tail++; + } + return data_byte; +} + +/**************************************************************************** +* DESCRIPTION: Adds an element of data to the FIFO +* RETURN: true on succesful add, false if not added +* ALGORITHM: none +* NOTES: none +*****************************************************************************/ +bool FIFO_Put( + FIFO_BUFFER * b, + uint8_t data_byte) +{ + bool status = false; /* return value */ + + if (b) { + /* limit the ring to prevent overwriting */ + if (!FIFO_Full(b)) { + b->buffer[b->head % b->buffer_len] = data_byte; + b->head++; + status = true; + } + } + + return status; +} + +/**************************************************************************** +* DESCRIPTION: Configures the ring buffer +* RETURN: none +* ALGORITHM: none +* NOTES: buffer_len must be a power of two +*****************************************************************************/ +void FIFO_Init( + FIFO_BUFFER * b, + volatile uint8_t *buffer, + unsigned buffer_len) +{ + if (b) { + b->head = 0; + b->tail = 0; + b->buffer = buffer; + b->buffer_len = buffer_len; + } + + return; +} + +#ifdef TEST +#include +#include + +#include "ctest.h" + +/* test the FIFO */ +/* note: must be a power of two! */ +#define FIFO_BUFFER_SIZE 64 +void testFIFOBuffer( + Test * pTest) +{ + FIFO_BUFFER test_buffer; + volatile uint8_t data_store[FIFO_BUFFER_SIZE]; + uint8_t test_data; + uint8_t index; + uint8_t count; + bool status; + + FIFO_Init(&test_buffer, data_store, sizeof(data_store)); + ct_test(pTest, FIFO_Empty(&test_buffer)); + + /* load the buffer */ + for (test_data = 0; test_data < FIFO_BUFFER_SIZE; test_data++) { + status = FIFO_Put(&test_buffer, test_data); + ct_test(pTest, status == true); + ct_test(pTest, !FIFO_Empty(&test_buffer)); + } + /* not able to put any more */ + status = FIFO_Put(&test_buffer, 42); + ct_test(pTest, status == false); + /* unload the buffer */ + for (index = 0; index < FIFO_BUFFER_SIZE; index++) { + ct_test(pTest, !FIFO_Empty(&test_buffer)); + test_data = FIFO_Peek(&test_buffer); + ct_test(pTest, test_data == index); + test_data = FIFO_Get(&test_buffer); + ct_test(pTest, test_data == index); + } + ct_test(pTest, FIFO_Empty(&test_buffer)); + test_data = FIFO_Get(&test_buffer); + ct_test(pTest, test_data == 0); + test_data = FIFO_Peek(&test_buffer); + 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++) { + ct_test(pTest, FIFO_Empty(&test_buffer)); + for (count = 1; count < 4; count++) { + test_data = count; + status = FIFO_Put(&test_buffer, test_data); + ct_test(pTest, status == true); + ct_test(pTest, !FIFO_Empty(&test_buffer)); + } + for (count = 1; count < 4; count++) { + ct_test(pTest, !FIFO_Empty(&test_buffer)); + test_data = FIFO_Peek(&test_buffer); + ct_test(pTest, test_data == count); + test_data = FIFO_Get(&test_buffer); + ct_test(pTest, test_data == count); + } + } + ct_test(pTest, FIFO_Empty(&test_buffer)); + + return; +} + +#ifdef TEST_FIFO_BUFFER +int main( + void) +{ + Test *pTest; + bool rc; + + pTest = ct_create("FIFO Buffer", NULL); + + /* individual tests */ + rc = ct_addTestFunction(pTest, testFIFOBuffer); + assert(rc); + + ct_setStream(pTest, stdout); + ct_run(pTest); + (void) ct_report(pTest); + + ct_destroy(pTest); + + return 0; +} +#endif +#endif diff --git a/bacnet-stack/test/rpm.mak b/bacnet-stack/test/rpm.mak index 4cd356e9..10cd06ba 100644 --- a/bacnet-stack/test/rpm.mak +++ b/bacnet-stack/test/rpm.mak @@ -15,6 +15,7 @@ SRCS = $(SRC_DIR)/bacdcode.c \ $(SRC_DIR)/bactext.c \ $(SRC_DIR)/indtext.c \ $(SRC_DIR)/datetime.c \ + $(SRC_DIR)/memcopy.c \ $(SRC_DIR)/rpm.c \ ctest.c