Index: App/Services/CommBuffers.c =================================================================== diff -u -rc91e9da338d92432930d3589a4055ebbb404c6cb -r833095dbbe2b21a989b05f48bd7ddc390ad964cb --- App/Services/CommBuffers.c (.../CommBuffers.c) (revision c91e9da338d92432930d3589a4055ebbb404c6cb) +++ App/Services/CommBuffers.c (.../CommBuffers.c) (revision 833095dbbe2b21a989b05f48bd7ddc390ad964cb) @@ -25,19 +25,20 @@ // ********** private definitions ********** -#define COMM_BUFFER_LENGTH 128 // bytes +#define COMM_BUFFER_LENGTH 512 // max bytes in each comm buffer (double if you count double buffers) +#define DOUBLE_BUFFERS 2 // need 2 buffers for double buffering // ********** private data ********** -static U32 commBufferByteCount[NUM_OF_COMM_BUFFERS][2]; // for each buffer, how many bytes does it contain? (also index to next available) -static U32 activeDoubleBuffers[NUM_OF_COMM_BUFFERS]; // for each buffer, which double buffer is being fed right now? -static U08 commBuffers[NUM_OF_COMM_BUFFERS][2][COMM_BUFFER_LENGTH]; // each is double buffered to avoid thread contention +static U32 commBufferByteCount[NUM_OF_COMM_BUFFERS][DOUBLE_BUFFERS]; // for each buffer, how many bytes does it contain? (also index to next available) +static U32 activeDoubleBuffers[NUM_OF_COMM_BUFFERS]; // for each buffer, which double buffer is being fed right now? +static U08 commBuffers[NUM_OF_COMM_BUFFERS][DOUBLE_BUFFERS][COMM_BUFFER_LENGTH]; // each is double buffered to avoid thread contention // ********** private function prototypes ********** static U32 switchDoubleBuffer( COMM_BUFFER_T buffer ); +static void getDataFromInactiveBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ); static U32 getRemainingByteCapacity( COMM_BUFFER_T buffer ); -static BOOL isCommBufferEmpty( COMM_BUFFER_T buffer ); /************************************************************************* * @brief initCommBuffers @@ -50,7 +51,7 @@ *************************************************************************/ void initCommBuffers( void ) { - S32 b,l,d; + S32 b,d,i; // reset and zero out all buffers for ( b = 0; b < NUM_OF_COMM_BUFFERS; b++ ) @@ -59,9 +60,9 @@ for ( d = 0; d < 2; d++ ) { commBufferByteCount[b][d] = 0; - for ( l = 0; l < COMM_BUFFER_LENGTH; l++ ) + for ( i = 0; i < COMM_BUFFER_LENGTH; i++ ) { - commBuffers[b][d][l] = 0; + commBuffers[b][d][i] = 0; } } } @@ -129,16 +130,15 @@ * @brief getFromCommBuffer * The getFromCommBuffer function fills a given byte array with a given \n * number of bytes from a given buffer and returns the number of bytes \n - * retrieved from the buffer. This function will always draw from the \n - * inactive double buffer. If some of the requested data is in the active \n - * double buffer, the double buffers will be switched when the inactive \n - * double buffer is emptied and the retrieve will continue to the requested \n - * number of bytes. + * retrieved from the buffer. This function will draw from the inactive \n + * double buffer first and, if needed, switch double buffers to draw the \n + * reset of the requested data. * Only one function in one thread should be calling this function for a given \n * buffer. * @details - * Inputs : commBuffers[], commBufferByteCount[] - * Outputs : commBufferByteCount[], activeDoubleBuffers[] + * Inputs : commBuffers[], commBufferByteCount[], activeDoubleBuffers[] + * Outputs : commBuffers[], commBufferByteCount[], activeDoubleBuffers[], \n + * and the given data array is populated with data from the buffer. * @param buffer : which comm buffer to retrieve data from * @param data : pointer to byte array to stuff data into * @param len : # of bytes to retrieve into given data array. @@ -151,56 +151,104 @@ // verify given buffer if ( buffer < NUM_OF_COMM_BUFFERS ) { - // check to see if requested # of bytes is in given buffer - if ( getNumberOfBytesInCommBuffer( buffer ) >= len ) + // verify size of peek + if ( ( len <= ( COMM_BUFFER_LENGTH * DOUBLE_BUFFERS ) ) && ( len <= numberOfBytesInCommBuffer( buffer ) ) ) { - // switch double buffer (now we'll read from what was active buffer and Rx interrupts will feed new active buffer) - U32 activeBuffer = switchDoubleBuffer( buffer ); + U32 activeBuffer = activeDoubleBuffers[buffer]; U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); - U32 bytesRetrieved = commBufferByteCount[buffer][inactiveBuffer]; + U32 bytesInInactiveBuffer = commBufferByteCount[buffer][inactiveBuffer]; + U32 sizeOfFirstConsumption = ( len <= bytesInInactiveBuffer ? len : bytesInInactiveBuffer ); - // ensure caller's data buffer can hold the data we have to retrieve - if ( bytesRetrieved <= 1000 ) // was maxLen + // see what we can get from inactive buffer + getDataFromInactiveBuffer( buffer, data, sizeOfFirstConsumption ); // will switch double buffers if we empty inactive buffer + // will return # of bytes consumed + result = sizeOfFirstConsumption; + // do we need more from active buffer? + if ( len > bytesInInactiveBuffer ) { - U08 *buffPtr; // buffer source for retrieved data - U08 *dstPtr; // buffer destination for retrieved data - U32 i; + U32 remNumOfBytes = len - sizeOfFirstConsumption; + U08 *remPtr = data + sizeOfFirstConsumption; - // get source pointer to start of comm buffer - buffPtr = &commBuffers[buffer][inactiveBuffer][0]; - // get destination pointer to start of given data array - dstPtr = data; - // copy source data to destination buffer - for ( i = 0; i < bytesRetrieved; i++ ) - { - *dstPtr++ = *buffPtr++; - } - // reset inactive buffer after data retrieved from it - commBufferByteCount[buffer][inactiveBuffer] = 0; - // set result to # of bytes received - result = bytesRetrieved; + getDataFromInactiveBuffer( buffer, remPtr, remNumOfBytes ); + // will return # of bytes consumed + result += remNumOfBytes; } - else // not enough space in caller's buffer + } + else // invalid peek size given + { + // TODO - s/w fault + } + } + else // invalid buffer given + { + // TODO - s/w fault + } + + return result; +} + +/************************************************************************* + * @brief peekFromCommBuffer + * The peekFromCommBuffer function fills a given byte array with a given \n + * number of bytes from a given buffer. This function does NOT consume \n + * the bytes - it only peeks at them. A call to numberOfBytesInCommBuffer() \n + * should be made before calling this function to determine how many bytes \n + * are currently in the buffer. Do not call this function with a "len" \n + * longer than what is currently in the buffer. + * @details + * Inputs : commBuffers[], commBufferByteCount[], activeDoubleBuffers[] + * Outputs : given array populated with requested # of bytes from the buffer. + * @param buffer : which comm buffer to retrieve data from + * @param data : pointer to byte array to stuff data into + * @param len : # of bytes to retrieve into given data array. + * @return the number of bytes retrieved. + *************************************************************************/ +U32 peekFromCommBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ) +{ + U32 numOfBytesPeeked = 0; + + // verify given buffer + if ( buffer < NUM_OF_COMM_BUFFERS ) + { + // verify size of peek + if ( ( len <= ( COMM_BUFFER_LENGTH * DOUBLE_BUFFERS ) ) && ( len <= numberOfBytesInCommBuffer( buffer ) ) ) + { + U32 activeBuffer = activeDoubleBuffers[buffer]; + U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 bytesInInactiveBuffer = commBufferByteCount[buffer][inactiveBuffer]; + + if ( len <= bytesInInactiveBuffer ) { - // TODO - s/w fault? + memcpy( data, &commBuffers[buffer][inactiveBuffer][0], len ); + numOfBytesPeeked = len; } + else // will need to get the rest from active buffer + { + U32 remNumOfBytes = len - bytesInInactiveBuffer; + U08 *remPtr = data + bytesInInactiveBuffer; + + memcpy( data, &commBuffers[buffer][inactiveBuffer][0], bytesInInactiveBuffer ); + memcpy( remPtr, &commBuffers[buffer][activeBuffer][0], remNumOfBytes ); + numOfBytesPeeked = bytesInInactiveBuffer + remNumOfBytes; + } } - else // buffer contains insufficient data to satisfy the request + else // invalid peek size given { - // result already set to zero + // TODO - s/w fault } } else // invalid buffer given { // TODO - s/w fault } - return result; + return numOfBytesPeeked; } + /************************************************************************* - * @brief getNumberOfBytesInCommBuffer - * The getNumberOfBytesInCommBuffer function determines how many bytes \n + * @brief numberOfBytesInCommBuffer + * The numberOfBytesInCommBuffer function determines how many bytes \n * are currently contained in a given comm buffer. Both double buffers \n * are considered for this. * @details @@ -209,7 +257,7 @@ * @param buffer : which comm buffer to get byte count for * @return the number of bytes in the given comm buffer. *************************************************************************/ -U32 getNumberOfBytesInCommBuffer( COMM_BUFFER_T buffer ) +U32 numberOfBytesInCommBuffer( COMM_BUFFER_T buffer ) { U32 result = 0; @@ -251,44 +299,59 @@ } /************************************************************************* - * @brief getRemainingByteCapacity - * The getRemainingByteCapacity function determines the remaining capacity \n - * of the given buffer. + * @brief getDataFromInactiveBuffer + * The getDataFromInactiveBuffer function retrieves a given number of bytes \n + * from the inactive buffer of a given buffer. This function should only be \n + * called by getFromCommBuffer(). Params will be pre-validated. * @details - * Inputs : commBufferByteCount[], activeDoubleBuffers[] - * Outputs : none - * @param buffer : which comm buffer to check the capacity of - * @return the number of bytes of capacity remaining in the buffer. + * Inputs : commBuffers[], activeDoubleBuffers[], commBufferByteCount[] + * Outputs : commBuffers[], activeDoubleBuffers[], commBufferByteCount[] + * @param buffer : which comm buffer get data from + * @param data : pointer to byte array to populate with data + * @param len : # of bytes to get from comm buffer + * @return none *************************************************************************/ -static U32 getRemainingByteCapacity( COMM_BUFFER_T buffer ) +static void getDataFromInactiveBuffer( COMM_BUFFER_T buffer, U08 *data, U32 len ) { - U32 result; U32 activeBuffer = activeDoubleBuffers[buffer]; + U32 inactiveBuffer = ( activeBuffer == 0 ? 1 : 0 ); + U32 bytesInInactiveBuffer = commBufferByteCount[buffer][inactiveBuffer]; - result = COMM_BUFFER_LENGTH - commBufferByteCount[buffer][activeBuffer]; + // get the requested data from inactive buffer + memcpy( data, &commBuffers[buffer][inactiveBuffer][0], len ); - return result; + if ( len < bytesInInactiveBuffer ) + { + U08 *endPtr = (&commBuffers[buffer][inactiveBuffer][0] + len); + + // move un-consumed data in inactive buffer to start of inactive buffer + memcpy( &commBuffers[buffer][inactiveBuffer][0], endPtr, (bytesInInactiveBuffer - len) ); + // reduce byte count for inactive buffer by # of bytes consumed + commBufferByteCount[buffer][inactiveBuffer] -= len; + } + else + { + // inactive buffer has been emptied so switch double buffers + switchDoubleBuffer( buffer ); // switch will zero count off inactive buffer + } } /************************************************************************* - * @brief isCommBufferEmpty - * The isCommBufferEmpty function determines whether a given comm buffer \n - * is empty. + * @brief getRemainingByteCapacity + * The getRemainingByteCapacity function determines the remaining capacity \n + * of the given buffer. * @details * Inputs : commBufferByteCount[], activeDoubleBuffers[] * Outputs : none - * @param buffer : which comm buffer to check for empty - * @return TRUE if the given comm buffer is empty, FALSE if not + * @param buffer : which comm buffer to check the capacity of + * @return the number of bytes of capacity remaining in the buffer. *************************************************************************/ -static BOOL isCommBufferEmpty( COMM_BUFFER_T buffer ) +static U32 getRemainingByteCapacity( COMM_BUFFER_T buffer ) { - BOOL result = FALSE; + U32 result; U32 activeBuffer = activeDoubleBuffers[buffer]; - if ( commBufferByteCount[buffer][activeBuffer] == 0 ) - { - result = TRUE; - } + result = COMM_BUFFER_LENGTH - commBufferByteCount[buffer][activeBuffer]; return result; }