/* * 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 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, see . * * 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