diff options
Diffstat (limited to 'Src/Multiplexer/RingBuffer.h')
-rw-r--r-- | Src/Multiplexer/RingBuffer.h | 187 |
1 files changed, 187 insertions, 0 deletions
diff --git a/Src/Multiplexer/RingBuffer.h b/Src/Multiplexer/RingBuffer.h new file mode 100644 index 0000000..29cafcd --- /dev/null +++ b/Src/Multiplexer/RingBuffer.h @@ -0,0 +1,187 @@ +/* + * Video On Demand Samples + * + * Copyright (C) 2015 Microchip Technology Germany II GmbH & Co. KG + * + * 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 3 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, see <http://www.gnu.org/licenses/>. + * + * You may also obtain this software under a propriety license from Microchip. + * Please contact Microchip for further information. + * + */ + +/*----------------------------------------------------------*/ +/*! \file + * \brief This file contains the CRingBuffer class. + */ +/*----------------------------------------------------------*/ + +#ifndef CRINGBUFFER_H +#define CRINGBUFFER_H + +#include "Console.h" + + +/*----------------------------------------------------------*/ +/*! \brief Class providing a ring buffer. One thread can +* write to the buffer while another thread is reading +* from it. This class has highest performance for +* synchronization, since it is not using mutexes. +* +* LIMITATIONS: +* - only one thread can read +* - only one thread can write +* - the ring buffer size needs to be aligned to +* read, write block size +* +* Violating any limitation will lead to unpredictable +* results. +*/ +/*----------------------------------------------------------*/ +class CRingBuffer +{ + uint8_t *m_pBuf; + uint32_t m_nWriteTot; // total bytes written to ring buffer + uint32_t m_nReadTot; // total bytes read from ring buffer + uint32_t m_nWritePos; // memory write position + uint32_t m_nReadPos; // memory read position + uint32_t m_nReadLen; // bytes per read + uint32_t m_nWriteLen; // bytes per write + uint32_t m_nBufLen; // bytes of buffer + +public: + /*----------------------------------------------------------*/ + /*! \brief constructs a ring buffer instance + * \param nReadLen - read block size in bytes + * \param nWriteLen - write block size in bytes + * \param nWriteBlocks - total buffer size counted in write + * blocks + */ + /*----------------------------------------------------------*/ + CRingBuffer(uint32_t nReadLen, uint32_t nWriteLen, uint32_t nWriteBlocks) + : m_nWriteTot(0) + , m_nReadTot(0) + , m_nWritePos(0) + , m_nReadPos(0) + , m_nReadLen(nReadLen) + , m_nWriteLen(nWriteLen) + , m_nBufLen(nWriteBlocks*nWriteLen) + { + if ( 0 != (m_nBufLen % m_nReadLen) ) { + ConsolePrintf( PRIO_ERROR, RED"! ring size needs to be dividable by read block size"RESETCOLOR); + throw (-10); + } + m_pBuf = new uint8_t[m_nBufLen]; + + if (NULL == m_pBuf) { + ConsolePrintf( PRIO_ERROR, RED"! out of memory"RESETCOLOR); + throw (-10); + } + } + + + + /*----------------------------------------------------------*/ + /*! \brief destructs ring buffer instance + */ + /*----------------------------------------------------------*/ + ~CRingBuffer() + { + delete m_pBuf; + } + + + + /*----------------------------------------------------------*/ + /*! \brief checks if there is enough memory available to + * write a chunk of data to the ring buffer + * \return true, if can be written + */ + /*----------------------------------------------------------*/ + bool GetCanWrite() + { + uint32_t nFilled = m_nWriteTot - m_nReadTot; + return nFilled < m_nBufLen - m_nWriteLen; + } + + + + /*----------------------------------------------------------*/ + /*! \brief checks if there is enough memory available to + * read a chunk of data from the ring buffer + * \return true, if can be read + */ + /*----------------------------------------------------------*/ + bool GetCanRead() + { + uint32_t nFilled = m_nWriteTot - m_nReadTot; + return nFilled >= m_nReadLen; + } + + + + /*----------------------------------------------------------*/ + /*! \brief gets pointer to current read position + * \return pointer to current read position + */ + /*----------------------------------------------------------*/ + uint8_t *GetReadPos() + { + return m_pBuf + m_nReadPos; + } + + + + /*----------------------------------------------------------*/ + /*! \brief gets pointer to current write position + * \return pointer to current write position + */ + /*----------------------------------------------------------*/ + uint8_t *GetWritePos() + { + return m_pBuf + m_nWritePos; + } + + + + /*----------------------------------------------------------*/ + /*! \brief called after a chunk of data has been written + * to the ring buffer + */ + /*----------------------------------------------------------*/ + void WriteDone() + { + m_nWriteTot += m_nWriteLen; + m_nWritePos += m_nWriteLen; + if (m_nBufLen == m_nWritePos) + m_nWritePos = 0; + } + + + + /*----------------------------------------------------------*/ + /*! \brief called after a chunk of data has been read + * from the ring buffer + */ + /*----------------------------------------------------------*/ + void ReadDone() + { + m_nReadTot += m_nReadLen; + m_nReadPos += m_nReadLen; + if (m_nBufLen == m_nReadPos) + m_nReadPos = 0; + } +}; + +#endif |