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
00001 /*--------------------------------------------------------------------------- 00002 00003 QRSS Receiver Application 00004 00005 by Clayton ZL3TKA/VK1TKA 00006 clayton@isnotcrazy.com 00007 00008 Header File for Buffer System 00009 Designed to buffer 32 bit I/Q samples 00010 00011 ---------------------------------------------------------------------------*/ 00012 #ifndef _BUFFERSYS_H 00013 #define _BUFFERSYS_H 00014 00015 #include "mbed.h" 00016 #include "global.h" 00017 00018 // Definitions 00019 00020 #ifndef BUFFERSYS_SIZE 00021 #define BUFFERSYS_SIZE 512 00022 #endif 00023 00024 // 00025 // Structures 00026 // 00027 00028 //--------------------------------------------------------------------------- 00029 // 00030 // A Sample structure 00031 // The single data sample point 00032 // 00033 typedef struct _data_sample 00034 { 00035 int32_t iQData; 00036 int32_t iIData; 00037 } TDataSample; 00038 00039 // Long samples - more bit sizes 00040 // Not used by the buffers, but available for other parts in the system 00041 typedef struct _long_data_sample 00042 { 00043 int64_t iQData; 00044 int64_t iIData; 00045 } TLongDataSample; 00046 00047 extern const TDataSample NullSample; 00048 00049 // 00050 // Classes 00051 // 00052 00053 // Forward references 00054 class TBufferPool; 00055 00056 //--------------------------------------------------------------------------- 00057 // 00058 // A Buffer Data Class 00059 // The actual thing that holds the sample data 00060 // 00061 class TBufferData 00062 { 00063 // create/destroy 00064 public: 00065 // creates the buffer 00066 TBufferData() : 00067 iLength(0), 00068 pNext(NULL), 00069 iRefCount(0), 00070 pPool(NULL) 00071 {} 00072 // delete the buffer 00073 ~TBufferData() 00074 {} 00075 00076 // API 00077 public: 00078 00079 // Check the reference count 00080 // Any operation that changes a buffer's data (or provides a write pointer) MUST check 00081 // iRefCount and throw exception if not = 1 00082 inline void CheckRefCount( void ) const 00083 { 00084 if ( iRefCount != 1 ) 00085 error( "TBufferData::CheckRefCount RefCount not equal to 1\r\n" ); 00086 } 00087 00088 // Clear the buffer 00089 void Clear( void ) 00090 { 00091 iLength = 0; 00092 } 00093 00094 // Append a sample 00095 bool Append( const TDataSample *pSample ) 00096 { 00097 CheckRefCount(); 00098 // Check for overflows 00099 if ( iLength>=BUFFERSYS_SIZE ) 00100 return false; // no room 00101 // Append the data 00102 asSamples[iLength] = *pSample; 00103 iLength ++; 00104 return true; 00105 } 00106 00107 // Remove samples form the end of the buffer 00108 // Fails if there are not enough samples to remove 00109 bool Remove( int iSamples ) 00110 { 00111 CheckRefCount(); 00112 if ( iSamples<0 ) 00113 error( "TBufferData::Remove Invalid remove number\r\n" ); 00114 // Check for underflow 00115 if ( iLength<iSamples ) 00116 { // underflow - remove all anyway 00117 iLength = 0; 00118 return false; 00119 } 00120 // adjust the length 00121 iLength -= iSamples; 00122 return true; 00123 } 00124 00125 // data 00126 private: 00127 00128 // the buffer 00129 TDataSample asSamples[BUFFERSYS_SIZE]; 00130 00131 // data size count 00132 int iLength; // current samples count 00133 00134 // a pointer for queuing 00135 TBufferData *pNext; 00136 00137 // a reference counter for counting holders of this buffer 00138 int iRefCount; 00139 00140 // a timestamp of the sample capture 00141 uint32_t uiTimestamp; 00142 00143 // a pointer to this buffers pool (to return it too) 00144 TBufferPool *pPool; // the pool that the buffer came from 00145 00146 #ifdef BUFFER_DEBUG 00147 // details of buffer ownership (for debugging only) 00148 bool bQueued; // the buffer is in a queue 00149 bool bPooled; // the buffer is in a pool (unused buffer) 00150 #endif 00151 00152 //Declare the buffer classes as friendly 00153 //so it can access the protected members of buffers. 00154 friend class TBufferHandle; 00155 friend class TBufferQueue; 00156 friend class TBufferPool; 00157 00158 00159 }; 00160 00161 //--------------------------------------------------------------------------- 00162 // 00163 // A Buffer Handle Class 00164 // Something that holds a buffer 00165 // Can also be the base class for something that processes a buffer 00166 // 00167 class TBufferHandle 00168 { 00169 // create/destroy 00170 public: 00171 TBufferHandle() : 00172 pMyBuffer( NULL ) 00173 {} 00174 00175 virtual ~TBufferHandle() 00176 { // release any attached buffer 00177 Release(); 00178 } 00179 00180 // buffer attached/release 00181 public: 00182 // test if the handle has a buffer attached 00183 inline bool HasBuffer( void ) const 00184 { 00185 if ( pMyBuffer != NULL ) 00186 return true; 00187 return false; 00188 } 00189 00190 protected: 00191 // attached a buffer to the handle 00192 bool Attach( TBufferData * pBuffer ) 00193 { 00194 // release any old buffer 00195 Release(); 00196 00197 // Attach the buffer to the handler 00198 if ( pBuffer != NULL ) 00199 { 00200 pMyBuffer = pBuffer; 00201 // Increment the reference count of the buffer 00202 pMyBuffer->iRefCount++; 00203 return true; 00204 } 00205 return false; 00206 } 00207 // debug - check that a buffer is attached 00208 inline void CheckForBuffer( void ) const 00209 { 00210 if ( pMyBuffer == NULL ) 00211 error( "TBufferHandle::CheckForBuffer Handle does not have a buffer attached\r\n" ); 00212 } 00213 00214 public: 00215 // transfer a buffer from another handle 00216 bool TransferBuffer( TBufferHandle & Handle ) 00217 { 00218 // attach buffer from other handle 00219 if ( !Attach(Handle.pMyBuffer) ) 00220 return false; 00221 // release buffer from the other handle 00222 Handle.Release(); 00223 return true; 00224 } 00225 00226 // release the buffer from the handle 00227 void Release( void ); 00228 00229 // Set the timestamp 00230 void Timestamp( uint32_t uiTime ) 00231 { 00232 if ( HasBuffer() ) 00233 pMyBuffer->uiTimestamp = uiTime; 00234 } 00235 00236 // Read the timestamp 00237 uint32_t Timestamp() 00238 { 00239 if ( HasBuffer() ) 00240 return pMyBuffer->uiTimestamp; 00241 return 0; 00242 } 00243 00244 // buffer manipulation 00245 public: 00246 // append a sample 00247 bool Append( const TDataSample &Sample ) 00248 { 00249 CheckForBuffer(); 00250 return pMyBuffer->Append( &Sample ); 00251 } 00252 00253 // Remove characters form the end of the buffer 00254 // Fails if there are not enough bytes to remove 00255 bool Remove( int iBytes ) 00256 { 00257 CheckForBuffer(); 00258 return pMyBuffer->Remove( iBytes ); 00259 } 00260 00261 // Clear the buffer 00262 void Clear( void ) 00263 { 00264 CheckForBuffer(); 00265 pMyBuffer->Clear(); 00266 } 00267 00268 // set buffer length (after data has been manually added) 00269 void SetLength( int iLen ) 00270 { 00271 if ( HasBuffer() ) 00272 { 00273 if ( iLen<0 ) 00274 iLen = 0; 00275 if ( iLen>BUFFERSYS_SIZE ) 00276 iLen = BUFFERSYS_SIZE; 00277 pMyBuffer->iLength = iLen; 00278 } 00279 } 00280 00281 // buffer examination 00282 public: 00283 // get buffer length 00284 int Length( void ) const 00285 { 00286 if ( !HasBuffer() ) 00287 return 0; 00288 return pMyBuffer->iLength; 00289 } 00290 00291 // get buffer size 00292 int Size( void ) const 00293 { 00294 if ( !HasBuffer() ) 00295 return 0; 00296 return BUFFERSYS_SIZE; 00297 } 00298 00299 int Room( void ) const 00300 { 00301 if ( !HasBuffer() ) 00302 return 0; 00303 return ( BUFFERSYS_SIZE - pMyBuffer->iLength ); 00304 } 00305 00306 // get a pointer to the buffer data 00307 TDataSample * SamplePtr( int iIndex=0 ) 00308 { 00309 if ( !HasBuffer() ) 00310 return NULL; // no buffer 00311 if ( iIndex>pMyBuffer->iLength ) 00312 return NULL; // index past end of buffer 00313 return &(pMyBuffer->asSamples[iIndex]); 00314 } 00315 // get buffer data (note that there is no way to detect failure) 00316 const TDataSample operator []( int iIndex ) const 00317 { 00318 if ( HasBuffer() && (iIndex<pMyBuffer->iLength) && (iIndex>=0) ) 00319 return pMyBuffer->asSamples[iIndex]; 00320 return NullSample; // otherwise return empty sample 00321 } 00322 00323 // data 00324 protected: 00325 // pointer to the buffer being references to 00326 TBufferData *pMyBuffer; 00327 00328 friend class TBufferQueue; 00329 friend class TBufferPool; 00330 }; 00331 00332 //--------------------------------------------------------------------------- 00333 // 00334 // A Buffer Queue 00335 // A queue of buffers 00336 // 00337 class TBufferQueue 00338 { 00339 // create/destroy 00340 public: 00341 TBufferQueue() : 00342 pFront(NULL), 00343 pBack(NULL), 00344 iCount(0) 00345 {} 00346 00347 virtual ~TBufferQueue() 00348 { 00349 // release all buffer 00350 Flush(); 00351 } 00352 00353 // queue manipulation 00354 public: 00355 // peek at the front buffer on the queue, but still leave the buffer there 00356 // (buffer must not be editted) 00357 bool Peek( TBufferHandle &Handle ) const 00358 { // attached the buffer to the handle 00359 return Handle.Attach( pFront ); // Attach also inc ref count 00360 } 00361 00362 // remove the first buffer from the queue and return in the handle 00363 bool Read( TBufferHandle &Handle ) 00364 { 00365 // release any old buffers 00366 Handle.Release(); 00367 // check for any buffers 00368 if ( iCount<=0 ) 00369 return false; //Nothing in queue 00370 // get the front buffer 00371 TBufferData * pRemovedBuffer = pFront; 00372 if ( pRemovedBuffer==NULL ) 00373 error( "TBufferQueue::Read queue pFront pointer!\r\n" ); 00374 // adjust the queue ptrs 00375 RemovePtrFromQueue(); 00376 #ifdef BUFFER_DEBUG 00377 // reset queued flag 00378 pRemovedBuffer->bQueued = false; 00379 #endif 00380 // no RefCount adjustment needed - buffer is added to handle but release from the queue 00381 // Manually put the buffer into the (empty) handle 00382 Handle.pMyBuffer = pRemovedBuffer; 00383 return true; 00384 } 00385 00386 // Write a buffer into the queue, removing it from the handle 00387 bool Write( TBufferHandle &Handle ) 00388 { 00389 // check there is a buffer 00390 if ( !Handle.HasBuffer() ) 00391 return false; 00392 // Buffer is manually moved (Reference counter is untouched) 00393 // Add msg ptr to the queue (does not adjust the reference counter) 00394 AddPtrToQueue( Handle.pMyBuffer ); 00395 // Flag the buffer as queued 00396 #ifdef BUFFER_DEBUG 00397 Handle.pMyBuffer->bQueued = true; 00398 #endif 00399 // no RefCount adjustment needed - buffer is added to queue but release from the handle 00400 // Manually remove the buffer from the handle 00401 Handle.pMyBuffer = NULL; 00402 return true; 00403 } 00404 00405 // Return number of queued buffers 00406 int Count() const 00407 { return iCount; } 00408 00409 // Test if empty 00410 bool Empty() const 00411 { return (iCount==0); } 00412 00413 // strip all buffers from the queue 00414 bool Flush( void ) 00415 { 00416 // check for buffers to flush 00417 if ( iCount==0 ) 00418 return false; 00419 // read and release buffers until no more to read 00420 TBufferHandle MsgHandle; 00421 while ( Read(MsgHandle) ) 00422 { // release the buffers 00423 MsgHandle.Release(); 00424 } 00425 return true; 00426 } 00427 00428 // internal methods 00429 protected: 00430 // Add the buffer to the end of the queue 00431 // Does not do any checks etc or adjust buffer reference count 00432 void AddPtrToQueue( TBufferData *pMsg ) 00433 { 00434 pMsg->pNext = NULL; 00435 if ( iCount == 0 ) 00436 { // Queue is currently empty 00437 // Front = back = buffer 00438 pFront = pMsg; 00439 pBack = pMsg; 00440 iCount = 1; 00441 } 00442 else 00443 { // Add the buffer to the back of the queue 00444 pBack->pNext = pMsg; 00445 pBack = pMsg; 00446 iCount++; 00447 } 00448 } 00449 00450 // Remove a pointer from the front of the queue 00451 // Does not do any checks etc or adjust buffer reference count - just removes pointer 00452 void RemovePtrFromQueue( void ) 00453 { 00454 // adjust the queue 00455 if ( iCount<=1 ) 00456 { // Empty queue 00457 pFront = NULL; 00458 pBack = NULL; 00459 iCount=0; 00460 } 00461 else 00462 { 00463 // Remove first item 00464 pFront = pFront->pNext; 00465 // Decrement the number of buffers in the queue 00466 iCount--; 00467 } 00468 } 00469 00470 // data 00471 protected: 00472 TBufferData *pFront; // front of the queue (out point) 00473 TBufferData *pBack; // back of the queue (in point) 00474 int iCount; // number of items in the queue 00475 00476 friend class TBufferHandle; 00477 00478 00479 00480 00481 }; 00482 00483 //--------------------------------------------------------------------------- 00484 // 00485 // A Buffer Pool 00486 // A pool of free buffers 00487 // 00488 class TBufferPool : protected TBufferQueue 00489 { 00490 // create/destroy 00491 public: 00492 // create an pool and optionally add buffers to it off the stack 00493 TBufferPool( int iNumMsgs=0 ) : 00494 iBuffCount(0) 00495 { 00496 if (iNumMsgs>0) 00497 CreateBuffers( iNumMsgs ); 00498 } 00499 // destroy a pool and all of its internal methods 00500 virtual ~TBufferPool() 00501 { 00502 // delete all buffers 00503 TBufferHandle MsgHandle; 00504 while ( Read(MsgHandle) ) 00505 { 00506 // delete the TBufferData 00507 delete MsgHandle.pMyBuffer; 00508 // clear the buffer handle 00509 MsgHandle.pMyBuffer = NULL; 00510 } 00511 } 00512 00513 // pool setup 00514 public: 00515 // Add buffers to the pool 00516 // Buffers are created off the heap 00517 bool CreateBuffers( int iNumMsgs ) 00518 { 00519 TBufferData * pBuff; 00520 // Loop and create msgs 00521 while ( iNumMsgs>0 ) 00522 { 00523 //printf( "Creating buffer %d\r\n", iBuffCount ); 00524 // Create the new buffer 00525 pBuff = new TBufferData; 00526 if ( pBuff==NULL ) 00527 return false; 00528 // add the buffer to the pool 00529 pBuff->pPool = this; 00530 ReturnToPool( pBuff ); 00531 iBuffCount++; 00532 iNumMsgs--; 00533 } 00534 return true; 00535 } 00536 00537 // add a new buffer to the pool - 00538 // either as a buffer (with or without a data structure) 00539 // or as a data structure with a buffer 00540 void AddNewMsgToPool( TBufferData & Buffer ) 00541 { 00542 Buffer.pPool = this; 00543 ReturnToPool( &Buffer ); 00544 iBuffCount++; 00545 } 00546 00547 // add an array of buffers to the pool 00548 void AddNewMsgsToPool( TBufferData *pBuffer, int iCount ) 00549 { 00550 while ( iCount>0 ) 00551 { 00552 AddNewMsgToPool( *pBuffer ); 00553 pBuffer++; 00554 iCount--; 00555 } 00556 } 00557 00558 // place or return a buffer in the pool 00559 void ReturnToPool( TBufferData * pBuffer ) 00560 { 00561 // Add to the queue (does not adjust the reference counter) 00562 AddPtrToQueue( pBuffer ); 00563 // zero reference (should already be the case) 00564 pBuffer->iRefCount = 0; 00565 #ifdef BUFFER_DEBUG 00566 // Flag the buffer as pooled 00567 pBuffer->bPooled = true; 00568 #endif 00569 } 00570 00571 // Message Handling 00572 public: 00573 // buffer creation - takes a msg from the pool 00574 bool Create( TBufferHandle &Handle ) 00575 { 00576 // read the buffer from the queue 00577 if ( !Read(Handle) ) 00578 return false; 00579 // inc ref count (RefCount is 0 in pool, and Read does not adjust it) 00580 Handle.pMyBuffer->iRefCount++; 00581 #ifdef BUFFER_DEBUG 00582 // reset pool flag 00583 Handle.pMyBuffer->bPooled = false; 00584 #endif 00585 // Initialise the buffer 00586 Handle.Clear(); 00587 Handle.pMyBuffer->uiTimestamp = 0; 00588 return true; 00589 } 00590 00591 // Pool Status 00592 public: 00593 // return number of buffers available 00594 int Available() const 00595 { return iCount; } 00596 00597 // data 00598 protected: 00599 int iBuffCount; // number of buffers installed in the pool 00600 00601 friend class TBufferData; 00602 friend class TBufferHandle; 00603 00604 }; 00605 00606 00607 #endif 00608 00609 //--------------------------------------------------------------------------- 00610 // END 00611 //--------------------------------------------------------------------------- 00612
Generated on Wed Jul 13 2022 23:08:21 by 1.7.2