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.

Sending Large Packets Greater Than FIFO at high baud rates

Other Parts Discussed in Thread: TEST2, CC1101

Howdy,

I know I've already posted this problem on a few other forums but they keep telling me that they aren't the right ones so I thought I would try this forum. I've been working with two CC430F6137 trying to understand the basics and learning how to make them run fast. The issue I keep having is when using the example Fixed_GT_FIFO that is given on the TI website, it runs perfectly at 915MHz and a 38kB Baudrate but when I try to change the Baudrate (preferably to 500kB) the CC430 wont send or receive the signal. Is there something I need to change besides the registers to make this work properly? I have had the 500kB baud rate working on the Fixed_LT_FIFO so i know the register settings work and its not a board issue. I've noticed in the pktRxHandler that it will not detect the CC430_STATE_RX meaning there isn't anything being written to the FIFO. But the receiver will recognize that there is an incoming signal (i.e. it starts running the received signal code but wont recognize that there is anything in the FIFO).  

The register settings used are as follows

RF_SETTINGS rfSettings = {
0x0c,  // FSCTRL1 Frequency synthesizer control.
0x00, // FSCTRL0 Frequency synthesizer control.
0x23, // FREQ2 Frequency control word, high byte.
0x31, // FREQ1 Frequency control word, middle byte.
0x3B, // FREQ0 Frequency control word, low byte.
0x0E, // MDMCFG4 Modem configuration.
0x3B,  // MDMCFG3 Modem configuration.
0x03,  // MDMCFG2 Modem configuration.
0x22, // MDMCFG1 Modem configuration.
0xF8, // MDMCFG0 Modem configuration.
0x00, // CHANNR Channel number.
0x62, // DEVIATN Modem deviation setting (when FSK modulation is enabled).
0xB6, // // FREND1 Front end RX configuration.
0x10, // FREND0 Front end TX configuration.
0x10, // MCSM0 Main Radio Control State Machine configuration.
0x1D, // FOCCFG Frequency Offset Compensation Configuration.
0x1C, // BSCFG Bit synchronization Configuration.
0xC7, // AGCCTRL2 AGC control.
0x00,  // AGCCTRL1 AGC control.
0xB0, // AGCCTRL0 AGC control.
0xEA, // FSCAL3 Frequency synthesizer calibration.
0x2A, // FSCAL2 Frequency synthesizer calibration.
0x00, // FSCAL1 Frequency synthesizer calibration.
0x1F, // FSCAL0 Frequency synthesizer calibration.
0x59, // FSTEST Frequency synthesizer calibration.
0x88, // TEST2 Various test settings.
0x31,  // TEST1 Various test settings.
0x09, // TEST0 Various test settings.
0x47, // FIFOTHR RXFIFO and TXFIFO thresholds.
0x29, // IOCFG2 GDO2 output pin configuration.
0x06, // IOCFG0 GDO0 output pin configuration. Refer to SmartRF® Studio User Manual for detailed pseudo register explanation.
0x04, // PKTCTRL1 Packet automation control.
0x05, // PKTCTRL0 Packet automation control. (5 does not work)
0x00, // ADDR Device address.
0x64, // PKTLEN Packet length.

Update: I think I've determined that the issue is due to the Timer interrupt in the ReceievePacket and TransmitPacket Sections. Under the standard Baudrate of 38k it interrupts every couple of ms to see if the remaining bytes in FIFO is under 64 or not. If I speedup the Baudrate and lower the RX_TIMER_PERIOD and TX_TIMER_PERIOD i can start increasing the baudrate a little at a time with successful results. Unfortunately as the RX_TIMER_PERIOD value started at 80 and needed to be lowered 5-10 for a 5kB increase this is not a great solution. I can set the timer's clock to the SM CLK at 1 MHz instead of the ACLK at 32kHz allowing me to get the distance on RX_TIMER_PERIOD that is needed (I think). The issue kept occurring but I was able to get a little bit faster (160kB) so I thought I would increase the clock rate again to 20MHz to try that but it didn't really get the results that I expected. The baud rate did increase but only by 8 or so kB giving me a final of 168. When transmitting above this baudrate I cannot even get the End of packet TX interrupt to signal. Anything below 168 the End of Packet TX interrupt will raise telling me that there is at least something being transmitted but if I raise the baud rate above 160 the interrupt flag never sets. 

Is there another way to transmit packets of size 100 besides using the timers (i.e. interrupts) because i think that this entire issue has to do with the interrupts not firing fast enough. It seems like even when trying to transmit that the interrupts are not occurring leading me to think they cant run fast enough for anything over 168kB.

Thanks,

Brian

  • This does not make sense, there is a FIFO "near empty" flag that the CC1101 (rf core) can produce and that is what you use.

    /TA
  • Sorry I might have explained it incorrectly. This is the original code that I am using and would like to speed it up. Whenever I increase the baudrate it will no longer go inside the final if statement (in other words txBytesLeft never equals zero).

    case CC430_STATE_TX:
    // If there's anything to transfer..
    if (freeSpaceInFifo = MIN(txBytesLeft, TxStatus & CC430_FIFO_BYTES_AVAILABLE_MASK))
    {
    txBytesLeft -= freeSpaceInFifo;

    while(freeSpaceInFifo--)
    {
    WriteSingleReg(TXFIFO, TxBuffer[txPosition]);
    txPosition++;
    }

    if(!txBytesLeft)
    {
    RF1AIES |= BIT9; // End-of-packet TX interrupt
    RF1AIFG &= ~BIT9; // clear RFIFG9
    while(!(RF1AIFG & BIT9)); // poll RFIFG9 for TX end-of-packet
    RF1AIES &= ~BIT9; // End-of-packet TX interrupt
    RF1AIFG &= ~BIT9; // clear RFIFG9
    transmitting = 0;
    recieveflag = 0;
    packetTransmit = 1;
    }
  • Brian,

    I have assigned one of my team members to take a look at the example code, fix it and provide you with working example.

    Thomas
  • Thomas,

    That would be awesome! Thanks

    Brian
  • Not sure if this will help but I noticed that when running at faster speeds the Fixed_GT_FIFO is sending the first part of the packet correctly but wont send the last little bit because its going into the Tx underflow mode which seems to be stopping it from running. Is there something that would cause the radio to suddenly go into Underflow mode instead of transmit mode at high speeds only? Whenever running at low speeds (baud rate less than 160k) the radio is staying in the transmit mode until the entire packet is sent. Thanks.
  • Hello,

    We have done some testing and found some things that could fix the problem. Another way to transmit the packets is to rely on the available bytes in the TX and RX FIFO and use interrupts to activate writing and reading to and from the FIFO depending on the FIFO threshold. The interrupts are RFIFG3 - RFIFG9. The main issue we found was that the speed of the clock was too slow. A quick fix for this would be to call this function in the beginning of main:

    void MSP_Setup(void) {

    SetVCore(2); // 2 is needed for radio operation, 3 if we need to go to 24MHz.

    // Set the High-Power Mode Request Enable bit so LPM3 can be entered
    // with active radio enabled
    PMMCTL0_H = 0xA5;
    PMMCTL0_L |= PMMHPMRE_L;
    PMMCTL0_H = 0x00;


    // Setup the XTAL ports to use the external 32K oscillilator
    P5SEL |= 0x03; // Select XT1
    UCSCTL6 &= ~(XT1DRIVE_0); // Max drive on XTAL
    UCSCTL6 |= XCAP_2; // Internal load cap

    // Loop until XT1,XT2 & DCO stabilizes
    do {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
    // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
    } while (SFRIFG1&OFIFG); // Test oscillator fault flag
    UCSCTL6 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive

    // Set up clock system on MCU to fit your system
    // Target specific implementation
    UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
    UCSCTL1 = DCORSEL_4; // Select suitable range
    UCSCTL2 = 244; // DCO = 244 * 32768Hz ~= 8MHz
    UCSCTL4 = SELA__XT1CLK | SELS__DCOCLK | SELM__DCOCLK; // use 32k xtal
    }

    This will speed up the clock. I tried using the original example code at 500 kBaud and found that it at least received part of the packet. Depending on how you set it up, it may differ for you. When I tried using RFIFG interrupts instead of Timer interrupts, I received the complete packet. Try it out and let me know if it works for you.

    Here's a link to the CC430 User's Guide : www.ti.com.cn/.../slau259e.pdf
    pg.732 talks about the RF1A registers
    pg.674-675 list the RFIFG interrupts
    pg.684 reveals the radio core status byte

    I have also noticed the underflow problem you pointed out. The only work around for that I have found out so far is to fill the FIFO as full as possible as much as you can guarantee not losing data, then flushing it out when safe. But for now just test out changing the clock and see if it works.

    Bryan V.
  • The clock code seemed to work properly but I am having some problems implementing the RFIFG interrupts for the receiving side. The transmitting side seems to work properly although I don't have a way to check it properly, the receiving side is saying that it received the entire signal (by reaching the ReceieveOff Command in if(!rxBytesLeft)) but whenever I check the RxBuffer it is all zeros except for the last three packets. Did I setup the RFIFG Flags incorrectly or is there a better way to interrupt the code using the RFIFG flags?

    Thanks



    void pktRxHandler(void) {
    unsigned char RxStatus;
    unsigned char bytesInFifo;
    // Which state?
    RxStatus = Strobe(RF_SNOP);

    switch(RxStatus & CC430_STATE_MASK)
    {
    case CC430_STATE_RX:
    // If there's anything in the RX FIFO....
    while(!packetReceived){
    if (bytesInFifo = MIN(rxBytesLeft, RxStatus & CC430_FIFO_BYTES_AVAILABLE_MASK))
    {
    // Update how many bytes are left to be received
    rxBytesLeft -= bytesInFifo;

    // Read from RX FIFO and store the data in rxBuffer
    while (bytesInFifo--) {
    RxBuffer[rxPosition] = ReadSingleReg(RXFIFO);
    rxPosition++;
    }

    if (!rxBytesLeft){
    packetReceived = 1;
    receiving = 0;
    lengthByteRead = 0;
    ReceiveOff();
    P1OUT ^= BIT0;// Toggle LED1
    }
    }

    RxStatus = Strobe(RF_SNOP);

    RF1AIFG &= ~BIT3;
    while((RF1AIFG & BIT3)){};
    }

    break;


    default:
    if(!packetReceived)
    {
    packetReceived = 1;
    }

    rxBytesLeft = 0;
    receiving = 0;
    ReceiveOff();

    break;
    }
    } // pktRxHandler






    void pktTxHandler(void) {
    unsigned char freeSpaceInFifo;
    unsigned char TxStatus;

    // Which state?
    TxStatus = Strobe(RF_SNOP);
    while(TxStatus != 0x2F){
    TxStatus = Strobe(RF_SNOP);
    }

    switch (TxStatus & CC430_STATE_MASK) {

    case CC430_STATE_TX:
    // If there's anything to transfer..
    while(txBytesLeft){
    if (freeSpaceInFifo = MIN(txBytesLeft, TxStatus & CC430_FIFO_BYTES_AVAILABLE_MASK))
    {
    txBytesLeft -= freeSpaceInFifo;

    while(freeSpaceInFifo--)
    {
    WriteSingleReg(TXFIFO, TxBuffer[txPosition]);
    }

    if(!txBytesLeft)
    {
    RF1AIES |= BIT9; // End-of-packet TX interrupt
    RF1AIFG &= ~BIT9; // clear RFIFG9
    while(!(RF1AIFG & BIT9)); // poll RFIFG9 for TX end-of-packet
    RF1AIES &= ~BIT9; // End-of-packet TX interrupt
    RF1AIFG &= ~BIT9; // clear RFIFG9
    transmitting = 0;
    recieveflag = 0;
    packetTransmit = 1;
    }
    }
    RF1AIFG &= ~BIT5;
    while((RF1AIFG & BIT5)){};
    }
    break;

    case CC430_STATE_TX_UNDERFLOW:
    Strobe(RF_SFTX); // Flush the TX FIFO

    __no_operation();
    // No break here!
    default:
    if(!packetTransmit)
    packetTransmit = 1;

    if (transmitting) {
    if ((TxStatus & CC430_STATE_MASK) == CC430_STATE_IDLE) {
    transmitting = 0;
    }
    }
    break;
    }
    } // pktTxHandler
  • I don't believe there is an easy way to check what you are transmitting, but you can check if you are receiving correctly. The way I check it is setting a breakpoint at the line where your receiver toggles the LED, then looking in the RX buffer.  Your flags look right. You can check if the interrupts are registering by setting breakpoints on the line that begins like:

    #pragma vector=CC1101_VECTOR
    __interrupt void CC1101_ISR(void)
    {
    switch(__even_in_range(RF1AIV,32)) // Prioritizing Radio Core Interrupt
    {

    ...

    }

    Try first sending smaller packet sizes and then increasing it and checking the RX buffer. To do this, you can modify the value of PACKET_LEN in the .h file and the PKTLEN line in the RfRegSettings.c file. It should work for very small sizes. Let us know if sending small packet sizes works and if not, let us know what the contents of the RX buffer looks like.

    Thanks.

  • It worked perfectly! Turns out it was a simple typo in the transmit part of the code that sent 100 packets of 00 instead of incrementing the buffer making it look like it wasn't sending or receiving when in reality it was. I must have dropped the txPosition++ during one of the trials of debugging this afternoon. Thank you so much for spending time to help me with the faster speeds and even debugging my code! You have been a tremendous help! Thank you so much!

    Thanks again,
    Brian
  • I'm sorry to bother you again but I seem to be creating problems left and right with this code. The receiver will receive the correct packet (all numbers 0 to 99) correctly once or twice then it will receive an incorrect packet (numbers 0-64 then 1-31 then 96-99) from then on. I know this is an issue with the receiving side because if I reset the receiving chip it will receive a correct packet again. I feel like this should be a problem caused by reading the FIFO too early or not emptying the FIFO correctly but i'm not sure how to determine it these are the issue or not. The code also occasionally gets trapped in the while statement under case 20 in the CC1101_ISR which signify that the sync word is not being correctly transmitted. The last thing I noticed that might cause be the issue is the while((RF1AIFG & BIT3)) in the pktRxHandler() is never actaully being triggered which means the flag is never set. Is there something simple I am missing that could be causing these problems?

    Thanks,
    Brian
  • That is very odd. One idea I have that you could try is to fill up the FIFO as you are doing now (0x00 to 0x99), then once you have finished, the LED should toggle on the receiver side. Then you could disable the interrupts momentarily and fill up all the contents from [0] to [99] will some value like 0xFF, then reenable interrupts. Then retransmit the data and then see what the contents of the RX buffer looks like. The numbers 0-64 are right, but since the buffer never resets to being filled with all 0's it is hard to tell what's going on. 

    I have had a few troubles cleaning the FIFO, so I have just been flushing it. I haven't been using the sync word interrupt, but if you have ever entered a line under case 8 in the CC1101_ISR, then the RF1AIFG has had its BIT3 set. Set a breakpoint there and see if it ever stops there.

    Some things I noticed when I was testing was that some interrupts seem to take precedence of others. For example, I tried using RFIFG5 and RFIFG6 interrupts triggered with negative edges (TXFIFO below TXFIFO threshold). When I used RFIFG6, it would never trigger when there was less data than the TXFIFO threshold in the TXFIFO. However when I used RFIFG5, it would trigger at the same situation. Maybe RFIFG4 might work for you, but it also triggers at end of packet.

    Make sure that when you set up your interrupts it follows a similar format:

    RF1AIES |= BIT5; //Edge Select (0 for positive edge, 1 for negative edge)
    RF1AIFG = 0; // Clear pending RFIFG interrupts (I found this is important to be written or else the program stops working when returning from CC1101_ISSR)
    RF1AIE |= BIT5; // Enable interrupt

    Let me know your findings. 

    Thanks,

    Bryan

  • I'm not sure what you mean by "fill up the contents from[0] to[99] with a value like 0xFF", are you talking about the RxBuffer or the FIFO because I tried the RxBuffer but got the same results as before and im not sure how to write to the RxFIFO directly without using another transmitter.

    Since you did not use any sync words does that mean there doesnt need to be anything in the RFIFG9 section of the CC1101_ISR interrupt (case 20)? The pktRxHandler() is being called from the RFIFG3 interrupt section (case 8) and if I put a breakpoint there it stops everytime something is being recieved. 

    All of my interrupts seem to be setup just like your example above except for I am using the postitive edge and you are using the negative edge. I have tried reversing this and use the negative edge for the recieving but it never leaves the while loop when that happens. 

    I have attached my file below if that helps any. 

    Thanks,

    Brian

    /******************************************************************************
    * CC430 RF Code Example - TX and RX (fixed-size packet length > FIFO size)
    *
    * Simple RF Link to Toggle Receiver's LED by pressing Transmitter's Button    
    * Warning: This RF code example is setup to operate at either 868 or 915 MHz, 
    * which might be out of allowable range of operation in certain countries.
    * The frequency of operation is selectable as an active build configuration
    * in the project menu. 
    * 
    * Please refer to the appropriate legal sources before performing tests with 
    * this code example. 
    * 
    * This code example can be loaded to 2 CC430 devices. Each device will transmit 
    * a 100 byte packet upon a button pressed. Each device will also toggle its LED 
    * upon receiving the packet(s). 
    * 
    * The RF packet engine settings specify variable-length-mode with CRC check 
    * enabled. The RX packet also appends 2 status bytes regarding CRC check, RSSI 
    * and LQI info. For specific register settings please refer to the comments for 
    * each register in RfRegSettings.c, the CC430x613x User's Guide, and/or 
    * SmartRF Studio.
    * 
    * G. Larmore
    * Texas Instruments Inc.
    * June 2012
    * Built with IAR v5.40.1 and CCS v5.2
    ******************************************************************************/
    
    #include "RF_Toggle_LED_Demo.h"
    
    extern RF_SETTINGS rfSettings;
    
    unsigned char packetReceived;
    unsigned char packetTransmit; 
    
    unsigned char txBytesLeft = PACKET_LEN;           // +1 for length byte 
    unsigned char txPosition = 0; 
    unsigned char rxBytesLeft = PACKET_LEN+2;         // +2 for status bytes
    unsigned char rxPosition = 0;
    unsigned char lengthByteRead = 0; 
    
    unsigned char RxBufferLength = 0;
    unsigned char TxBufferLength = 0; 
    unsigned char * _p_Buffer = 0; 
    unsigned char buttonPressed = 0;
    unsigned int i = 0;                 
    
    unsigned char transmitting = 0; 
    unsigned char receiving = 0; 
    
    unsigned char RxBuffer[PACKET_LEN+2] = {0};
    unsigned char TxBuffer[PACKET_LEN]= {
        0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
        0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
        0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 
        0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 
        0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 
        0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 
        0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 
        0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 
        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 
        0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 
    };
    
    void main( void )
    {  
      // Stop watchdog timer to prevent time out reset 
      WDTCTL = WDTPW + WDTHOLD; 
        
      // Increase PMMCOREV level to 2 for proper radio operation
      SetVCore(2);                               
      
      MSP_Setup();
        
      ResetRadioCore();
      InitButtonLeds();
      //InitTimer(); 
        
      // Clean out the RX Buffer 
      rxPosition = PACKET_LEN+2;
      while(rxPosition--)
      {
        RxBuffer[rxPosition] = 0; 
      }
    
      InitRadio();  
      ReceiveOn(); 
        
      while (1)
      { 
        P1IE |= BIT7;                           // Enable button interrupt
        
        __bis_SR_register( LPM3_bits + GIE );   
        __no_operation(); 
        
        if (buttonPressed)                      // Process a button press->transmit 
        {            
          ReceiveOff();                         // Button means TX, stop RX
          receiving = 0;                         
          
          TransmitPacket();                 
    
          buttonPressed = 0;                    // Re-enable button press                           
        }    
        if(receiving)
        {
          ReceivePacket(); 
          __no_operation(); 
        }
        if(!transmitting)
        {
          ReceiveOn(); 
        }
      }
    }
    
    void ReceivePacket(void)
    {
      rxBytesLeft = PACKET_LEN + 2;// Set maximum packet leng + 2 for appended bytes
      rxPosition = 0; 
      packetReceived = 0; 
      
      __delay_cycles(2800);                     // Wait for bytes to fill in RX FIFO
    
      /*TA0CCR1   = RX_TIMER_PERIOD;              // x cycles * 1/32768 = y us
      TA0CCTL1 |= CCIE;            
      TA0CTL   |= MC_2 + TACLR;                 // Start the timer- continuous mode
    
      __bis_SR_register(LPM3_bits + GIE); 
      __no_operation(); 
      
      TA0CCR1 = RX_TIMER_PERIOD;             
      TA0CCTL1 &= ~(CCIE);
      TA0CTL &= ~(MC_3);                  // Turn off timer 
      */
      __no_operation(); 
    }
    
    void TransmitPacket(void)
    {  
      P3OUT |= BIT6;                        // Pulse LED during Transmit 
    
      txBytesLeft = PACKET_LEN;   
      txPosition = 0; 
      packetTransmit = 0; 
      transmitting = 1;       
      
      Strobe( RF_STX );                         // Strobe STX   
      
      pktTxHandler();
      /*TA0CCR1   = TX_TIMER_PERIOD;              // x cycles * 1/32768 = y us
      TA0CCTL1 |= CCIE; 
      TA0CTL |= MC_2 + TACLR;                   // Start the timer- continuous mode   
    
      __bis_SR_register(LPM3_bits + GIE); 
      __no_operation(); 
      
      TA0CCR1 = TX_TIMER_PERIOD;             // x cycles * 1/32768 = y us
      TA0CCTL1 &= ~(CCIE); 
      TA0CTL &= ~(MC_3);                  // Turn off timer         
    */
      P3OUT &= ~BIT6;                     // Turn off LED after Transmit               
    }
    
    void ReceiveOn(void)
    {  
      RF1AIES &= ~BIT9 + ~BIT3; 
      RF1AIFG = 0;                              // Clear pending RFIFG interrupts
      RF1AIE  |= BIT9 + BIT3;                          // Enable the sync word received interrupt
      
      // Radio is in IDLE following a TX, so strobe SRX to enter Receive Mode
      Strobe( RF_SRX );        
      
      __no_operation(); 
    }
    
    void ReceiveOff(void)
    {
      RF1AIE &= ~BIT9 + ~BIT3;                          // Disable RX interrupts
      RF1AIFG = 0;//~BIT9 + ~BIT3;                         // Clear pending IFG
      RF1AIES &= ~BIT9 + ~BIT3;                         // Switch back to to sync word
    
      // It is possible that ReceiveOff is called while radio is receiving a packet.
      // Therefore, it is necessary to flush the RX FIFO after issuing IDLE strobe 
      // such that the RXFIFO is empty prior to receiving a packet.
      Strobe(RF_SIDLE); 
      Strobe(RF_SFRX);                       
    }
    
    //------------------------------------------------------------------------------
    //  void pktRxHandler(void)
    //
    //  DESCRIPTION:
    //      This function is called every time a timer interrupt occurs. The 
    //      function starts by retreiving the status byte. Every time the status 
    //      byte indicates that there are available bytes in the RX FIFO, bytes are 
    //      read from the RX FIFO and written to RxBuffer. This is done until the 
    //      whole packet is received. If the status byte indicates that there has 
    //      been an RX FIFO overflow the RX FIFO is flushed. Please see the 
    //      EM430F6137RF900 RF Examples User Manual for a flow chart describing this 
    //      function.
    //------------------------------------------------------------------------------
    void pktRxHandler(void) {
      unsigned char RxStatus;
      unsigned char bytesInFifo;
      
      // Which state?
      RxStatus = Strobe(RF_SNOP);
      
      switch(RxStatus & CC430_STATE_MASK)
      {
        case CC430_STATE_RX:
          // If there's anything in the RX FIFO....
          while(!packetReceived){
          if (bytesInFifo = MIN(rxBytesLeft, RxStatus & CC430_FIFO_BYTES_AVAILABLE_MASK))
          {         
            // Update how many bytes are left to be received
            rxBytesLeft -= bytesInFifo;
      
            // Read from RX FIFO and store the data in rxBuffer
            while (bytesInFifo--) {
              RxBuffer[rxPosition] = ReadSingleReg(RXFIFO);
              rxPosition++; 
            }  
            if (!rxBytesLeft){           
                packetReceived = 1; 
                receiving = 0;
                lengthByteRead = 0; 
                ReceiveOff();
                
                P1OUT ^= BIT0;                    // Toggle LED1             
            }      
          } 
          RxStatus = Strobe(RF_SNOP);
          
          RF1AIFG &= ~BIT3;
          while((RF1AIFG & BIT3)){};
          }
          break;
        default:
          if(!packetReceived)
          {
            packetReceived = 1; 
          }
          
          rxBytesLeft = 0;
          receiving = 0; 
          ReceiveOff();
    
          break;  
      }
    } // pktRxHandler
    
    //------------------------------------------------------------------------------
    //  void pktTxHandler(void)
    //
    //  DESCRIPTION:
    //      This function is called every time a timer interrupt occurs. The function starts
    //      by getting the status byte. Every time the status byte indicates that there 
    //      is free space in the TX FIFO, bytes are taken from txBuffer and written to 
    //      the TX FIFO until the whole packet is written or the TXFIFO has underflowed. 
    //      See the EM430F6137RF900 RF Examples User Manual for a flow chart describing 
    //      this function.
    //------------------------------------------------------------------------------
    void pktTxHandler(void) {
        unsigned char freeSpaceInFifo;
        unsigned char TxStatus;  
        
        // Which state?
        TxStatus = Strobe(RF_SNOP);
        while(TxStatus != 0x2F){
          TxStatus = Strobe(RF_SNOP);
        }
    
        switch (TxStatus & CC430_STATE_MASK) {
            case CC430_STATE_TX:
                // If there's anything to transfer..
              while(txBytesLeft){
                 if (freeSpaceInFifo = MIN(txBytesLeft, TxStatus & CC430_FIFO_BYTES_AVAILABLE_MASK)) 
                {
                  txBytesLeft -= freeSpaceInFifo;
    
                  while(freeSpaceInFifo--)
                  {
                    WriteSingleReg(TXFIFO, TxBuffer[txPosition]);
                    txPosition++; 
                  }
                  
                  if(!txBytesLeft)
                  {                
                    RF1AIES |= BIT9;      // End-of-packet TX interrupt
                    RF1AIFG &= ~BIT9;     // clear RFIFG9
                    while(!(RF1AIFG & BIT9)); // poll RFIFG9 for TX end-of-packet  
                    RF1AIES &= ~BIT9;      // End-of-packet TX interrupt
                    RF1AIFG &= ~BIT9;     // clear RFIFG9
                    transmitting = 0; 
                    packetTransmit = 1; 
                  }
                }
                RF1AIFG &= ~BIT5;
                while((RF1AIFG & BIT5)){};
              }
                break;
    
            case CC430_STATE_TX_UNDERFLOW:
                Strobe(RF_SFTX);  // Flush the TX FIFO
                
                __no_operation(); 
                // No break here!
            default:
                if(!packetTransmit) 
                  packetTransmit = 1; 
                
                if (transmitting) {
                    if ((TxStatus & CC430_STATE_MASK) == CC430_STATE_IDLE) {
        	          transmitting = 0; 
                    }
                }
            break;
        }
    } // pktTxHandler
    
    /*void InitTimer(void)
    {
      P5SEL |= 0x03;                            // Set xtal pins  
      LFXT_Start(XT1DRIVE_0); 
      
      TA0CCR1  = RX_TIMER_PERIOD;               // x cycles * 1/32768 = y us
      TA0CCTL1 = CCIE;                          // Enable interrupts
      TA0CTL   = TASSEL__SMCLK + TACLR;          // ACLK source
    }
    */
    
    void MSP_Setup(void) {
    
    SetVCore(2); // 2 is needed for radio operation, 3 if we need to go to 24MHz.
    
    // Set the High-Power Mode Request Enable bit so LPM3 can be entered
    // with active radio enabled
    PMMCTL0_H = 0xA5;
    PMMCTL0_L |= PMMHPMRE_L;
    PMMCTL0_H = 0x00;
    
    
    // Setup the XTAL ports to use the external 32K oscillilator
    P5SEL |= 0x03; // Select XT1
    UCSCTL6 &= ~(XT1DRIVE_0); // Max drive on XTAL
    UCSCTL6 |= XCAP_2; // Internal load cap
    
    // Loop until XT1,XT2 & DCO stabilizes
    do {
    UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
    // Clear XT2,XT1,DCO fault flags
    SFRIFG1 &= ~OFIFG; // Clear fault flags
    } while (SFRIFG1&OFIFG); // Test oscillator fault flag
    UCSCTL6 &= ~(XT1DRIVE_3); // Xtal is now stable, reduce drive
    
    // Set up clock system on MCU to fit your system
    // Target specific implementation
    UCSCTL0 = 0x00; // Set lowest possible DCOx, MODx
    UCSCTL1 = DCORSEL_4; // Select suitable range
    UCSCTL2 = 244; // DCO = 244 * 32768Hz ~= 8MHz
    UCSCTL4 = SELA__XT1CLK | SELS__DCOCLK | SELM__DCOCLK; // use 32k xtal
    }
    
    void InitButtonLeds(void)
    {
      // Set up the button as interruptible 
      P1DIR &= ~BIT7;
      P1REN |= BIT7;
      P1IES &= BIT7;
      P1IFG = 0;
      P1OUT |= BIT7;
      P1IE  |= BIT7; 
    
      // Initialize Port J
      PJOUT = 0x00;
      PJDIR = 0xFF; 
    
      // Set up LEDs 
      P1OUT &= ~BIT0;
      P1DIR |= BIT0;
      P3OUT &= ~BIT6;
      P3DIR |= BIT6;
    }
    
    void InitRadio(void)
    {
      // Set the High-Power Mode Request Enable bit so LPM3 can be entered
      // with active radio enabled 
      PMMCTL0_H = 0xA5;
      PMMCTL0_L |= PMMHPMRE_L; 
      PMMCTL0_H = 0x00; 
      
      WriteRfSettings(&rfSettings);
      
      WriteSinglePATable(PATABLE_VAL);
    }
    
    /**************************************
    * Interrupt Service Routines
    **************************************/
    
    #pragma vector=TIMER0_A1_VECTOR
    __interrupt void TIMER0_A1_ISR(void)
    {
      switch(__even_in_range(TA0IV,14))
      {
        case 0:  break;                  
        case 2:  
          /*if(receiving)
          {
            TA0CCR1 += RX_TIMER_PERIOD;                  // 16 cycles * 1/32768 = ~500 us
    
            pktRxHandler();  
            
            if(packetReceived)
              __bic_SR_register_on_exit(LPM3_bits); 
          }
          else if(transmitting)
          {
            TA0CCR1 += TX_TIMER_PERIOD;                  // 16 cycles * 1/32768 = ~500 us
    
            pktTxHandler(); 
            
            if(packetTransmit)
              __bic_SR_register_on_exit(LPM3_bits); 
          }  */     
          break;
        case 4:  break;                         // CCR2 not used
        case 6:  break;                         // Reserved not used
        case 8:  break;                         // Reserved not used
        case 10: break;                         // Reserved not used
        case 12: break;                         // Reserved not used
        case 14: break;                         // Overflow not used
      }
    }
    
    #pragma vector=CC1101_VECTOR
    __interrupt void CC1101_ISR(void)
    {
      switch(__even_in_range(RF1AIV,32))        // Prioritizing Radio Core Interrupt 
      {
        case  0: break;                         // No RF core interrupt pending                                            
        case  2: break;                         // RFIFG0 
        case  4: break;                         // RFIFG1
        case  6: break;                         // RFIFG2
        case  8: 
          pktRxHandler();                         // RFIFG3
          break;
        case 10: break;                         // RFIFG4
        case 12: break;                         // RFIFG5
        case 14: break;                         // RFIFG6          
        case 16: break;                         // RFIFG7
        case 18: break;                         // RFIFG8
        case 20:                                // RFIFG9
          if(!(RF1AIES & BIT9))                 // RX sync word received 
          {
            receiving = 1;         
            __bic_SR_register_on_exit(LPM3_bits); // Exit active    
          }	   
          else while(1); 			    // trap 
          break;
        case 22: break;                         // RFIFG10
        case 24: break;                         // RFIFG11
        case 26: break;                         // RFIFG12
        case 28: break;                         // RFIFG13
        case 30: break;                         // RFIFG14
        case 32: break;                         // RFIFG15
      }      
    }
    
    #pragma vector=PORT1_VECTOR
    __interrupt void PORT1_ISR(void)
    {
      switch(__even_in_range(P1IV, 16))
      {
        case  0: break;
        case  2: break;                         // P1.0 IFG
        case  4: break;                         // P1.1 IFG
        case  6: break;                         // P1.2 IFG
        case  8: break;                         // P1.3 IFG
        case 10: break;                         // P1.4 IFG
        case 12: break;                         // P1.5 IFG
        case 14: break;                         // P1.6 IFG
        case 16:                                // P1.7 IFG
          __delay_cycles(1000);                 // debounce delay 
          buttonPressed = 1;
          P1IE = 0;                             // Debounce by disabling buttons
          P1IFG = 0; 
          __bic_SR_register_on_exit(LPM3_bits); // Exit active    
          break;
      }
    }

  • I just tested your code, and I can only give you the quick results that I have found so far. I believe your problem has something to do with your transmitter. I was using SmartRF Studio 7 with another device to determine what was being sent by the transmitter. I also tested it with the receiver to confirm. I noticed that when you press the button once or twice, the correct results are displayed. But after a few presses, the results become like how you described. I also noticed that the receiver stops receiving after about 3-4 button presses and the program breaks when returning from the CC1101_ISR after that time. I will see if I find anything else
  • After some more testing I have some suggestions you could try. First I would like to share with you the code I had written for transmit. The way I implemented how the data would be transmitted was to send chunks of data once a while and then clean the FIFO before sending more data until the Packet Length was reached. I did this because I could not figure out why the Radio Core Status Byte was in the TX or TX underflow state, even when the TX FIFO was already out of space. You will see that I flushed the TX FIFO to be able to refill it was more data (lines 435 - 453). Also the RFIFG interrupts work in a certain way not fully mentioned in the reference manual. For instance the RFIFG interrupts that occur when the threshold is passed or under seem to only happen when the threshold value is reached and no other time. I will post my code here, but only use the portion for transmission. I have tested the transmission of data and it will go from 0x00 to 0x99 every time, so once you use it you will know any other problems should be on the receiver side.

    Your receiver code looks fine, but I would like you to change a few things.

    1. In ReceivePacket(), you should comment out or remove "__delay_cycles(2800);                     // Wait for bytes to fill in RX FIFO", as the TX and RX should be running about the same rate. I believe this was what was causing the RXBuffer to recycle through the old contents of the RX FIFO, since the TX happens so fast that the second and third part of the TX was never able to get written into the RX FIFO before it was cleaned.

    2. Include the line "__bic_SR_register_on_exit(LPM3_bits); // Exit active" for the RFIFG interrupts when you know you might enter the CC1101_ISR while you are waiting at this line "_bis_SR_register( LPM3_bits + GIE );". The previous line will allow you to move out of this line and let you TX and RX more than 4 times.

    3. You could choose to use RFIFG9 instead of RFIFG3. I have found that RFIFG3 will wait until the RXFIFO has been filled to the threshold amount of data before running the ISR. RFIFG9 will wait until the sync word is received before running. And since TX and RX are running about the same rate, it should be fine.

    I tested this and I have received all 100 bytes many times. Use my transmit code and your modified receive code and adjust as you see fit.

    /cfs-file/__key/communityserver-discussions-components-files/156/CC430-July-7.c

    Let me know if this works for you.

    Thanks,

    Bryan V.

  • That seemed to fix most of the issues but I am still getting the same results (0x00 : 0x64, 0x0 : 0x34) instead of the 0x00 : 0x99 but only after approximately 26 correct transmissions. These are due entirely to the receiver because the chip can be reset and will work perfectly for another 26 or so transmissions. After you transmit anything from the original receiver side you will also only receive  (0x00:0x61, 0x00:0x34). I really dont understand how it can be reading the same FIFO values that it has already read, doesn't the reading of the values from the RXFIFO clear them from the FIFO?

  • I tried sending 26 packets over and I only encountered 1 packet where the data was corrupt. Using SmartRF Studio 7 with the device to read the packet, I noticed this happens very rarely. Usually it occurs when packets are sent too fast with 2 packets coming and the 1st correct while the 2nd corrupted. If I press the button slowly it doesn't seem to appear. I seem to only see it when the button debouncing doesn't work well. I will provide the same code I posted yesterday, but with the modifications that I suggested. Hopefully our code is identical.

    In my previous code I forgot to clear the transmitting flag, which was why when the transmitter decided to want to receive, it couldn't. I don't know if that was what you meant before or if you solved it already (I noticed you edited your post right after as I wrote the 1st paragraph).

    I'm not sure what you mean by your second to last sentence. Do you mean that after receiving, you transmit, and the device that should be receiving that packet gets the same  data as what you first received from the original receiver?

    For your last sentence, and I'm not 100% sure about this, I believe that the FIFO's work like this: There is some counter that keeps track of how many bytes are still important in the FIFO. When you read from the RX FIFO, the counter "should" decrement (I have not seen this actually being done, so I could be wrong). The old contents in the FIFO are just rewritten when new data is sent from the TX FIFO. After you exceed the size of the RX FIFO, I think you just wrap around back to the first position you started at. Yesterday I tried seeing why the RX buffer was being filled with old values, and I noticed that the old values happened right when the total size of the FIFO was exceeded. When I said flush the FIFO, I believe the same idea was happening. That the old values remain in the RX FIFO before being rewritten when the next transmission comes, while the counter goes back to 64. I was using "ReadSingleReg(RXBYTES)" and the Strobe commands to help me see the remaining size of the RX FIFO.

    Hopefully this helps.

    /cfs-file/__key/communityserver-discussions-components-files/156/CC430.c

    Let me know what your results are, and if there are difference between our code.

    Thanks.

  • That explanation of the FIFO seemed to help me a lot! Yes I was able to find the transmitting flag error which is why I edited my post yesterday. I also couldn't find many differences between our codes.

    What I meant by that sentence was that the CC430's will communicate correctly in one direction (i.e. one is the receiver and the other is the transmitter) but when I send a packet in the other direction (Transmitter and receiver switched roles) the new receiver is picking up incorrect data just like before (starting with 0x00:0x64 then 0x01:0x34). I believe the issue is something to do with not resetting a flag correctly when leaving the transmitter mode but I have not found the source of the error yet. I will keep looking and hopefully find the error. Thanks for all of your help!