QRSS Rx Network receiver. A receiver to sample a segment of RF spectrum and send this data to a server for further processing and display. NXP mbed Design Challenge entry (Honorable Mention). Published in Circuit Cellar, Feb 2012
Dependencies: NetServices mbed DNSResolver
BufferSys.h
- Committer:
- claytong
- Date:
- 2012-01-25
- Revision:
- 0:82ff15078322
File content as of revision 0:82ff15078322:
/*--------------------------------------------------------------------------- QRSS Receiver Application by Clayton ZL3TKA/VK1TKA clayton@isnotcrazy.com Header File for Buffer System Designed to buffer 32 bit I/Q samples ---------------------------------------------------------------------------*/ #ifndef _BUFFERSYS_H #define _BUFFERSYS_H #include "mbed.h" #include "global.h" // Definitions #ifndef BUFFERSYS_SIZE #define BUFFERSYS_SIZE 512 #endif // // Structures // //--------------------------------------------------------------------------- // // A Sample structure // The single data sample point // typedef struct _data_sample { int32_t iQData; int32_t iIData; } TDataSample; // Long samples - more bit sizes // Not used by the buffers, but available for other parts in the system typedef struct _long_data_sample { int64_t iQData; int64_t iIData; } TLongDataSample; extern const TDataSample NullSample; // // Classes // // Forward references class TBufferPool; //--------------------------------------------------------------------------- // // A Buffer Data Class // The actual thing that holds the sample data // class TBufferData { // create/destroy public: // creates the buffer TBufferData() : iLength(0), pNext(NULL), iRefCount(0), pPool(NULL) {} // delete the buffer ~TBufferData() {} // API public: // Check the reference count // Any operation that changes a buffer's data (or provides a write pointer) MUST check // iRefCount and throw exception if not = 1 inline void CheckRefCount( void ) const { if ( iRefCount != 1 ) error( "TBufferData::CheckRefCount RefCount not equal to 1\r\n" ); } // Clear the buffer void Clear( void ) { iLength = 0; } // Append a sample bool Append( const TDataSample *pSample ) { CheckRefCount(); // Check for overflows if ( iLength>=BUFFERSYS_SIZE ) return false; // no room // Append the data asSamples[iLength] = *pSample; iLength ++; return true; } // Remove samples form the end of the buffer // Fails if there are not enough samples to remove bool Remove( int iSamples ) { CheckRefCount(); if ( iSamples<0 ) error( "TBufferData::Remove Invalid remove number\r\n" ); // Check for underflow if ( iLength<iSamples ) { // underflow - remove all anyway iLength = 0; return false; } // adjust the length iLength -= iSamples; return true; } // data private: // the buffer TDataSample asSamples[BUFFERSYS_SIZE]; // data size count int iLength; // current samples count // a pointer for queuing TBufferData *pNext; // a reference counter for counting holders of this buffer int iRefCount; // a timestamp of the sample capture uint32_t uiTimestamp; // a pointer to this buffers pool (to return it too) TBufferPool *pPool; // the pool that the buffer came from #ifdef BUFFER_DEBUG // details of buffer ownership (for debugging only) bool bQueued; // the buffer is in a queue bool bPooled; // the buffer is in a pool (unused buffer) #endif //Declare the buffer classes as friendly //so it can access the protected members of buffers. friend class TBufferHandle; friend class TBufferQueue; friend class TBufferPool; }; //--------------------------------------------------------------------------- // // A Buffer Handle Class // Something that holds a buffer // Can also be the base class for something that processes a buffer // class TBufferHandle { // create/destroy public: TBufferHandle() : pMyBuffer( NULL ) {} virtual ~TBufferHandle() { // release any attached buffer Release(); } // buffer attached/release public: // test if the handle has a buffer attached inline bool HasBuffer( void ) const { if ( pMyBuffer != NULL ) return true; return false; } protected: // attached a buffer to the handle bool Attach( TBufferData * pBuffer ) { // release any old buffer Release(); // Attach the buffer to the handler if ( pBuffer != NULL ) { pMyBuffer = pBuffer; // Increment the reference count of the buffer pMyBuffer->iRefCount++; return true; } return false; } // debug - check that a buffer is attached inline void CheckForBuffer( void ) const { if ( pMyBuffer == NULL ) error( "TBufferHandle::CheckForBuffer Handle does not have a buffer attached\r\n" ); } public: // transfer a buffer from another handle bool TransferBuffer( TBufferHandle & Handle ) { // attach buffer from other handle if ( !Attach(Handle.pMyBuffer) ) return false; // release buffer from the other handle Handle.Release(); return true; } // release the buffer from the handle void Release( void ); // Set the timestamp void Timestamp( uint32_t uiTime ) { if ( HasBuffer() ) pMyBuffer->uiTimestamp = uiTime; } // Read the timestamp uint32_t Timestamp() { if ( HasBuffer() ) return pMyBuffer->uiTimestamp; return 0; } // buffer manipulation public: // append a sample bool Append( const TDataSample &Sample ) { CheckForBuffer(); return pMyBuffer->Append( &Sample ); } // Remove characters form the end of the buffer // Fails if there are not enough bytes to remove bool Remove( int iBytes ) { CheckForBuffer(); return pMyBuffer->Remove( iBytes ); } // Clear the buffer void Clear( void ) { CheckForBuffer(); pMyBuffer->Clear(); } // set buffer length (after data has been manually added) void SetLength( int iLen ) { if ( HasBuffer() ) { if ( iLen<0 ) iLen = 0; if ( iLen>BUFFERSYS_SIZE ) iLen = BUFFERSYS_SIZE; pMyBuffer->iLength = iLen; } } // buffer examination public: // get buffer length int Length( void ) const { if ( !HasBuffer() ) return 0; return pMyBuffer->iLength; } // get buffer size int Size( void ) const { if ( !HasBuffer() ) return 0; return BUFFERSYS_SIZE; } int Room( void ) const { if ( !HasBuffer() ) return 0; return ( BUFFERSYS_SIZE - pMyBuffer->iLength ); } // get a pointer to the buffer data TDataSample * SamplePtr( int iIndex=0 ) { if ( !HasBuffer() ) return NULL; // no buffer if ( iIndex>pMyBuffer->iLength ) return NULL; // index past end of buffer return &(pMyBuffer->asSamples[iIndex]); } // get buffer data (note that there is no way to detect failure) const TDataSample operator []( int iIndex ) const { if ( HasBuffer() && (iIndex<pMyBuffer->iLength) && (iIndex>=0) ) return pMyBuffer->asSamples[iIndex]; return NullSample; // otherwise return empty sample } // data protected: // pointer to the buffer being references to TBufferData *pMyBuffer; friend class TBufferQueue; friend class TBufferPool; }; //--------------------------------------------------------------------------- // // A Buffer Queue // A queue of buffers // class TBufferQueue { // create/destroy public: TBufferQueue() : pFront(NULL), pBack(NULL), iCount(0) {} virtual ~TBufferQueue() { // release all buffer Flush(); } // queue manipulation public: // peek at the front buffer on the queue, but still leave the buffer there // (buffer must not be editted) bool Peek( TBufferHandle &Handle ) const { // attached the buffer to the handle return Handle.Attach( pFront ); // Attach also inc ref count } // remove the first buffer from the queue and return in the handle bool Read( TBufferHandle &Handle ) { // release any old buffers Handle.Release(); // check for any buffers if ( iCount<=0 ) return false; //Nothing in queue // get the front buffer TBufferData * pRemovedBuffer = pFront; if ( pRemovedBuffer==NULL ) error( "TBufferQueue::Read queue pFront pointer!\r\n" ); // adjust the queue ptrs RemovePtrFromQueue(); #ifdef BUFFER_DEBUG // reset queued flag pRemovedBuffer->bQueued = false; #endif // no RefCount adjustment needed - buffer is added to handle but release from the queue // Manually put the buffer into the (empty) handle Handle.pMyBuffer = pRemovedBuffer; return true; } // Write a buffer into the queue, removing it from the handle bool Write( TBufferHandle &Handle ) { // check there is a buffer if ( !Handle.HasBuffer() ) return false; // Buffer is manually moved (Reference counter is untouched) // Add msg ptr to the queue (does not adjust the reference counter) AddPtrToQueue( Handle.pMyBuffer ); // Flag the buffer as queued #ifdef BUFFER_DEBUG Handle.pMyBuffer->bQueued = true; #endif // no RefCount adjustment needed - buffer is added to queue but release from the handle // Manually remove the buffer from the handle Handle.pMyBuffer = NULL; return true; } // Return number of queued buffers int Count() const { return iCount; } // Test if empty bool Empty() const { return (iCount==0); } // strip all buffers from the queue bool Flush( void ) { // check for buffers to flush if ( iCount==0 ) return false; // read and release buffers until no more to read TBufferHandle MsgHandle; while ( Read(MsgHandle) ) { // release the buffers MsgHandle.Release(); } return true; } // internal methods protected: // Add the buffer to the end of the queue // Does not do any checks etc or adjust buffer reference count void AddPtrToQueue( TBufferData *pMsg ) { pMsg->pNext = NULL; if ( iCount == 0 ) { // Queue is currently empty // Front = back = buffer pFront = pMsg; pBack = pMsg; iCount = 1; } else { // Add the buffer to the back of the queue pBack->pNext = pMsg; pBack = pMsg; iCount++; } } // Remove a pointer from the front of the queue // Does not do any checks etc or adjust buffer reference count - just removes pointer void RemovePtrFromQueue( void ) { // adjust the queue if ( iCount<=1 ) { // Empty queue pFront = NULL; pBack = NULL; iCount=0; } else { // Remove first item pFront = pFront->pNext; // Decrement the number of buffers in the queue iCount--; } } // data protected: TBufferData *pFront; // front of the queue (out point) TBufferData *pBack; // back of the queue (in point) int iCount; // number of items in the queue friend class TBufferHandle; }; //--------------------------------------------------------------------------- // // A Buffer Pool // A pool of free buffers // class TBufferPool : protected TBufferQueue { // create/destroy public: // create an pool and optionally add buffers to it off the stack TBufferPool( int iNumMsgs=0 ) : iBuffCount(0) { if (iNumMsgs>0) CreateBuffers( iNumMsgs ); } // destroy a pool and all of its internal methods virtual ~TBufferPool() { // delete all buffers TBufferHandle MsgHandle; while ( Read(MsgHandle) ) { // delete the TBufferData delete MsgHandle.pMyBuffer; // clear the buffer handle MsgHandle.pMyBuffer = NULL; } } // pool setup public: // Add buffers to the pool // Buffers are created off the heap bool CreateBuffers( int iNumMsgs ) { TBufferData * pBuff; // Loop and create msgs while ( iNumMsgs>0 ) { //printf( "Creating buffer %d\r\n", iBuffCount ); // Create the new buffer pBuff = new TBufferData; if ( pBuff==NULL ) return false; // add the buffer to the pool pBuff->pPool = this; ReturnToPool( pBuff ); iBuffCount++; iNumMsgs--; } return true; } // add a new buffer to the pool - // either as a buffer (with or without a data structure) // or as a data structure with a buffer void AddNewMsgToPool( TBufferData & Buffer ) { Buffer.pPool = this; ReturnToPool( &Buffer ); iBuffCount++; } // add an array of buffers to the pool void AddNewMsgsToPool( TBufferData *pBuffer, int iCount ) { while ( iCount>0 ) { AddNewMsgToPool( *pBuffer ); pBuffer++; iCount--; } } // place or return a buffer in the pool void ReturnToPool( TBufferData * pBuffer ) { // Add to the queue (does not adjust the reference counter) AddPtrToQueue( pBuffer ); // zero reference (should already be the case) pBuffer->iRefCount = 0; #ifdef BUFFER_DEBUG // Flag the buffer as pooled pBuffer->bPooled = true; #endif } // Message Handling public: // buffer creation - takes a msg from the pool bool Create( TBufferHandle &Handle ) { // read the buffer from the queue if ( !Read(Handle) ) return false; // inc ref count (RefCount is 0 in pool, and Read does not adjust it) Handle.pMyBuffer->iRefCount++; #ifdef BUFFER_DEBUG // reset pool flag Handle.pMyBuffer->bPooled = false; #endif // Initialise the buffer Handle.Clear(); Handle.pMyBuffer->uiTimestamp = 0; return true; } // Pool Status public: // return number of buffers available int Available() const { return iCount; } // data protected: int iBuffCount; // number of buffers installed in the pool friend class TBufferData; friend class TBufferHandle; }; #endif //--------------------------------------------------------------------------- // END //---------------------------------------------------------------------------