/** * Initialization function for the UART1 peripheral. * Should be called in initialization code for the * model. This function configures the UART * for whatever baud rate is specified. It also configures two circular buffers * for transmission and reception. */ void Uart1Init(uint16_t brgRegister) { // First initialize the necessary circular buffers. CB_Init(&uart1RxBuffer, u1RxBuf, sizeof(u1RxBuf)); CB_Init(&uart1TxBuffer, u1TxBuf, sizeof(u1TxBuf)); // Configure and open the port; // U1MODE Register // ============== U1MODEbits.UARTEN = 0; // Disable the port U1MODEbits.USIDL = 0; // Stop on idle U1MODEbits.IREN = 0; // No IR decoder U1MODEbits.RTSMD = 0; // Ready to send mode (irrelevant) U1MODEbits.UEN = 0; // Only RX and TX U1MODEbits.WAKE = 1; // Enable at startup U1MODEbits.LPBACK = 0; // Disable loopback U1MODEbits.ABAUD = 0; // Disable autobaud U1MODEbits.URXINV = 0; // Normal operation (high is idle) U1MODEbits.PDSEL = 0; // No parity 8 bit U1MODEbits.STSEL = 0; // 1 stop bit U1MODEbits.BRGH = 0; // Low speed mode // U1STA Register // ============== U1STAbits.URXISEL = 0; // RX interrupt when a single char enters the buffer.s U1STAbits.UTXISEL0 = 1; U1STAbits.UTXISEL1 = 0; // TX interrupt when FIFO buffer is empty. There's no reason to // interrupt after every byte, so this reduces the number of // interrupts. U1STAbits.OERR = 0; // clear overun error U1BRG = brgRegister; // Set the baud rate register // Finally setup interrupts for proper UART communication. IPC3bits.U1TXIP = 6; // Interrupt priority 6 IPC2bits.U1RXIP = 6; // Interrupt priority 6 IEC0bits.U1TXIE = 1; // Enable transmission interrupt IEC0bits.U1RXIE = 1; // Enable reception interrupt // Enable the port; U1MODEbits.UARTEN = 1; // Enable the port U1STAbits.UTXEN = 1; // Enable TX }
/** * Initialization function for the UART2 peripheral. * Should be called in initialization code for the * model. This function configures the UART * for whatever baud rate is specified. It also configures two circular buffers * for transmission and reception. */ void initUart2(unsigned int brgRegister) { // Initialize our circular buffers. If this fails, we crash and burn. if (!CB_Init(&uart2RxBuffer, rxDataArray, ARRAYSIZE)) { while (1); } if (!CB_Init(&uart2TxBuffer, txDataArray, ARRAYSIZE)) { while (1); } // Configure and open the port; // U2MODE Register // ============== U2MODEbits.UARTEN = 0; // Disable the port U2MODEbits.USIDL = 0; // Stop on idle U2MODEbits.IREN = 0; // No IR decoder U2MODEbits.RTSMD = 0; // Ready to send mode (irrelevant) U2MODEbits.UEN = 0; // Only RX and TX U2MODEbits.WAKE = 1; // Enable at startup U2MODEbits.LPBACK = 0; // Disable loopback U2MODEbits.ABAUD = 0; // Disable autobaud U2MODEbits.URXINV = 0; // Normal operation (high is idle) U2MODEbits.PDSEL = 0; // No parity 8 bit U2MODEbits.STSEL = 0; // 1 stop bit U2MODEbits.BRGH = 0; // Low speed mode // U2STA Register // ============== U2STAbits.URXISEL = 2; // RX interrupt when 3 chars are in U2STAbits.OERR = 0; // clear overun error U2BRG = brgRegister; // Set the baud rate register // Finally setup interrupts for proper UART communication. IPC7bits.U2TXIP = 6; // Interrupt priority 6 IPC7bits.U2RXIP = 6; // Interrupt priority 6 IEC1bits.U2TXIE = 1; // Enable transmission interrupt IEC1bits.U2RXIE = 1; // Enable reception interrupt // Enable the port; U2MODEbits.UARTEN = 1; // Enable the port U2STAbits.UTXEN = 1; // Enable TX }
/** * Initialization function for the UART2 peripheral. Should be called in initialization code for the * model. This function configures the UART for whatever baud rate is specified. It also configures * two circular buffers for transmission and reception. * * This function can be called again to re-initialize the UART. This clears all relevant registers * and reinitializes values to 0. */ void Uart2Init(uint16_t brgRegister) { // First initialize the necessary circular buffers. CB_Init(&uart2RxBuffer, u2RxBuf, sizeof(u2RxBuf)); CB_Init(&uart2TxBuffer, u2TxBuf, sizeof(u2TxBuf)); // If the UART was already opened, close it first. This should also clear the transmit/receive // buffers so we won't have left-over data around when we re-initialize, if we are. CloseUART2(); // Configure and open the port. OpenUART2(UART_EN & UART_IDLE_CON & UART_IrDA_DISABLE & UART_MODE_FLOW & UART_UEN_00 & UART_EN_WAKE & UART_DIS_LOOPBACK & UART_DIS_ABAUD & UART_NO_PAR_8BIT & UART_UXRX_IDLE_ONE & UART_BRGH_SIXTEEN & UART_1STOPBIT, UART_INT_TX_LAST_CH & UART_IrDA_POL_INV_ZERO & UART_SYNC_BREAK_DISABLED & UART_TX_ENABLE & UART_INT_RX_CHAR & UART_ADR_DETECT_DIS & UART_RX_OVERRUN_CLEAR, brgRegister ); // Setup interrupts for proper UART communication. Enable both TX and RX interrupts at // priority level 6 (arbitrary). ConfigIntUART2(UART_RX_INT_EN & UART_RX_INT_PR6 & UART_TX_INT_EN & UART_TX_INT_PR6); }
return_value_t http_init() { http_state.parser = malloc_dbg(sizeof(http_parser),10); parser = http_state.parser; http_parser_init(parser,HTTP_REQUEST); http_state.parser_settings = malloc_dbg(sizeof(http_parser_settings),11); settings = http_state.parser_settings; settings->on_body = 0; settings->on_header_field = 0; settings->on_header_value = 0; settings->on_headers_complete = 0; settings->on_message_begin = 0; settings->on_message_complete = 0; settings->on_status_complete = 0; settings->on_url = 0; http_state.num_requests = 0; http_state.json_parser = malloc_dbg(sizeof(jsmn_parser),44); json_parser = http_state.json_parser; if(parser == NULL || settings == NULL || json_parser == NULL){ //could not allocate parser, error http_state.init_return = RET_ERROR; } else { http_state.init_return = RET_OK; } if(http_state.init_return == RET_OK){ if(CB_Init(&http_state.rx_buffer,http_rx_buffer,HTTP_RX_BUFFER_SIZE*sizeof(xbee_rx_ip_packet_t))!=SUCCESS){ http_state.init_return = RET_ERROR; } else { http_state.init_return = RET_OK; } } if(http_state.init_return == RET_OK){ rf_add_ip_rx_packet_handler(http_handle_rx_packet); } return http_state.init_return; }
int main(void) { /*Enable interrupts*/ INTCON2bits.GIE = 1; //disabled by the bootloader, so we must absolutely enable this!!! asm("CLRWDT"); //clear watchdog timer for (torque = 0; torque < 65533; torque++) { Nop(); } InitBoard(&ADCBuff, &uartBuffer, &spiBuffer, EventChecker); if (can_motor_init()) { while (1); } CB_Init(&uartBuffer, uartBuf, 32); CB_Init(&spiBuffer, (uint8_t *) spiBuf, 128); LED1 = 1; LED2 = 0; LED3 = 1; LED4 = 1; #ifdef POSITION /* This is used for testing */ // SetPosition(incPos); #endif #ifdef VELOCITY SetVelocity(0); #endif while (1) { if (events & EVENT_UPDATE_SPEED) { PMSM_Update_Position(); events &= ~EVENT_UPDATE_SPEED; } if (events & EVENT_CAN) { can_process(); // LED2 = !LED2; if (txreq_bitarray & 0b00000001 && !C1TR01CONbits.TXREQ0) { C1TR01CONbits.TXREQ0 = 1; txreq_bitarray = txreq_bitarray & 0b11111110; } if (txreq_bitarray & 0b00000010 && !C1TR01CONbits.TXREQ1) { C1TR01CONbits.TXREQ1 = 1; txreq_bitarray = txreq_bitarray & 0b11111101; } if (txreq_bitarray & 0b00000100 && !C1TR23CONbits.TXREQ2) { C1TR23CONbits.TXREQ2 = 1; txreq_bitarray = txreq_bitarray & 0b11111011; } if (txreq_bitarray & 0b00001000 && !C1TR23CONbits.TXREQ3) { C1TR23CONbits.TXREQ3 = 1; txreq_bitarray = txreq_bitarray & 0b11110111; } if (txreq_bitarray & 0b00010000 && !C1TR45CONbits.TXREQ4) { C1TR45CONbits.TXREQ4 = 1; txreq_bitarray = txreq_bitarray & 0b11101111; } if (txreq_bitarray & 0b00100000 && !C1TR45CONbits.TXREQ5) { C1TR45CONbits.TXREQ5 = 1; txreq_bitarray = txreq_bitarray & 0b11011111; } if (txreq_bitarray & 0b01000000 && !C1TR67CONbits.TXREQ6) { C1TR67CONbits.TXREQ6 = 1; txreq_bitarray = txreq_bitarray & 0b10111111; } SetPosition(((float) CO(position_control_Commanded_Position)) * 109. / 1000.); CO(state_Current_Position) = CO(position_control_Commanded_Position); can_time_dispatch(); events &= ~EVENT_CAN; } if (events & EVENT_UART_DATA_READY) { events &= ~EVENT_UART_DATA_READY; } if (events & EVENT_SPI_RX) { static uint8_t message[32]; uint16_t size; uint8_t out[56]; message[0] = 0xFF; message[1] = 0xFF; message[2] = 0xFF; message[3] = 0xFF; message[4] = 0xFF; message[5] = 0xFF; message[6] = 0xFF; message[7] = 0xFF; CB_ReadByte(&spiBuffer, &message[0]); CB_ReadByte(&spiBuffer, &message[1]); CB_ReadByte(&spiBuffer, &message[2]); CB_ReadByte(&spiBuffer, &message[3]); CB_ReadByte(&spiBuffer, &message[4]); CB_ReadByte(&spiBuffer, &message[5]); CB_ReadByte(&spiBuffer, &message[6]); CB_ReadByte(&spiBuffer, &message[7]); CB_Init(&spiBuffer, &spiBuf, 64); events &= ~EVENT_SPI_RX; } if (events & EVENT_REPORT_FAULT) { events &= ~EVENT_REPORT_FAULT; } } }
int main(void) { // Watchdog Timer Enabled/disabled by user software // (LPRC can be disabled by clearing SWDTEN bit in RCON registe // Configure Oscillator to operate the device at 40Mhz // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2 // Fosc= 8M*40/(2*2)=80Mhz for 8M input clock PLLFBD = 38; // M=40 CLKDIVbits.PLLPOST = 0; // N1=2 CLKDIVbits.PLLPRE = 0; // N2=2 OSCTUN = 0; // Tune FRC oscillator, if FRC is used RCONbits.SWDTEN = 0; /* Disable Watch Dog Timer*/ // Clock switch to incorporate PLL __builtin_write_OSCCONH(0x03); // Initiate Clock Switch to Primary // Oscillator with PLL (NOSC=0b011) __builtin_write_OSCCONL(0x01); // Start clock switching while (OSCCONbits.COSC != 0b011); // Wait for Clock switch to occur while (OSCCONbits.LOCK != 1) { }; /* Wait for PLL to lock*/ // bufferPointer = NULL; Uart2Init(InterruptRoutine); if (!CB_Init(&circBuf, cbData, CB_SIZE)) FATAL_ERROR(); // Generate a fake input to record to the circular buffer // give beginning and end special characters unsigned char goodData[512]; int i; for (i=0; i<512; i++) { goodData[i] = (char)i; } goodSum = checksum(goodData, 512); Uart2PrintStr("Begin.\n"); file = NewSDInit("newfile.txt"); int SDConnected = 0; while(1) { // if (bufferPointer != NULL) { TODO implement this? // CB_WriteMany(&circBuf, bufferPointer, UART2_BUFFER_SIZE, 1); // the 1 is arbitrary // bufferPointer = NULL; // } if (SD_IN) { // if the board was just plugged in try to reinitialize if(!SDConnected) { MEDIA_INFORMATION * Minfo; do { Minfo = MDD_MediaInitialize(); } while(Minfo->errorCode == MEDIA_CANNOT_INITIALIZE); SDConnected = 1; } // When we are connected and initialized, poll the buffer, if there // is data, write it. unsigned char outData[SD_SECTOR_SIZE]; if (CB_PeekMany(&circBuf, outData, SD_SECTOR_SIZE)){ if(NewSDWriteSector(file, outData)){ // Remove the data we just written. if(checksum(outData, 512) != goodSum) { FATAL_ERROR(); } CB_Remove(&circBuf, SD_SECTOR_SIZE); } } } else { SDConnected = 0; } } }
/** * @brief Run various unit tests confirming proper operation of the CircularBuffer. * * To run (assuming all files in the same directory and that's your current directory): * ``` * $ gcc CircularBuffer.c -DUNIT_TEST_CIRCULAR_BUFFER -Wall -g * $ a.out * Running unit tests. * All tests passed. * $ */ int main() { printf("Running unit tests.\n"); // These tests check the ability of the circular buffer to write a single item and // then read it back. { // Create a new circular buffer. CircularBuffer b; uint16_t size = 256; uint8_t *buffer = (uint8_t*)malloc(256*sizeof(uint8_t)); CB_Init(&b, buffer, size); assert(!b.dataSize); // Add a single item and check. CB_WriteByte(&b, 0x56); assert(b.dataSize == 1); uint8_t peekval; assert(CB_Peek(&b, &peekval)); assert(peekval == 0x56); // Remove that item and check. uint8_t d; assert(CB_ReadByte(&b, &d) && d == 0x56); assert(b.dataSize == 0); assert(CB_Peek(&b, &peekval) == 0); free(buffer); } /* This tests the ability of the buffer to read and write many items. This code also tests writing two and reading from a buffer which has been wrapped around. Deeppeek is tested. */ { // Create a new circular buffer. CircularBuffer b; uint16_t size = 256; uint8_t *buffer = (uint8_t*)malloc(256*sizeof(uint8_t)); CB_Init(&b, buffer, size); assert(!b.dataSize); // Here we make a 1016 int8_t long string for testing. Testing with the library with BUFFER_SIZE // set to larger than 1016 will produce errors. int8_t testString[] = "Copyright (C) <year> <copyright holders> Permission is hereby granted, free of int8_tge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THEAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."; // Fill the buffer to SIZE+1 and check. uint16_t i; for (i = 0; i < b.staticSize; ++i) { assert(b.dataSize == i); assert(CB_WriteByte(&b, testString[i])); assert(b.dataSize == i + 1); } assert(!CB_WriteByte(&b, 0x89)); assert(b.overflowCount == 1); // Run a deepPeek on the now-full buffer. uint8_t tmpString[b.staticSize]; assert(CB_PeekMany(&b, tmpString, b.staticSize)); assert(b.dataSize == b.staticSize); i = 0; while(i < 256){ ++i; } assert(memcmp(testString, tmpString, b.staticSize) == 0); assert(b.dataSize); // Verify reading of an entire circular-buffer uint8_t d; i = b.dataSize; while (i > 0) { assert(CB_ReadByte(&b, &d)); assert(d == testString[b.staticSize - i]); i--; } assert(b.dataSize == 0); d = 0x77; int8_t d2 = d; assert(!CB_ReadByte(&b, &d)); assert(d == d2); //nothing has been read // Test element insertion when the buffer wraps around. uint8_t peekval; assert(CB_WriteByte(&b, 91)); assert(b.overflowCount == 1); // Overflow is triggered on an earlier test assert(b.dataSize == 1); CB_Peek(&b, &peekval); assert(peekval == 91); assert(CB_WriteByte(&b, 92)); assert(b.dataSize == 2); assert(CB_WriteByte(&b, 93)); assert(b.dataSize == 3); assert(CB_WriteByte(&b, 94)); assert(b.dataSize == 4); // Test DeepPeek on wrapped-around buffers uint8_t peekData[4]; assert(CB_PeekMany(&b, peekData, 4)); assert(peekData[0] == 91); assert(peekData[1] == 92); assert(peekData[2] == 93); assert(peekData[3] == 94); // Test reading now. assert(CB_ReadByte(&b, &d) && d == 91); assert(CB_ReadByte(&b, &d) && d == 92); assert(CB_ReadByte(&b, &d) && d == 93); assert(CB_ReadByte(&b, &d) && d == 94); assert(!CB_ReadByte(&b, &d) && d == 94); free(buffer); } /* This section of test code checks that CB_Init will not initialize a buffer if its arguments are not valid. */ { //Test initialization with invalid arguments CircularBuffer b; uint8_t *buffer = (uint8_t*)malloc(256*sizeof(uint8_t)); assert(CB_Init(&b, buffer, 0) == false); //checks the invalid argument size = 0 assert(CB_Init(&b, buffer, 1) == false); //checks the invalid argument size = 1 assert(CB_Init(&b, buffer, 128) == true); //checks that the function returns true upon true buffer = NULL; assert(CB_Init(&b, buffer, 16) == false); //tests the invalid argument where buffer is a null pointer free(buffer); } /* This code tests the buffer at the edge case size is two. */ { //Test functionality at edge case size is 2 uint8_t CBtestbuf[2]; CircularBuffer b; CB_Init(&b, CBtestbuf, 2); //creates a new buffer of length two assert(!b.dataSize); // Add a single item and check. uint8_t peekval; CB_WriteByte(&b, 0x56); assert(b.dataSize == 1); CB_Peek(&b, &peekval); assert(peekval == 0x56); // Remove that item and check. uint8_t e; assert(CB_ReadByte(&b, &e) && e == 0x56); assert(b.dataSize == 0); assert(CB_Peek(&b, &peekval) == 0); //Now write two characters to the buffer assert(CB_WriteByte(&b, 0x56)); assert(CB_WriteByte(&b, 0x58)); assert(b.dataSize == 2); //Check to see if the length is correct CB_WriteByte(&b, 0x59); //Write a third element to the two bit buffer assert(b.overflowCount == 1); //Check that overflow has occurred assert(CB_ReadByte(&b, &e) && e == 0x56); //Check Reading an element assert(b.dataSize == 1); //Check the length of the buffer assert(CB_ReadByte(&b, &e) && e == 0x58); //Check Reading an element assert(b.dataSize == 0); //Check that the buffer is now empty assert(CB_ReadByte(&b, &e) == false); //checks that the empty buffer cannot be read from } /* This code tests the edge case where the buffer is at the maximum size. The size is limited by the maximum value which can be held in a uint16_t. */ { //Test functionality at edge case size is UINT16_MAX CircularBuffer b; uint8_t *buffertwo = (uint8_t*)malloc(UINT16_MAX*sizeof(uint8_t)); CB_Init(&b, buffertwo, UINT16_MAX); assert(!b.dataSize); assert(b.staticSize == UINT16_MAX); // Here we use the same UINT16_MAX int8_character long string for testing. Testing with the library with BUFFER_SIZE // set to larger than UINT16_MAX will produce errors. uint8_t testStringtwo[b.staticSize+1]; int i; for (i = 0; i < b.staticSize; ++i) { testStringtwo[i] = i; } // Fill the buffer to SIZE+1 and check for (i = 0; i < b.staticSize; ++i) { assert(b.dataSize == i); assert(CB_WriteByte(&b, i)); assert(b.dataSize == i + 1); } assert(!CB_WriteByte(&b, 0x89)); assert(b.overflowCount == 1); // Run a deepPeek on the now-full buffer. uint8_t tmpStringtwo[b.staticSize]; assert(CB_PeekMany(&b, tmpStringtwo, b.staticSize)); assert(b.dataSize == b.staticSize); assert(memcmp(testStringtwo, tmpStringtwo, b.staticSize) == 0); // Verify reading of an entire circular-buffer uint8_t d; for (i = b.dataSize; i > 0; --i) { assert(CB_ReadByte(&b, &d)); assert(d == testStringtwo[b.staticSize - i]); } assert(b.dataSize == 0); d = 0x77; int8_t d3 = d; assert(!CB_ReadByte(&b, &d)); assert(d == d3); assert(!b.dataSize); // Test element insertion when the buffer wraps around. uint8_t peekval; assert(CB_WriteByte(&b, 91)); assert(b.overflowCount == 1); // Overflow is triggered on an earlier test assert(b.dataSize == 1); CB_Peek(&b, &peekval); assert(peekval == 91); assert(CB_WriteByte(&b, 92)); assert(b.dataSize == 2); assert(CB_WriteByte(&b, 93)); assert(b.dataSize == 3); assert(CB_WriteByte(&b, 94)); assert(b.dataSize == 4); // Test DeepPeek on wrapped-around buffers uint8_t peekDatatwo[4]; assert(CB_PeekMany(&b, peekDatatwo, 4)); assert(peekDatatwo[0] == 91); assert(peekDatatwo[1] == 92); assert(peekDatatwo[2] == 93); assert(peekDatatwo[3] == 94); // Test reading now. assert(CB_ReadByte(&b, &d) && d == 91); assert(CB_ReadByte(&b, &d) && d == 92); assert(CB_ReadByte(&b, &d) && d == 93); assert(CB_ReadByte(&b, &d) && d == 94); assert(!CB_ReadByte(&b, &d) && d == 94); free(buffertwo); } /* This tests the remove function */ { /**Test Remove Function*/ CircularBuffer b; uint8_t CBtestbuften[10]; CB_Init(&b, CBtestbuften, 10); //creates a new buffer of length ten assert(!b.dataSize); int i; i = 0; while(i < 9){ CB_WriteByte(&b, i); ++i; } //Test removing a valid number of items assert(b.dataSize == 9); assert(CB_Remove(&b, 4)); assert(b.dataSize == 5); uint8_t d; CB_ReadByte(&b, &d); assert(d == 4); //Test removing more items than are in the buffer assert(b.dataSize == 4); CB_Remove(&b, 10); assert(b.dataSize == 0); //The buffer is now empty } /* This tests using the CB_ReadMany function to read a buffer. */ { /**Test reading multiple values from the buffer using CB_ReadMany */ CircularBuffer b; uint8_t CBtestbufthirty[30]; CB_Init(&b, CBtestbufthirty, 30); //creates a new buffer of length thirty assert(!b.dataSize); int i = 0; while(i < 30){ CB_WriteByte(&b, i); ++i; } assert(b.dataSize == 30); uint8_t readresults[30]; assert(CB_ReadMany(&b,readresults, 15)); i = 0; while(i < 15){ assert(readresults[i] == i); ++i; } assert(b.dataSize == 15); assert(CB_ReadMany(&b,readresults, 15)); assert(b.dataSize == 0); //Checks that buffer is now empty assert(b.readIndex == b.writeIndex); //checks that the pointers are equal } /* This tests using CB_WriteMany to write to a buffer. */ { /**Testing the WriteMany function*/ CircularBuffer b; uint8_t CBtestbufthirty[30]; CB_Init(&b, CBtestbufthirty, 30); //re-initializes buffer of length thirty assert(!b.dataSize); uint8_t readresults[100]; int i = 0; while (i < 100) { readresults[i] = i; ++i; } assert(CB_WriteMany(&b, readresults, 22, true)); //write 22 values from readresults to the buffer assert(b.dataSize == 22); uint8_t d; i = 0; while (i < 22) { CB_ReadByte(&b, &d); assert(d == i); ++i; } CB_Init(&b, CBtestbufthirty, 30); //re-initializes buffer of length thirty assert(!b.dataSize); assert(b.readIndex == b.writeIndex); i = 0; while (i < 30) { readresults[i] = i; ++i; } CB_WriteMany(&b, readresults, 22, false); //write 22 values from readresults to the buffer assert(b.dataSize == 22); i = 0; while (i < 22) { CB_ReadByte(&b, &d); assert(d == i); ++i; } /**Now test the failure criteria specified in failEarly*/ CB_Init(&b, CBtestbufthirty, 30); //re-initializes buffer of length thirty CB_WriteMany(&b, readresults, 18, true); assert(b.dataSize == 18); assert(CB_WriteMany(&b, readresults, 50, true) == false); //Writing more than the buffer can hold returns an error assert(b.dataSize == 18); // Checks that nothing was written assert(!CB_WriteMany(&b, readresults, 100, false)); // Now without the size check assert(b.dataSize == 30); //Checks that buffer is now full assert(b.overflowCount == 88); //100-(30-18) = 88 elements have overflowed i = 0; while (i < 18) { CB_ReadByte(&b, &d); assert(i == d); ++i; } while (i < 12) { CB_ReadByte(&b, &d); assert(i == d); ++i; } } /* This code tests using the CB_WriteMany and CB_ReadMany functions to read and write structures to a buffer. CB_PeekMany is also tested. */ { // The test circular buffer CircularBuffer c; //Testing writing of a structure to the buffer and reading it back // Create a new circular buffer. TestStruct t1 = {6, 42, 1.5}; uint16_t sizetwo = 256*sizeof(TestStruct); uint8_t structbuff[sizetwo]; assert(CB_Init(&c, structbuff, sizetwo)); //Creates a buffer to hold 256 TestStruct structures assert(!c.dataSize); CB_WriteMany(&c, &t1, sizeof(TestStruct), true); assert(c.dataSize == sizeof(TestStruct)); TestStruct f; CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the structure back from the buffer assert(!c.dataSize); //the buffer is now empty assert(TestStructEqual(&f, &t1)); TestStruct t2 = {56, 700, 5.75}; //filled with arbitrary values //Write a single structure to the buffer and then read it back assert(c.dataSize == 0); assert(CB_WriteMany(&c, &t2, sizeof(TestStruct), true)); assert(c.dataSize == sizeof(TestStruct)); assert(CB_ReadMany(&c, &f, sizeof(TestStruct))); //read the structure back from the buffer assert(TestStructEqual(&f, &t2)); //Write two structures to the buffer and then read them back CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); assert(c.dataSize == 2*sizeof(TestStruct)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); assert(c.readIndex == c.writeIndex); //The buffer is now empty. // Write four structures to the buffer using a loop and read them back. CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); assert(c.dataSize == 4*sizeof(TestStruct)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); assert(c.dataSize == 3*sizeof(TestStruct)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); assert(c.dataSize == 2*sizeof(TestStruct)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read third the structure back from the buffer assert(TestStructEqual(&f, &t1)); assert(c.dataSize == 1*sizeof(TestStruct)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the fourth structure back from the buffer assert(TestStructEqual(&f, &t2)); assert(c.dataSize == 0); //the buffer is now empty // Now write six structures and then read them off using a loop. CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); int i = 0; while (i < 3) { CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); ++i; } //Now write from a loop and read from a loop i = 0; while (i < 3) { CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); ++i; } i = 0; while (i < 3) { CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); ++i; } assert(c.readIndex == c.writeIndex); //the buffer is empty //Now write 40 elements from a loop and read 40 elements from a loop i = 0; while (i < 20) { CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); ++i; } i = 0; while (i < 20) { CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); ++i; } //Now try to overfill a buffer and then read the structures back //C is length 256*sizeof(TestStruct) so we will try to write 260 structures assert(c.readIndex == c.writeIndex); //the buffer is empty assert(c.dataSize == 0); i = 0; while (i < 130) { //writes 260 structures to the buffer CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_WriteMany(&c, &t2, sizeof(TestStruct), true); ++i; } i = 0; while (i < 128) { CB_ReadMany(&c, &f, sizeof(TestStruct)); //read first the structure back from the buffer assert(TestStructEqual(&f, &t1)); CB_ReadMany(&c, &f, sizeof(TestStruct)); //read the second structure back from the buffer assert(TestStructEqual(&f, &t2)); ++i; } assert(c.readIndex == c.writeIndex); //the buffer is empty assert(c.dataSize == 0); //Testing CB_PeekMany on structures TestStruct peekTest; CB_WriteMany(&c, &t1, sizeof(TestStruct), true); CB_PeekMany(&c, (uint8_t*)&peekTest, sizeof(TestStruct)); assert(TestStructEqual(&t1, &peekTest)); } { // Test writing and reading from the circular buffer. Showed a failure mode of the CircularBuffer with regards to its read index. CircularBuffer circBuf; unsigned char data[20]; unsigned char testIn[20] = "Hey There This Test"; unsigned char testOut[20]; // Initialize the circular buffer assert(CB_Init(&circBuf, data, 20)); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); // Write and read to the buffer multiple times CB_WriteMany(&circBuf, testIn, 20, true); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); CB_PeekMany(&circBuf, testOut, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); CB_Remove(&circBuf, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); assert(!memcmp(testIn, testOut, 20)); CB_WriteMany(&circBuf, testIn, 20, true); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); CB_PeekMany(&circBuf, testOut, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); CB_Remove(&circBuf, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 0); assert(!memcmp(testIn, testOut, 20)); //Test uneven data CB_WriteMany(&circBuf, testIn, 7, true); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 7); CB_PeekMany(&circBuf, testOut, 7); assert(circBuf.readIndex == 0); assert(circBuf.writeIndex == 7); CB_Remove(&circBuf, 7); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); //Test the full data again CB_WriteMany(&circBuf, testIn, 20, true); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); CB_PeekMany(&circBuf, testOut, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); CB_Remove(&circBuf, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); assert(!memcmp(testIn, testOut, 20)); CB_WriteMany(&circBuf, testIn, 20, true); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); CB_PeekMany(&circBuf, testOut, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); CB_Remove(&circBuf, 20); assert(circBuf.readIndex == circBuf.writeIndex); assert(circBuf.readIndex == 7); assert(circBuf.writeIndex == 7); assert(!memcmp(testIn, testOut, 20)); } printf("All tests passed.\n"); return 0; }