This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CC1101 - Buffer Indexing Gets corrupted

Other Parts Discussed in Thread: CC1101

I am working with the CC1101 and using the examples posted by TI.  I am using the Link2 example and I have modified it a little to suit my needs.  I am trying to program the board to read data from the UART and transmit that data.  I am able to send the data correctly on the first packet sent, but as I send subsequent packets, the rxBuffer does not receive the values correctly.

Here is my transmitter code:

TX

//-------------------------------------------------------------------------------------------------------
//  Global Variables
BYTE xdata buffer[8];
BYTE xdata txBuffer[258];
UINT8 state = SETUP;
// Byte array used by the intToAscii(UINT16 value) function
UINT8 xdata asciiString[6];

TX_DATA xdata txData = {
    0,          // bytesLeft
    0,          // iterations
    FALSE,      // writeRemainingDataFlag
    FALSE,      // packetSentFlag
    txBuffer,   // *pBufferIndex
    0           // packetsSent
};

// PKT_DATA xdata pktData;
//-------------------------------------------------------------------------------------------------------



void main (void) {
    // BYTE xdata menuEntry;
    // UINT16 packetsSent = 0;
    // UINT8 length;
    UINT16 xdata i;
    UINT16 xdata numberOfPackets = 1;
    // UINT16 xdata k;
    // UINT8 regCounter;
   

    #ifdef STAND_ALONE
   
        // Select the Internal Oscillator as Multiplier input source and disable the watchdog timer
        // SYSCLK = 4X Clock Multiplier / 2    
         CLOCK_INIT();
    #endif

    // Set up the crossbar and I/O ports to communicate with the SmartRF04EB peripherals
    IO_PORT_INIT();

    // Initialize the LCD display. The SMBus uses timer 0 to generate SCL
    ebLcdInit();

    // Initialize the ADC converter
    ebAdcInit(ADC_JOY);

    // 8-bit Uart with variable baudrate, logic level of stop bit is ignored. User must poll the
    // RI_0 and TI_0 flag to determine when a byte arrives or when the TX buffer is empty.
    // Timer1 is used as a baudrate generator
    halUartSetup(UART_BAUDRATE_115200, DEFAULT_MODE);

    SPI_INIT(SCLK_6_MHZ);
  
    // halUartSetup(UART_BAUDRATE_115200, DEFAULT_MODE);

    POWER_UP_RESET_CCxxx0();
   

    halRfWriteRfSettings(&rfSettings);

    //halSpiWriteReg(CCxxx0_FIFOTHR, 0x0E);   // FIFO_THR = 14
                                            // 5 bytes in TX FIFO (59 available spaces)
                                            // 60 bytes in the RX FIFO
                                            // If this threshold is changed, AVAILABLE_BYTES_IN_TX_FIFO
                                            // and BYTES_RX_FIFO (Link2.h) must be updated

    //halSpiWriteReg(CCxxx0_IOCFG1,0x2E);            // GDO1 output pin configuration
    halSpiWriteReg(CCxxx0_SYNC1,0x54);            // SYNC1        Sync Word, High Byte
    halSpiWriteReg(CCxxx0_SYNC0,0xD5);            // SYNC0        Sync Word, Low Byte
    //halSpiWriteReg(CCxxx0_CHANNR,0x00);            // Channel number
    //halSpiWriteReg(CCxxx0_MCSM2,0x00);            // Main Radio Control State Machine configuration
    //halSpiWriteReg(CCxxx0_MCSM1,0x30);            // Main Radio Control State Machine configuration
    halSpiWriteReg(CCxxx0_WOREVT1,0x87);        // WOREVT1        Time out high byte event0
    halSpiWriteReg(CCxxx0_WOREVT0,0x6B);        // WOREVT0        Time out low byte event0
    halSpiWriteReg(CCxxx0_WORCTRL,0xFB);        // WORCTRL        Wake On Radio Control       
    //halSpiWriteReg(CCxxx0_RCCTRL1,0x1F);        // RCCTRL0        RC Oscillator Configuration
    //halSpiWriteReg(CCxxx0_RCCTRL0,0x1F);        // RCCTRL0        RC Oscillator Configuration

    halSpiWriteReg(CCxxx0_PATABLE, paTable[0]);
   
    
    UART_RX_ENABLE();

    INT_PRIORITY(INUM_EXTERNAL1, INT_HIGH);

    ebLcdUpdate("Mode: TX", "Push S1 to Start");

   

    // Infinite loop
    while (TRUE) {
        // Create data packet
        switch (state)
        {
            case SETUP:
                // This wait is implemented to give the LCD display enough time to be update
                // between each iteration
                halWait(250);
                if (ebButtonPushed())
                {
                    //ENABLE_GLOBAL_INT(INT_OFF);
                    printf("Hello World\n");

                    state = TX_START;
                       
                        // Associated to the TX FIFO: Asserts when the TX FIFO is filled above TXFIFO_THR.
                        // De-asserts when the TX FIFO is below TXFIFO_THR.
                        halSpiWriteReg(CCxxx0_IOCFG2, 0x02);
         
                        SETUP_GDO2_INT(EDGE, LOW);      // Enables external interrupt on falling edge
                        SETUP_GDO0_INT(EDGE, LOW);
                        ebLcdUpdate("Button pushed", "Waiting for data");                   
                }
                _nop_(); // If this instruction is removed, IE0 might not be cleared
                INT_SETFLAG(INUM_EXTERNAL0, INT_CLR);   // Clears the interrupt flag
                INT_SETFLAG(INUM_EXTERNAL1, INT_CLR);   // Clears the interrupt flag
                ENABLE_GLOBAL_INT(INT_ON);
                break;           
               
            case TX_START:
                // Create data packet
                createDataPacket();                     

                // The TX FIFO needs to be re-filled several times
                halSpiWriteBurstReg(CCxxx0_TXFIFO, txBuffer, FIFO_SIZE); // Fill up the TX FIFO
                halSpiStrobe(CCxxx0_STX);
                for(i = 1; i <= 101; i++)
                {
                    printf ("TX %u: %X\n", i, txBuffer[i]);
                }

                txData.bytesLeft = 101 + 1 - FIFO_SIZE;
                txData.pBufferIndex = txBuffer + FIFO_SIZE;
                txData.iterations = (txData.bytesLeft / AVAILABLE_BYTES_IN_TX_FIFO);
                if (!txData.iterations)
                    txData.writeRemainingDataFlag = TRUE;
           
                // Enable external interrupt 1 (the TX FIFO will need to be re-filled in this ISR)             
                ENABLE_GLOBAL_INT(INT_OFF);
                INT_ENABLE(INUM_EXTERNAL1, INT_ON);
                INT_SETFLAG(INUM_EXTERNAL1, INT_CLR);
                ENABLE_GLOBAL_INT(INT_ON);
       
                state = TX_WAIT;

            //----------------------------------------------------------------------------------------
            case TX_WAIT:
            //----------------------------------------------------------------------------------------

                if (txData.packetSentFlag)
                {
                   
                    txData.packetSentFlag = FALSE;
                    intToAscii(++txData.packetsSent);
                    // ebLcdUpdate("Sent:", asciiString);
                    if (txData.packetsSent < numberOfPackets)
                        state = TX_START;
                    else
                    {
                        for(i = 1; i <= 101; i++)
                        {
                            printf ("TX %u: %X\n", i, txBuffer[i]);
                        }
                        halWait(1000000);
                        txData.packetsSent = 0;
                        state = SETUP;
                        ebLcdUpdate("Packets Sent", "S1 to restart");
                    }

                }
                break;

            //----------------------------------------------------------------------------------------
            default:
            //----------------------------------------------------------------------------------------
                break;
        }
    }
}


//  void createDataPacket(UINT 16)
//
//  DESCRIPTION:
//      This function is called before a packet is going to be transmitted.
//      Packet format:
//
//  |----------------------------------------------------------------------------------------------------
//  |              |               |             |             |            |             |             |
//  | Length field | Address Field |     Data    |    Data     |............|     Data    |     Data    |
//  |              |               |             |             |            |             |             |
//  |----------------------------------------------------------------------------------------------------
//          ^             ^               ^                                                      ^
//          |             |               |                                                      |
//     txBuffer[0]    txBuffer[1]    txBuffer[2]                          txBuffer[menuData.packetLength]
//-------------------------------------------------------------------------------------------------------
void createDataPacket(void)
{
    UINT16 mm;

    txBuffer[0] = ADDR;
    for (mm = 1; mm <= 101; mm++)
    {
        if(mm == 1)
            txBuffer[mm] = 0x66;
        //    UART_WAIT_AND_RECEIVE(txBuffer[i]);
        else
            txBuffer[mm] = 0x01;//rand();
    }
        // printf("Done and done");
       
    //}

} //createDataPacket

   


//-------------------------------------------------------------------------------------------------------
//  void EXTERNAL1_ISR(void)
//
//  DESCRIPTION:
//      This ISR is only enabled when the length byte is 64 or greater in TX or 62 or greater in RX.
//      In TX mode there will be an interrupt when the number of bytes in the TX FIFO goes below the threshold
//      (less than 5 bytes left in the TX FIFO) and in RX mode there will be an interrupt when there are
//      60 bytes in the RX FIFO.
//      For better understanding on how this interrupt work, please see the
//      CC1100/CC1150DK & CC2500/CC2550DK Development Kit Examples and Libraries User Manual    
//-------------------------------------------------------------------------------------------------------
void EXTERNAL1_ISR(void) interrupt INUM_EXTERNAL1 {

    //----------------------- TX MODE -----------------------

    if (txData.writeRemainingDataFlag) { // Less than 60 bytes to write to the TX FIFO
        halSpiWriteBurstReg(CCxxx0_TXFIFO, txData.pBufferIndex, txData.bytesLeft);
           
        INT_ENABLE(INUM_EXTERNAL1, INT_OFF);
           
    } else {
        halSpiWriteBurstReg(CCxxx0_TXFIFO, txData.pBufferIndex, AVAILABLE_BYTES_IN_TX_FIFO);
        txData.pBufferIndex += AVAILABLE_BYTES_IN_TX_FIFO;
        txData.bytesLeft -= AVAILABLE_BYTES_IN_TX_FIFO;
            if (!(--txData.iterations))
                txData.writeRemainingDataFlag = TRUE;
        }
    //-------------------------------------------------------



    IE1 = 0; // Clear the interrupt flag in case the interrupt flag were set while in the ISR
}// EXTERNAL_ISR




//-------------------------------------------------------------------------------------------------------
//  void EXTERNAL0_ISR(void)
//
//  DESCRIPTION:
//      In TX mode, this ISR will run when a packet has been sent. In RX mode it will run both when sync
//      is received (rising edge) and when the whole packet is received (falling edge).
//      For better understanding on how this interrupt work, please see the
//      CC1100/CC1150DK & CC2500/CC2550DK Development Kit Examples and Libraries User Manual
//-------------------------------------------------------------------------------------------------------
void EXTERNAL0_ISR(void) interrupt INUM_EXTERNAL0
{
    txData.writeRemainingDataFlag = FALSE;
    txData.packetSentFlag = TRUE;
   
}
// EXTERNAL_ISR




//-------------------------------------------------------------------------------------------------------
//  void intToAscii(UINT32 value)
//
//  DESCRIPTION:
//        Takes a 32 bits interger as input and converts it to ascii. Puts the result in the global
//      variable asciiString[]
//
//    ARGUMENTS:
//        UINT32 value
//            The value to be converted
//-------------------------------------------------------------------------------------------------------
void intToAscii(UINT16 value)
{
    UINT8 i;
    UINT8 j = 0;
    UINT8 digit_start = 0;
    UINT16 digit = 0;
    UINT32 denom = 1000000000;

    if (value == 0)
    {
        asciiString[0] = '0';
        asciiString[1] = NULL;
    }
    else
    {
        for(i = 10; i > 0; i--)
        {
            digit = value / denom;
            if((digit_start == 1) || (digit != 0))
            {
                digit_start = 1;
                value %= denom;
                asciiString[j++] = (digit + '0');
            }
            denom /= 10;
        }
        asciiString[j++] = NULL;
    }
}// intToAscii

 

Here is my receiver code:

RX

BYTE xdata buffer[8];
BYTE xdata rxBuffer[258];
UINT8 xdata state = SETUP;
// Byte array used by the intToAscii(UINT16 value) function
UINT8 xdata asciiString[6];

RX_DATA xdata rxData = {
    0,          // bytesLeft
    FALSE,      // packetReceivedFlag
    SYNC,       // syncOrEndOfPacket
    rxBuffer,   // *pBufferIndex
    0,          // lengthByte
    FALSE,      // crcOK
    0           // packetsReceived
};

//-------------------------------------------------------------------------------------------------------
void main (void) {
    UINT8 xdata numberOfPackets = 1;
    UINT8 xdata arr_size = 100;
    UINT16 xdata k;
    // UINT8 regCounter;
   
    #ifdef STAND_ALONE
   
        // Select the Internal Oscillator as Multiplier input source and disable the watchdog timer
        // SYSCLK = 4X Clock Multiplier / 2    
        CLOCK_INIT();
    #endif

    // Set up the crossbar and I/O ports to communicate with the SmartRF04EB peripherals
    IO_PORT_INIT();

    // Initialize the LCD display. The SMBus uses timer 0 to generate SCL
    ebLcdInit();

    // Initialize the ADC converter
    ebAdcInit(ADC_JOY);

    // 8-bit Uart with variable baudrate, logic level of stop bit is ignored. User must poll the
    // RI_0 and TI_0 flag to determine when a byte arrives or when the TX buffer is empty.
    // Timer1 is used as a baudrate generator
    halUartSetup(UART_BAUDRATE_115200, DEFAULT_MODE);

    SPI_INIT(SCLK_6_MHZ);

    POWER_UP_RESET_CCxxx0();
       
    halRfWriteRfSettings(&rfSettings);
    // Changed (ok)
    halSpiWriteReg(CCxxx0_SYNC1,0x54);            // SYNC1        Sync Word, High Byte
    halSpiWriteReg(CCxxx0_SYNC0,0xD5);            // SYNC0        Sync Word, Low Byte
    halSpiWriteReg(CCxxx0_CHANNR,0x00);            // Channel number
    halSpiWriteReg(CCxxx0_MCSM2,0x00);            // Main Radio Control State Machine configuration
    halSpiWriteReg(CCxxx0_MCSM1,0x30);            // Main Radio Control State Machine configuration
    halSpiWriteReg(CCxxx0_WOREVT1,0x87);        // WOREVT1        Time out high byte event0
    halSpiWriteReg(CCxxx0_WOREVT0,0x6B);        // WOREVT0        Time out low byte event0
    halSpiWriteReg(CCxxx0_WORCTRL,0xF8);        // WORCTRL        Wake On Radio Control       
    halSpiWriteReg(CCxxx0_FSCAL0,0x1F);            // Frequency synthesizer calibration
    halSpiWriteReg(CCxxx0_RCCTRL1,0x1F);        // RCCTRL0        RC Oscillator Configuration
    halSpiWriteReg(CCxxx0_RCCTRL0,0x1F);        // RCCTRL0        RC Oscillator Configuration
   

    halSpiWriteReg(CCxxx0_PATABLE, paTable[0]);

    ebLcdUpdate("Mode: Rx", "Push S1 To Rec");

    // Enable the UART receiver
    UART_RX_ENABLE();

    INT_PRIORITY(INUM_EXTERNAL1, INT_HIGH);
   
    // Infinite loop
    while (TRUE) {
        switch (state) {
           
            //----------------------------------------------------------------------------------------
            case SETUP:
            //----------------------------------------------------------------------------------------
           
                // This wait is implemented to give the LCD display enought time to be update
                // between each iteration
                halWait(250);

                if (ebButtonPushed())
                {
                   
                    ENABLE_GLOBAL_INT(INT_OFF);

                    state = RX_START;
                    ebLcdUpdate("Waiting for", "data");

                    // Associated to the RX FIFO: Asserts when RX FIFO is filled above RXFIFO_THR.
                    // De-asserts when RX FIFO is drained below RXFIFO_THR.
                    halSpiWriteReg(CCxxx0_IOCFG2, 0x00);

                    SETUP_GDO2_INT(EDGE, HIGH);     // Enables external interrupt on rising edge
                    SETUP_GDO0_INT(EDGE, HIGH);

                    _nop_(); // If this instruction is removed, IE0 might not be cleared
                    INT_SETFLAG(INUM_EXTERNAL0, INT_CLR);   // Clears the interrupt flag
                    INT_SETFLAG(INUM_EXTERNAL1, INT_CLR);   // Clears the interrupt flag
                    ENABLE_GLOBAL_INT(INT_ON);
                }
                break;           
           
            //----------------------------------------------------------------------------------------
            case RX_START:
            //----------------------------------------------------------------------------------------
                halSpiStrobe(CCxxx0_SRX);
                state = RX_WAIT;

            //----------------------------------------------------------------------------------------
            case RX_WAIT:
            //----------------------------------------------------------------------------------------

                if (rxData.packetReceivedFlag)
                {
                    rxData.packetReceivedFlag = FALSE;
                    rxData.pBufferIndex = rxBuffer;
                    if (rxData.crcOK)
                    {
                        for(k = 0; k < rxData.lengthByte; k++)
                            printf("\nReceived %u  = %X",k,rxBuffer[k]);
                       
                        ebLcdUpdate("Packet Received", "Push S1 to receive again");
                        state = SETUP;
                        halWait(10000);
                    }
                   
    
                    state = RX_START;
                   
                    // Enable external interrupt 1 in case the packet length is greater than 61 bytes.
                    // Configure external interrupt 0 to give an interrupt on rising edge (sync received)
                    ENABLE_GLOBAL_INT(INT_OFF);  
                    INT_ENABLE(INUM_EXTERNAL1, INT_ON);
                    _nop_(); // If this instruction is removed, IE1 might not be cleared
                    INT_SETFLAG(INUM_EXTERNAL1, INT_CLR);
                    SETUP_GDO0_INT(EDGE, HIGH);
                    _nop_(); // If this instruction is removed, IE0 might not be cleared
                    INT_SETFLAG(INUM_EXTERNAL0, INT_CLR);
                    ENABLE_GLOBAL_INT(INT_ON);
                }
                break;

            //----------------------------------------------------------------------------------------
            default:
            //----------------------------------------------------------------------------------------
               
                break;
        }
    }
}


//-------------------------------------------------------------------------------------------------------
//  void EXTERNAL1_ISR(void)
//
//  DESCRIPTION:
//      This ISR is only enabled when the length byte is 64 or greater in TX or 62 or greater in RX.
//      In TX mode there will be an interrupt when the number of bytes in the TX FIFO goes below the threshold
//      (less than 5 bytes left in the TX FIFO) and in RX mode there will be an interrupt when there are
//      60 bytes in the RX FIFO.
//      For better understanding on how this interrupt work, please see the
//      CC1100/CC1150DK & CC2500/CC2550DK Development Kit Examples and Libraries User Manual    
//-------------------------------------------------------------------------------------------------------
void EXTERNAL1_ISR(void) interrupt INUM_EXTERNAL1 {
    //-------------------------------------------------------

    //----------------------- RX MODE -----------------------
        // Do not empty the FIFO (See the CC1100 or 2500 Errata Note)
        halSpiReadBurstReg(CCxxx0_RXFIFO, rxData.pBufferIndex, (BYTES_IN_RX_FIFO - 1));
        rxData.bytesLeft -= (BYTES_IN_RX_FIFO - 1);   
        rxData.pBufferIndex += (BYTES_IN_RX_FIFO - 1);

    //-------------------------------------------------------

    IE1 = 0; // Clear the interrupt flag in case the interrupt flag were set while in the ISR
}// EXTERNAL_ISR




//-------------------------------------------------------------------------------------------------------
//  void EXTERNAL0_ISR(void)
//
//  DESCRIPTION:
//      In TX mode, this ISR will run when a packet has been sent. In RX mode it will run both when sync
//      is received (rising edge) and when the whole packet is received (falling edge).
//      For better understanding on how this interrupt work, please see the
//      CC1100/CC1150DK & CC2500/CC2550DK Development Kit Examples and Libraries User Manual
//-------------------------------------------------------------------------------------------------------
void EXTERNAL0_ISR(void) interrupt INUM_EXTERNAL0 {

    if (rxData.syncOrEndOfPacket == SYNC) {

        // After the sync word is received one needs to wait some time before there will be any data
        // in the FIFO.In addition, the FIFO should not be emptied
        // (See the CC1100 or 2500 Errata Note) before the whole packet has been
        // received.
        halWait(70); // Allow for 2 bytes to be put in the FIFO (2*8*(1/250000)) = 64 us

        if (PACKET_INT) { // If this pin has gone low again, one can assume that the lenght byte
                          // was 0 (nothing was put in the RX FIFO)
            rxData.lengthByte = 101;
            rxData.bytesLeft = rxData.lengthByte + 2;
            rxData.syncOrEndOfPacket = END_OF_PACKET;

            if (rxData.bytesLeft < FIFO_SIZE)

                // Disable interrupt on threshold since it is room for the whole packet in the FIFO
                INT_ENABLE(INUM_EXTERNAL1, INT_OFF);
        
            SETUP_GDO0_INT(EDGE, LOW);  // Enables external interrupt on falling edge (packet received)
            _nop_();                    // If this instruction is removed, IE0 might not be cleared
            INT_SETFLAG(INUM_EXTERNAL0, INT_CLR);
        }
    } else { // End of Packet
        halSpiReadBurstReg(CCxxx0_RXFIFO, rxData.pBufferIndex, rxData.bytesLeft);
        rxBuffer[0] = rxData.lengthByte;
        rxData.syncOrEndOfPacket = SYNC;
        rxData.packetReceivedFlag = TRUE;
        rxData.crcOK = TRUE;
    }
//------------------------------------------------------- 

}// EXTERNAL_ISR

The output that I see is this on the first packet:

 

on the next packet, this is the output that I see:

 

I have checked the txBuffer after the packet transmission and the packet indexing does not seem to change. This is the output that I see:

 

Somewhere along the line I am messing up my receive buffer indexing and I can't seem to figure it out.  Has anyone encountered something similar to this?

Thanks for your help in advance.

-Jon

  • Hi again Jon,

    This problem may probably not be caused by the CC1101 itself. To exclude this, please flush the RX buffer after each received packet, or check the remaining bytes in the RX fifo after a received packet. Can you tell what settings you use like;

    Packet mode,
    Packet length,
    CRC16 checksum,
    Addressing

    kind regards,

    Rick 

  • Normal 0 false false false EN-US X-NONE X-NONE MicrosoftInternetExplorer4

    Rick,

    Again, thank you for the very prompt response.  The mode that I am using for the packets is as follows:

    • FEC enabled
    • No CRC
    • Whitening enabled
    • Packet Length = 101
    • No addressing detection
    • Status appended

    These are the things that I can think of immediately.  Is there a configuration in particular that you are curious about?

    Also, I have tried flushing both the RX and TX buffers after a packet has been sent, but I see the same results.  Am I doing something wrong with my pointers then?

    Thanks,

    Jon

  • I can not answer accurately because i am at home right now and not at work. But can you verify that the status byte is received. If so, you should probably set your packet length on the receiver side 1 byte longer, as the status byte will not automaticly be removed from your packet.

  • Rick,

    Thank you again for your help.  Again, this was a stupid mistake on my part.  I had a script that sent commands to the UART, but I did not account for the check sum bits.  Also, I wasn't calculating how many bytes I really needed, so I was sending too many bytes to the UART.  As a result, I had data that was left in the UART buffer and causing all my data to be shifted by one index.  After I fixed this, I was getting the correct output.

    I was wondering, do you know how I can flush the UART buffer?

    Thanks again,

    Jon

  • Dear Jon,

    that strongly depends on the micro controller you use, but somehow there always is an command or register on the host side (micro controller) to flush the buffer. 

    kind regards,

    Rick