123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668 |
- /**
- * \file
- *
- * \brief This file controls the software FIFO management.
- *
- * These functions manages FIFOs thanks to simple a API. The FIFO can
- * be 100% full thanks to a double-index range implementation. For example,
- * a FIFO of 4 elements can be implemented: the FIFO can really hold up to 4
- * elements.
- * This is particularly well suited for any kind of application needing a lot of
- * small FIFO.
- *
- * Copyright (c) 2010-2015 Atmel Corporation. All rights reserved.
- *
- * \asf_license_start
- *
- * \page License
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice,
- * this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * 3. The name of Atmel may not be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * 4. This software may only be redistributed and used in connection with an
- * Atmel microcontroller product.
- *
- * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
- * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
- * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
- * POSSIBILITY OF SUCH DAMAGE.
- *
- * \asf_license_stop
- *
- */
- /*
- * Support and FAQ: visit <a href="http://www.atmel.com/design-support/">Atmel Support</a>
- */
- #ifndef _FIFO_H_
- #define _FIFO_H_
- #include "compiler.h"
- /**
- * \defgroup fifo_group First-In-First-Out Buffer (FIFO)
- *
- * See \ref fifo_quickstart.
- *
- * These functions manages FIFOs thanks to simple a API. The FIFO can
- * be 100% full thanks to a double-index range implementation. For example,
- * a FIFO of 4 elements can be implemented: the FIFO can really hold up to 4
- * elements. This is particularly well suited for any kind of application
- * needing a lot of small FIFO. The maximum fifo size is 128 items (uint8,
- * uint16 or uint32). Note that the driver, thanks to its conception, does
- * not use interrupt protection.
- *
- * @{
- */
- //! Error codes used by FIFO driver.
- enum {
- FIFO_OK = 0, //!< Normal operation.
- FIFO_ERROR_OVERFLOW, //!< Attempt to push something in a FIFO that is full.
- FIFO_ERROR_UNDERFLOW, //!< Attempt to pull something from a FIFO that is empty
- FIFO_ERROR, //!< Error condition during FIFO initialization
- };
- //! FIFO descriptor used by FIFO driver.
- struct fifo_desc {
- union
- {
- uint32_t *u32ptr; //!< Pointer to unsigned-32 bits location
- uint16_t *u16ptr; //!< Pointer to unsigned-16 bits location
- uint8_t *u8ptr; //!< Pointer to unsigned-8 bits location
- } buffer;
- volatile uint8_t read_index; //!< Read index
- volatile uint8_t write_index; //!< Write index
- uint8_t size; //!< Size of the FIFO (unit is in number of 'element')
- uint8_t mask; //!< Mask used to speed up FIFO operation (wrapping)
- };
- typedef struct fifo_desc fifo_desc_t;
- /**
- * \brief Initializes a new software FIFO for a certain 'size'.
- *
- * \pre Both fifo descriptor and buffer must be allocated by the caller before.
- *
- * \param fifo_desc Pointer on the FIFO descriptor.
- * \param buffer Pointer on the FIFO buffer.
- * \param size Size of the buffer (unit is in number of 'elements').
- * It must be a 2-power and <= to 128.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR when the size is not a 2-power.
- */
- int fifo_init(fifo_desc_t *fifo_desc, void *buffer, uint8_t size);
- /**
- * \brief Returns the number of elements in the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return The number of used elements.
- */
- static inline uint8_t fifo_get_used_size(fifo_desc_t *fifo_desc)
- {
- return ((fifo_desc->write_index - fifo_desc->read_index) & fifo_desc->mask);
- }
- /**
- * \brief Returns the remaining free spaces of the FIFO (in number of elements).
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return The number of free elements.
- */
- static inline uint8_t fifo_get_free_size(fifo_desc_t *fifo_desc)
- {
- return fifo_desc->size - fifo_get_used_size(fifo_desc);
- }
- /**
- * \brief Tests if a FIFO is empty.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return Status
- * \retval true when the FIFO is empty.
- * \retval false when the FIFO is not empty.
- */
- static inline bool fifo_is_empty(fifo_desc_t *fifo_desc)
- {
- return (fifo_desc->write_index == fifo_desc->read_index);
- }
- /**
- * \brief Tests if a FIFO is full.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return Status
- * \retval true when the FIFO is full.
- * \retval false when the FIFO is not full.
- */
- static inline bool fifo_is_full(fifo_desc_t *fifo_desc)
- {
- return (fifo_get_used_size(fifo_desc) == fifo_desc->size);
- }
- /**
- * \brief Puts a new 8-bits element into the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- */
- static inline void fifo_push_uint8_nocheck(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u8ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- }
- /**
- * \brief Puts a new 8-bits element into the FIFO and
- * checks for a possible overflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_push_uint8(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- if (fifo_is_full(fifo_desc)) {
- return FIFO_ERROR_OVERFLOW;
- }
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u8ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- return FIFO_OK;
- }
- /**
- * \brief Puts a new 16-bits element into the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- */
- static inline void fifo_push_uint16_nocheck(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u16ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- }
- /**
- * \brief Puts a new 16-bits element into the FIFO and
- * checks for a possible overflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_push_uint16(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- if (fifo_is_full(fifo_desc)) {
- return FIFO_ERROR_OVERFLOW;
- }
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u16ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- return FIFO_OK;
- }
- /**
- * \brief Puts a new 32-bits element into the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- */
- static inline void fifo_push_uint32_nocheck(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u32ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- }
- /**
- * \brief Puts a new 32-bits element into the FIFO and
- * checks for a possible overflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_push_uint32(fifo_desc_t *fifo_desc, uint32_t item)
- {
- uint8_t write_index;
- if (fifo_is_full(fifo_desc)) {
- return FIFO_ERROR_OVERFLOW;
- }
- write_index = fifo_desc->write_index;
- fifo_desc->buffer.u32ptr[write_index & (fifo_desc->mask >> 1)] = item;
- write_index = (write_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->write_index = write_index;
- return FIFO_OK;
- }
- /**
- * \brief Gets a 8-bits element from the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return extracted element.
- */
- static inline uint8_t fifo_pull_uint8_nocheck(fifo_desc_t *fifo_desc)
- {
- uint8_t read_index;
- uint8_t item;
- read_index = fifo_desc->read_index;
- item = fifo_desc->buffer.u8ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return item;
- }
- /**
- * \brief Gets a 8-bits element from the FIFO and
- * checks for a possible underflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_pull_uint8(fifo_desc_t *fifo_desc, uint8_t *item)
- {
- uint8_t read_index;
- if (fifo_is_empty(fifo_desc)) {
- return FIFO_ERROR_UNDERFLOW;
- }
- read_index = fifo_desc->read_index;
- *item = fifo_desc->buffer.u8ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return FIFO_OK;
- }
- /**
- * \brief Gets a 16-bits element from the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return extracted element.
- */
- static inline uint16_t fifo_pull_uint16_nocheck(fifo_desc_t *fifo_desc)
- {
- uint8_t read_index;
- uint16_t item;
- read_index = fifo_desc->read_index;
- item = fifo_desc->buffer.u16ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return item;
- }
- /**
- * \brief Gets a 16-bits element from the FIFO and
- * checks for a possible underflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_pull_uint16(fifo_desc_t *fifo_desc, uint16_t *item)
- {
- uint8_t read_index;
- if (fifo_is_empty(fifo_desc)) {
- return FIFO_ERROR_UNDERFLOW;
- }
- read_index = fifo_desc->read_index;
- *item = fifo_desc->buffer.u16ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return FIFO_OK;
- }
- /**
- * \brief Gets a 32-bits element from the FIFO
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \return extracted element.
- */
- static inline uint32_t fifo_pull_uint32_nocheck(fifo_desc_t *fifo_desc)
- {
- uint8_t read_index;
- uint32_t item;
- read_index = fifo_desc->read_index;
- item = fifo_desc->buffer.u32ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return item;
- }
- /**
- * \brief Gets a 32-bits element from the FIFO and
- * checks for a possible underflow.
- *
- * \param fifo_desc The FIFO descriptor.
- * \param item extracted element.
- *
- * \return Status
- * \retval FIFO_OK when no error occurred.
- * \retval FIFO_ERROR_UNDERFLOW when the FIFO was empty.
- */
- static inline int fifo_pull_uint32(fifo_desc_t *fifo_desc, uint32_t *item)
- {
- uint8_t read_index;
- if (fifo_is_empty(fifo_desc)) {
- return FIFO_ERROR_UNDERFLOW;
- }
- read_index = fifo_desc->read_index;
- *item = fifo_desc->buffer.u32ptr[read_index & (fifo_desc->mask >> 1)];
- read_index = (read_index + 1) & fifo_desc->mask;
- // Must be the last thing to do.
- barrier();
- fifo_desc->read_index = read_index;
- return FIFO_OK;
- }
- /**
- * \brief Gets a 32-bits element from the FIFO but does
- * not remove it from the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \retval item extracted element.
- */
- static inline uint32_t fifo_peek_uint32(fifo_desc_t *fifo_desc)
- {
- return fifo_desc->buffer.u32ptr[fifo_desc->read_index & (fifo_desc->mask >> 1)];
- }
- /**
- * \brief Gets a 16-bits element from the FIFO but does
- * not remove it from the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \retval item extracted element.
- */
- static inline uint16_t fifo_peek_uint16(fifo_desc_t *fifo_desc)
- {
- return fifo_desc->buffer.u16ptr[fifo_desc->read_index & (fifo_desc->mask >> 1)];
- }
- /**
- * \brief Gets a 8-bits element from the FIFO but does
- * not remove it from the FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- *
- * \retval item extracted element.
- */
- static inline uint8_t fifo_peek_uint8(fifo_desc_t *fifo_desc)
- {
- return fifo_desc->buffer.u8ptr[fifo_desc->read_index & (fifo_desc->mask >> 1)];
- }
- /**
- * \brief Flushes a software FIFO.
- *
- * \param fifo_desc The FIFO descriptor.
- */
- static inline void fifo_flush(fifo_desc_t *fifo_desc)
- {
- // Fifo starts empty.
- fifo_desc->read_index = fifo_desc->write_index = 0;
- }
- /**
- * @}
- */
- /**
- * \page fifo_quickstart Quick start guide for First-In-First-Out Buffer (FIFO)
- *
- * This is the quick start guide for the \ref fifo_group, with
- * step-by-step instructions on how to configure and use the driver in a
- * selection of use cases.
- *
- * The use cases contain several code fragments. The code fragments in the
- * steps for setup can be copied into a custom initialization function, while
- * the steps for usage can be copied into, e.g., the main application function.
- *
- * \section fifo_use_cases FIFO use cases
- * - \ref fifo_basic_use_case
- * - \subpage fifo_use_case_1
- *
- * \section fifo_basic_use_case Basic use case - Push and pull
- * In this use case, an element will be pushed to the FIFO, and the same
- * element will be pulled from it.
- *
- * \section fifo_basic_use_case_setup Setup steps
- *
- * \subsection fifo_basic_use_case_setup_code Example code
- * The following must be added to the project:
- * \code
- #define FIFO_BUFFER_LENGTH 4
- #define PUSH_VALUE 0x12345678
- union buffer_element {
- uint8_t byte;
- uint16_t halfword;
- uint32_t word;
- };
- \endcode
- *
- * Add to application initialization:
- * \code
- union buffer_element fifo_buffer[FIFO_BUFFER_LENGTH];
- fifo_desc_t fifo_desc;
- fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH);
- \endcode
- *
- * \subsection fifo_basic_use_case_setup_flow Workflow
- * -# Create a FIFO buffer of FIFO_BUFFER_LENGTH elements, capable
- * of holding a byte, halfword or word:
- * - \code union buffer_element fifo_buffer[FIFO_BUFFER_LENGTH]; \endcode
- * -# Create a FIFO buffer descriptor that contains information about the
- * location of the FIFO buffer, its size and where to read from or write to
- * upon the next buffer pull or push:
- * - \code fifo_desc_t fifo_desc; \endcode
- * -# Initialize the FIFO:
- * - \code fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH); \endcode
- *
- * \section fifo_basic_use_case_usage Usage steps
- *
- * \subsection fifo_basic_use_case_usage_code Example code
- * Add to application C-file:
- * \code
- uint8_t status;
- uint8_t pull_value;
- status = fifo_push_uint8(&fifo_desc, PUSH_VALUE & 0xff);
- status = fifo_pull_uint8(&fifo_desc, &pull_value);
- \endcode
- *
- * \subsection fifo_basic_use_case_usage_flow Workflow
- * -# Create a variable to hold the return status from the FIFO:
- * - \code uint8_t status; \endcode
- * -# Create a variable to hold the pulled value from the FIFO:
- * - \code uint8_t pull_value; \endcode
- * -# Put a new 8-bit element into the FIFO:
- * - \code status = fifo_push_uint8(&fifo_desc, PUSH_VALUE & 0xff); \endcode
- * \note The status variable will contain \ref FIFO_OK if no error occurred.
- * -# Get the 8-bit element from the FIFO:
- * - \code status = fifo_pull_uint8(&fifo_desc, &pull_value); \endcode
- * \note The status variable will contain \ref FIFO_OK if no error occurred.
- */
- /**
- * \page fifo_use_case_1 Push and flush
- *
- * In this use case, two elements will be pushed to the FIFO, and the FIFO
- * will be flushed.
- *
- * \section fifo_use_case_1_setup Setup steps
- *
- * \subsection fifo_use_case_1_setup_code Example code
- * The following must be added to the project:
- * \code
- #define FIFO_BUFFER_LENGTH 4
- #define PUSH_VALUE 0x12345678
- union buffer_element {
- uint8_t byte;
- uint16_t halfword;
- uint32_t word;
- };
- \endcode
- *
- * Add to application initialization:
- * \code
- union buffer_element fifo_buffer[FIFO_BUFFER_LENGTH];
- fifo_desc_t fifo_desc;
- fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH);
- \endcode
- *
- * \subsection fifo_use_case_1_setup_flow Workflow
- * -# Create a FIFO buffer of FIFO_BUFFER_LENGTH elements, capable
- * of holding a byte, halfword or word:
- * - \code union buffer_element fifo_buffer[FIFO_BUFFER_LENGTH]; \endcode
- * -# Create a FIFO buffer descriptor that containing information about the
- * location of the FIFO buffer, its size and where to read from or write to
- * upon the next buffer pull or push:
- * - \code fifo_desc_t fifo_desc; \endcode
- * -# Initialize the FIFO:
- * - \code fifo_init(&fifo_desc, fifo_buffer, FIFO_BUFFER_LENGTH); \endcode
- * \section fifo_use_case_1_usage Usage steps
- *
- * \subsection fifo_use_case_1_usage_code Example code
- * Add to application C-file:
- * \code
- uint8_t status;
- bool fifo_empty;
- status = fifo_push_uint16(&fifo_desc, PUSH_VALUE & 0xffff);
- status = fifo_push_uint16(&fifo_desc, PUSH_VALUE & 0xffff);
- fifo_flush(&fifo_desc);
- fifo_empty = fifo_is_empty(&fifo_desc);
- \endcode
- *
- * \subsection fifo_use_case_1_usage_flow Workflow
- * -# Create a variable to hold the return status from the FIFO:
- * - \code uint8_t status; \endcode
- * -# Create a variable to hold the pulled value from the FIFO:
- * - \code uint16_t pull_value; \endcode
- * -# Put two new 16-bit element into the FIFO:
- * - \code status = fifo_push_uint16(&fifo_desc, PUSH_VALUE & 0xffff); \endcode
- * - \code status = fifo_push_uint16(&fifo_desc, PUSH_VALUE & 0xffff); \endcode
- * \note The status variable will contain \ref FIFO_OK if no error occurred.
- * -# Flush the FIFO:
- * - \code fifo_flush(&fifo_desc); \endcode
- * -# Check that the FIFO is empty after flushing:
- * - \code fifo_empty = fifo_is_empty(&fifo_desc); \endcode
- * \note The fifo_empty variable will be true if the FIFO is empty.
- */
- #endif // _FIFO_H_
|