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.

Can't receive after transmission...CC430F5437

Other Parts Discussed in Thread: CC1101, CC430F5137, CC430F6137, TEST2

Hello

I'm havin the following problem. My device is supposed to listen to traffic and when receiving a message react to it and respond.
At the momemt it's able to do this but after send a reply it won't accept any further incoming messages.

The scanario is as following:

-interrupt routine listens for incoming data.
- once data is received it's stored in a global array
- the main function polls the array and handles it accordingly by send an appropriate response by calling the send function
- the send function prepares the packet and calls the transfer function which send the packet.
- loop repeats itself, though with the problem being that after the transfer it won't accept any further data (doesn't invoke the interrupt)

I've narrowed the problem down to it being related to the following lines in the end of the transfer function:

while(!(RF1AIFG & BIT9));
RF1AIFG &= ~BIT9;

If these are left out it continously accept data but without transmitting it. This is probably a "simple task" where some flag is left active.
Unfortunately my skills are limited and haven't managed to solve the issus. Any help would be highly appreciated!

Best regards Richard Salin

ps. The device calls ReceiveOn in the beginning so that's it's initial state.


#pragma vector=CC1101_VECTOR
__interrupt void CC1101_ISR(void)
{

  switch(__even_in_range(RF1AIV,32))            // Prioritizing Radio Core Interrupt
  {
    case 20: 
        // If device isn't tranmitting -> receive               // RFIFG9
        if(!transmitting){                            // RX end of packet
             
            RxBufferLength = ReadSingleReg( RXBYTES );
           
            // Check packet size
               if(RxBufferLength>50){
                   
                ReadBurstReg(RF_RXFIFORD, RxBuffer, RxBufferLength);
               
            // store length to array
                for(i=1;i<RxBufferLength-3;i++){
                    uip_buf[i-1] = RxBuffer[i];
                }
            // set received size (subtract length & status bytes)
                uip_length=RxBufferLength-4;
   
            // Flush buffer
            ReceiveOff();
            ReceiveOn();        
               }
        }
        else if(transmitting)                    // TX end of packet
        {
            RF1AIE &= ~BIT9;                        // Disable TX end-of-packet interrupt           
            transmitting = 0;
        }
        else while(1);                             // trap
       
        break;
  }         
}


void cc430_send(void)
{
    transmitting = 1;
    TxBuffer[0] = 55;
   
    for(u=0;u<54;u++){
            TxBuffer[u+1] = uip_buf[u];
        }
     
        for(u=0;u<55;u++){
          while (!(UCA0IFG&UCTXIFG));           // Wait for TX buffer ready to receive new byte
            UCA0TXBUF = TxBuffer[u];            // Output character
            for(j=0;j<1000;j++);
        }
   
        ReceiveOff();
        Transmit( (unsigned char*)TxBuffer, 54);
        ReceiveOn();
 

       transmitting = 0;
        return;

}

void Transmit(char *buffer, unsigned char length)
{   
    while (!(UCA0IFG&UCTXIFG));           // Wait for TX buffer ready to receive new byte
        UCA0TXBUF = length;

    /* Wait for radio to be ready for next instruction */
    while( !(RF1AIFCTL1 & RFINSTRIFG));
   
    /* Write cmd: TXFIFOWR */
    RF1AINSTRB = 0x7F;

    while(length){
        /* Wait for radio to be ready to accept the data */
        while( !(RF1AIFCTL1 & RFDINIFG)  );
   
        /* Write one byte to FIFO */
        RF1ADINB   = *buffer;
   
        buffer++;
        length--;
      }
  
      Strobe( RF_STX );                         // Strobe STX  
 
    // THIS LINE IS THE PROBLEM. WHEN CALLED THE DEVICES STOPS SENDING, BUT IF NOT IT DOESN'T TRANSMIT THE PACKET
      while(!(RF1AIFG & BIT9));
      RF1AIFG &= ~BIT9;
}

void ReceiveOn(void)
{
    // PA
    P3OUT |= 0x40;    // Set RX
    P1OUT &= ~0x1;    // Clear TX 
   
      RF1AIES |= BIT9;                          // Falling edge of RFIFG9
      RF1AIFG &= ~BIT9;                         // Clear a pending interrupt
      RF1AIE  |= BIT9;                          // Enable the interrupt
 
      // Radio is in IDLE following a TX, so strobe SRX to enter Receive Mode
      Strobe( RF_SRX );                     
}

void ReceiveOff(void){
    P3OUT &= ~0x40;   // Clear RX
      P1OUT |= 0x01;    // Set TX
     
      RF1AIE &= ~BIT9;                          // Disable RX interrupts
      RF1AIFG &= ~BIT9;                         // Clear pending IFG

      Strobe( RF_SIDLE );
      Strobe( RF_SFRX  );                      
}

  • Richard,

    Try monitoring the RF1AIN register instead of the RF1AIFG register in the while loop.  The RF1AIFG register latches on the rising edge whereas the RF1AIN represents the current state of the signal.

    Jim

     

  • Thank you for your reply. (sorry for the typo in the heading 5437->5137) The problem is accord to the registry monitor the AIN doesn't seem to change...

    I tried to remake the program based on the RF example from TI - slaa465 and only made smoe minor chnages that sholdn't affect the nature. As continously running the main loop and reading the state of the button instead of using interrupt, this as I was unable to connect a button to a interrupt IO due to the design.

    With this program the link works both way for a while after which (usually the one that sends less) stops sending. It's able to receive but not to transmit. I noticed that it always gets stuck at the following line

     while (!(RF1AIFCTL1 & RFDOUTIFG) );

    in the following function

     unsigned char ReadSingleReg(unsigned char addr)
    {
      unsigned char data_out;
     
      // Check for valid configuration register address, 0x3E refers to PATABLE
      if ((addr <= 0x2E) || (addr == 0x3E))
        // Send address + Instruction + 1 dummy byte (auto-read)
        RF1AINSTR1B = (addr | RF_SNGLREGRD);   
      else
        // Send address + Instruction + 1 dummy byte (auto-read)
        RF1AINSTR1B = (addr | RF_STATREGRD);   
     
      while (!(RF1AIFCTL1 & RFDOUTIFG) );   
      data_out = RF1ADOUTB;                    // Read data and clears the RFDOUTIFG

      return data_out;
    }

     By commenting out the line it seems to be working, my only concern is if this will indirectly affect the program?
    I can't manage t ofigure out what the line does...

    Best regards Richard Salin

  • im also having the same problems right now. Surely,  I can put some timeout mechanism on the while loop, but I am more eager to know the root cause of the problem.

    Thanks

  • Hi Guys, have you solved this issue by other way than delaying between two packets? I was just fased to the same problem, timeout solution works properly for me, but it doesn't  look clear. 

  • I have it solved, if someone will want it I can send sources. David

  • I was able to solve it as well. I strongly believe that this problem  is caused by the non-reentrant functions inside the interrupt routine.

  • I'm having the same problem. Could you please share with me your solution?

    Thankyou

  • I moved out the ReadSingleReg and ReadBurstReg from the interrupt routine and processed it outside.

    I was able to reproduce the problem by continuously monitoring the MARCSTATE via ReadSingleReg in a while loop with no delay. I did some minor modifications and  moved out the processing outside the interrupt routine especially the lines that contains the ReadSingleReg  and ReadBurstReg functions. My project has been working for months now without any problems :).   This functions are non-reentrant. Initially, I feel disappointed because I assumed that the author of the RF sample codes already considered a 100% code reusability for TI's customers.

  • Excuse me, could you send the sources to me? I've fased the same quesiton and I don't know why it is. This is my Email:qgy17725@163.com, I will sign in another one if the Email does'nt work to you.

    Thanks

    Qin

  • hello! I'm having the same problem. Could you please send me your sources?

    My email is: dessers.thomas@gmail.com

    Thanks!

    Thomas

  • Hi!I‘m having the same problem now. can you please send your solution to me.thank you

    my email is 963569008@qq.com

  • Excuse me, would you send me the project because I have faced a similar problem.Thank you.
    My email is 1034898161@qq.com
    Thanks a lot.
  • hello! I'm having the same problem. Could you please send me your sources?

    Thanks!

    Denys

  • Hi,

       Have you got the sources? If someone send you how to solve this problem, can you forward to me?

    My email is xunchen199102@gmail.com.

    Thanks a lot.

    rui

  • Rui,

    Are you trying to get the code included earlier in the post to transmit packets? What data rate over the air do you need/want, remember that data rate is a trade off between rate and range.

    Regards,
    /TA
  • Rui et al,

    I have fixed the code that was originally posted on this thread. There where a number of issues with the code, the mains errors were related to missing or incorrect system configuration during start up. I have added all the absolutely minimum required to get the transmit function to work.

    We strongly recommend starting a new project with more tested code base, like what we release in the product folders

    www.ti.com/.../toolssoftware

    However, for this case I have decided to upload the fixed source code. To use this start a new CC430F5137 or CC430F6137 project in CCS6.1 and copy the entire source below into the main.c and compile.

    Regards,
    /TA


    #include <msp430.h>

    /*
    * main.c
    */

    typedef struct {
    unsigned int addr;
    unsigned char data;
    } registerSetting_t;


    void cc430_send(void);
    void Transmit(unsigned char *buffer, unsigned char length);
    void ReceiveOn(void);
    void ReceiveOff(void);
    void cc430_write_reg(unsigned char addr, unsigned char value);

    #define TX_PKT_LENGTH 55
    unsigned char TxBuffer[TX_PKT_LENGTH];
    unsigned char uip_buf[TX_PKT_LENGTH];
    unsigned char transmitting;

    #define PMM_STATUS_OK 0
    #define PMM_STATUS_ERROR 1

    // Configuration Registers
    #define IOCFG2 0x00 // GDO2 output pin configuration
    #define IOCFG1 0x01 // GDO1 output pin configuration
    #define IOCFG0 0x02 // GDO0 output pin configuration
    #define FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds
    #define SYNC1 0x04 // Sync word, high byte
    #define SYNC0 0x05 // Sync word, low byte
    #define PKTLEN 0x06 // Packet length
    #define PKTCTRL1 0x07 // Packet automation control
    #define PKTCTRL0 0x08 // Packet automation control
    #define ADDR 0x09 // Device address
    #define CHANNR 0x0A // Channel number
    #define FSCTRL1 0x0B // Frequency synthesizer control
    #define FSCTRL0 0x0C // Frequency synthesizer control
    #define FREQ2 0x0D // Frequency control word, high byte
    #define FREQ1 0x0E // Frequency control word, middle byte
    #define FREQ0 0x0F // Frequency control word, low byte
    #define MDMCFG4 0x10 // Modem configuration
    #define MDMCFG3 0x11 // Modem configuration
    #define MDMCFG2 0x12 // Modem configuration
    #define MDMCFG1 0x13 // Modem configuration
    #define MDMCFG0 0x14 // Modem configuration
    #define DEVIATN 0x15 // Modem deviation setting
    #define MCSM2 0x16 // Main Radio Cntrl State Machine config
    #define MCSM1 0x17 // Main Radio Cntrl State Machine config
    #define MCSM0 0x18 // Main Radio Cntrl State Machine config
    #define FOCCFG 0x19 // Frequency Offset Compensation config
    #define BSCFG 0x1A // Bit Synchronization configuration
    #define AGCCTRL2 0x1B // AGC control
    #define AGCCTRL1 0x1C // AGC control
    #define AGCCTRL0 0x1D // AGC control
    #define WOREVT1 0x1E // High byte Event 0 timeout
    #define WOREVT0 0x1F // Low byte Event 0 timeout
    #define WORCTRL 0x20 // Wake On Radio control
    #define FREND1 0x21 // Front end RX configuration
    #define FREND0 0x22 // Front end TX configuration
    #define FSCAL3 0x23 // Frequency synthesizer calibration
    #define FSCAL2 0x24 // Frequency synthesizer calibration
    #define FSCAL1 0x25 // Frequency synthesizer calibration
    #define FSCAL0 0x26 // Frequency synthesizer calibration
    #define RCCTRL1 0x27 // RC oscillator configuration
    #define RCCTRL0 0x28 // RC oscillator configuration
    #define FSTEST 0x29 // Frequency synthesizer cal control
    #define PTEST 0x2A // Production test
    #define AGCTEST 0x2B // AGC test
    #define TEST2 0x2C // Various test settings
    #define TEST1 0x2D // Various test settings
    #define TEST0 0x2E // Various test settings

    // Strobe commands
    #define RF_SRES 0x30 // Reset chip.
    #define RF_SFSTXON 0x31 // Enable/calibrate freq synthesizer
    #define RF_SXOFF 0x32 // Turn off crystal oscillator.
    #define RF_SCAL 0x33 // Calibrate freq synthesizer & disable
    #define RF_SRX 0x34 // Enable RX.
    #define RF_STX 0x35 // Enable TX.
    #define RF_SIDLE 0x36 // Exit RX / TX
    #define RF_SAFC 0x37 // AFC adjustment of freq synthesizer
    #define RF_SWOR 0x38 // Start automatic RX polling sequence
    #define RF_SPWD 0x39 // Enter pwr down mode when CSn goes hi
    #define RF_SFRX 0x3A // Flush the RX FIFO buffer.
    #define RF_SFTX 0x3B // Flush the TX FIFO buffer.
    #define RF_SWORRST 0x3C // Reset real time clock.
    #define RF_SNOP 0x3D // No operation.

    // Status registers
    #define PARTNUM 0x30 // Part number
    #define VERSION 0x31 // Current version number
    #define FREQEST 0x32 // Frequency offset estimate
    #define LQI 0x33 // Demodulator estimate for link quality
    #define RSSI 0x34 // Received signal strength indication
    #define MARCSTATE 0x35 // Control state machine state
    #define WORTIME1 0x36 // High byte of WOR timer
    #define WORTIME0 0x37 // Low byte of WOR timer
    #define PKTSTATUS 0x38 // Current GDOx status and packet status
    #define VCO_VC_DAC 0x39 // Current setting from PLL cal module
    #define TXBYTES 0x3A // Underflow and # of bytes in TXFIFO
    #define RXBYTES 0x3B // Overflow and # of bytes in RXFIFO

    // Other memory locations
    #define PATABLE 0x3E
    #define TXFIFO 0x3F
    #define RXFIFO 0x3F

    // Masks for appended status bytes
    #define RSSI_RX 0x00 // Position of LQI byte
    #define LQI_RX 0x01 // Position of LQI byte
    #define CRC_OK 0x80 // Mask "CRC_OK" bit within LQI byte
    #define NUM_RXBYTES 0x7F // Mask "# of bytes" field in _RXBYTES

    // Definitions to support burst/single access:
    #define WRITE_BURST 0x40
    #define READ_SINGLE 0x80
    #define READ_BURST 0xC0

    // Packet length = 255
    // Data rate = 249.939
    // Address config = No address check
    // Base frequency = 914.999969
    // Carrier frequency = 914.999969
    // Whitening = false
    // RX filter BW = 541.666667
    // TX power = 0
    // Device address = 0
    // Channel spacing = 199.951172
    // Deviation = 126.953125
    // CRC enable = true
    // CRC autoflush = false
    // Modulated = true
    // Preamble count = 4
    // Manchester enable = false
    // Data format = Normal mode
    // Modulation format = 2-GFSK
    // Sync word qualifier mode = 30/32 sync word bits detected
    // Packet length mode = Variable packet length mode. Packet length configured by the first byte after sync word
    // Channel number = 0
    // PA ramping = false

    static const registerSetting_t preferredSettings[]=
    {
    {IOCFG2, 0x29},
    {IOCFG1, 0x2E},
    {IOCFG0, 0x06},
    {FIFOTHR, 0x07},
    {SYNC1, 0xD3},
    {SYNC0, 0x91},
    {PKTLEN, 0xFF},
    {PKTCTRL1, 0x04},
    {PKTCTRL0, 0x05},
    {FSCTRL1, 0x0C},
    {FREQ2, 0x23},
    {FREQ1, 0x31},
    {FREQ0, 0x3B},
    {MDMCFG4, 0x2D},
    {MDMCFG3, 0x3B},
    {MDMCFG2, 0x13},
    {MDMCFG1, 0x22},
    {MDMCFG0, 0xF8},
    {DEVIATN, 0x62},
    {MCSM2, 0x07},
    {MCSM1, 0x30},
    {MCSM0, 0x10},
    {FOCCFG, 0x1D},
    {BSCFG, 0x1C},
    {AGCCTRL2, 0xC7},
    {AGCCTRL1, 0x00},
    {AGCCTRL0, 0xB0},
    {WORCTRL, 0xFB},
    {FREND1, 0xB6},
    {FSCAL3, 0xEA},
    {FSCAL2, 0x2A},
    {FSCAL1, 0x00},
    {FSCAL0, 0x1F},
    {TEST0, 0x09},
    };



    unsigned char strobe(unsigned char strobe) {
    unsigned char statusByte = 0;

    // Check for valid strobe command
    if((strobe == 0xBD) || ((strobe >= RF_SRES) && (strobe <= RF_SNOP))) {
    // Clear the Status read flag
    RF1AIFCTL1 &= ~(RFSTATIFG);

    // Wait for radio to be ready for next instruction
    while( !(RF1AIFCTL1 & RFINSTRIFG));

    // Write the strobe instruction
    if ((strobe > RF_SRES) && (strobe < RF_SNOP)) {

    RF1AINSTRB = strobe;
    if ( (RF1AIN&0x04)== 0x04 ){ // chip at sleep mode
    if ( (strobe == RF_SXOFF) || (strobe == RF_SPWD) || (strobe == RF_SWOR) ) { }
    else {
    while ((RF1AIN&0x04)== 0x04); // chip-ready ?
    // Delay for ~810usec at 1.05MHz CPU clock, see erratum RF1A7
    __delay_cycles(850);
    }
    }
    while( !(RF1AIFCTL1 & RFSTATIFG) );
    }
    else { // chip active mode (SRES)
    RF1AINSTRB = strobe;
    }
    statusByte = RF1ASTATB;
    }
    return statusByte;
    }


    void cc430_write_burst_reg(unsigned char addr, unsigned char *buffer, unsigned char count) {

    unsigned char i;

    while (!(RF1AIFCTL1 & RFINSTRIFG)); // Wait for the Radio to be ready for next instruction
    RF1AINSTRW = ((addr | RF_REGWR)<<8 ) + buffer[0]; // Send address + Instruction

    for (i = 1; i < count; i++)
    {
    RF1ADINB = buffer[i]; // Send data
    while (!(RFDINIFG & RF1AIFCTL1)); // Wait for TX to finish
    }
    i = RF1ADOUTB; // Reset RFDOUTIFG flag which contains status byte
    }


    void cc430_write_reg(unsigned char addr, unsigned char value) {

    while (!(RF1AIFCTL1 & RFINSTRIFG)); // Wait for the Radio to be ready for next instruction
    RF1AINSTRB = (addr | RF_REGWR); // Send address + Instruction

    RF1ADINB = value; // Write data in

    __no_operation();
    }

    //****************************************************************************//
    // Set VCore Up
    //****************************************************************************//
    unsigned int SetVCoreUp (unsigned char level)
    {
    unsigned int PMMRIE_backup,SVSMHCTL_backup;

    // Open PMM registers for write access
    PMMCTL0_H = 0xA5;

    // Disable dedicated Interrupts to prevent that needed flags will be cleared
    PMMRIE_backup = PMMRIE;
    PMMRIE &= ~(SVSMHDLYIE | SVSMLDLYIE | SVMLVLRIE | SVMHVLRIE | SVMHVLRPE);
    // Set SVM highside to new level and check if a VCore increase is possible
    SVSMHCTL_backup = SVSMHCTL;
    PMMIFG &= ~(SVMHIFG | SVSMHDLYIFG);
    SVSMHCTL = SVMHE | SVMHFP | (SVSMHRRL0 * level);
    // Wait until SVM highside is settled
    while ((PMMIFG & SVSMHDLYIFG) == 0);

    // Disable full-performance mode to save energy
    //SVSMHCTL &= ~_HAL_PMM_SVSFP ;

    // Check if a VCore increase is possible
    if ((PMMIFG & SVMHIFG) == SVMHIFG){ //-> Vcc is to low for a Vcore increase
    // recover the previous settings
    PMMIFG &= ~SVSMHDLYIFG;
    SVSMHCTL = SVSMHCTL_backup;
    // Wait until SVM highside is settled
    while ((PMMIFG & SVSMHDLYIFG) == 0);
    // Clear all Flags
    PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    // backup PMM-Interrupt-Register
    PMMRIE = PMMRIE_backup;

    // Lock PMM registers for write access
    PMMCTL0_H = 0x00;
    return PMM_STATUS_ERROR; // return: voltage not set
    }
    // Set also SVS highside to new level //-> Vcc is high enough for a Vcore increase
    SVSMHCTL |= SVSHE | (SVSHRVL0 * level);
    // Set SVM low side to new level
    SVSMLCTL = SVMLE | SVMLFP | (SVSMLRRL0 * level);
    // Wait until SVM low side is settled
    while ((PMMIFG & SVSMLDLYIFG) == 0);
    // Clear already set flags
    PMMIFG &= ~(SVMLVLRIFG | SVMLIFG);
    // Set VCore to new level
    PMMCTL0_L = PMMCOREV0 * level;
    // Wait until new level reached
    if (PMMIFG & SVMLIFG)
    while ((PMMIFG & SVMLVLRIFG) == 0);
    // Set also SVS/SVM low side to new level
    PMMIFG &= ~SVSMLDLYIFG;
    SVSMLCTL |= SVSLE | (SVSLRVL0 * level);
    // wait for lowside delay flags
    while ((PMMIFG & SVSMLDLYIFG) == 0);

    // Disable SVS/SVM Low
    // Disable full-performance mode to save energy
    // SVSMLCTL &= ~(_HAL_PMM_DISABLE_SVSL_+_HAL_PMM_DISABLE_SVML_+_HAL_PMM_SVSFP );

    // Clear all Flags
    PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    // backup PMM-Interrupt-Register
    PMMRIE = PMMRIE_backup;

    // Lock PMM registers for write access
    PMMCTL0_H = 0x00;
    return PMM_STATUS_OK; // return: OK
    }


    void main(void) {
    unsigned char i;
    unsigned char actlevel;
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer


    P1DIR |= BIT0;
    P1OUT &= ~BIT0;

    actlevel = (PMMCTL0 & PMMCOREV_3); // Get actual VCore

    while(actlevel < 2) {
    actlevel++;
    SetVCoreUp (actlevel);
    };

    actlevel = (PMMCTL0 & PMMCOREV_3); // Get actual VCore

    // Write registers to radio
    for(i = 0; i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) {
    cc430_write_reg(preferredSettings[i].addr, preferredSettings[i].data);
    }

    /* enable global interrupts */
    _BIS_SR(GIE);

    while(1) {
    cc430_send();
    }

    }


    void cc430_send(void)
    {
    unsigned char u;

    /* byte number 0 contains the length byte, not including itself */
    TxBuffer[0] = TX_PKT_LENGTH-1;

    /* fill the buffer with data */
    for(u=1; u<TX_PKT_LENGTH; u++){
    TxBuffer[u] = 0x45;
    }

    cc430_write_burst_reg(TXFIFO, TxBuffer, TX_PKT_LENGTH);

    /* Force the radio into IDLE and flush FIFO's */
    ReceiveOff();

    /* transmit data */
    Transmit( TxBuffer, TX_PKT_LENGTH);

    return;

    }

    void Transmit(unsigned char *buffer, unsigned char length)
    {

    // BIT9 is the Sync recieved/sent and end-of-packet.
    RF1AIES |= BIT9; // edge select, high to low (end-of-packet)
    RF1AIFG &= ~BIT9; // Clear pending interrupts
    RF1AIE |= BIT9; // Enable TX end-of-packet interrupt

    strobe( RF_STX ); // Strobe STX

    /* set global value to indicate start of transmission */
    transmitting = 1;

    /* blink LED to indicate busy wait for RF to complete */
    P1OUT |= BIT0;
    while(transmitting);
    P1OUT &= ~BIT0;

    RF1AIE &= ~BIT9; // disable TX end-of-packet interrupt

    }

    void ReceiveOn(void)
    {
    // PA
    P3OUT |= 0x40; // Set RX
    P1OUT &= ~0x1; // Clear TX

    RF1AIES |= BIT9; // Falling edge of RFIFG9
    RF1AIFG &= ~BIT9; // Clear a pending interrupt
    RF1AIE |= BIT9; // Enable the interrupt

    // Radio is in IDLE following a TX, so strobe SRX to enter Receive Mode
    strobe( RF_SRX );
    }

    void ReceiveOff(void){
    P3OUT &= ~0x40; // Clear RX
    P1OUT |= 0x01; // Set TX

    RF1AIE &= ~BIT9; // Disable RX interrupts
    RF1AIFG &= ~BIT9; // Clear pending IFG

    strobe( RF_SIDLE );
    strobe( RF_SFRX );
    }

    #pragma vector=CC1101_VECTOR
    __interrupt void CC1101_ISR(void) {

    switch(__even_in_range(RF1AIV,32)) // Prioritizing Radio Core Interrupt
    {
    case 20:
    // If device isn't tranmitting -> receive // RFIFG9
    if(!transmitting){ // RX end of packet
    /* removed RX function here */
    }

    if(transmitting) // TX end of packet
    {
    RF1AIE &= ~BIT9; // Disable TX end-of-packet interrupt
    transmitting = 0;
    }
    break;
    }
    }
  • Rui et al,

    I have updated the code I published earlier to also include a working RX function.

    Take two CC430 boards create a transmitter by compiling the code with this option

    #define RF_MODE TX_MODE

    then create a receiver by compiling the code with this option

    #define RF_MODE TX_MODE

    The transmitter will blink the green LED every time it is waiting for the TX engine to complete, the RX side will blink green after it has received a packet.

    Regards,
    /TA


    #include <msp430.h>

    /*
    * main.c
    */

    #define RX_MODE 0x01
    #define TX_MODE 0x02

    /* define the mode the code should operation in */
    #define RF_MODE RX_MODE


    typedef struct {
    unsigned int addr;
    unsigned char data;
    } registerSetting_t;


    void cc430_send(void);
    void cc430_receive(void);

    void Transmit(unsigned char *buffer, unsigned char length);
    void ReceiveOff(void);
    void cc430_write_reg(unsigned char addr, unsigned char value);

    #define TX_PKT_LENGTH 55
    unsigned char TxBuffer[TX_PKT_LENGTH];
    unsigned char uip_buf[TX_PKT_LENGTH];
    unsigned char transmitting, receiving;

    #define PMM_STATUS_OK 0
    #define PMM_STATUS_ERROR 1

    // Configuration Registers
    #define IOCFG2 0x00 // GDO2 output pin configuration
    #define IOCFG1 0x01 // GDO1 output pin configuration
    #define IOCFG0 0x02 // GDO0 output pin configuration
    #define FIFOTHR 0x03 // RX FIFO and TX FIFO thresholds
    #define SYNC1 0x04 // Sync word, high byte
    #define SYNC0 0x05 // Sync word, low byte
    #define PKTLEN 0x06 // Packet length
    #define PKTCTRL1 0x07 // Packet automation control
    #define PKTCTRL0 0x08 // Packet automation control
    #define ADDR 0x09 // Device address
    #define CHANNR 0x0A // Channel number
    #define FSCTRL1 0x0B // Frequency synthesizer control
    #define FSCTRL0 0x0C // Frequency synthesizer control
    #define FREQ2 0x0D // Frequency control word, high byte
    #define FREQ1 0x0E // Frequency control word, middle byte
    #define FREQ0 0x0F // Frequency control word, low byte
    #define MDMCFG4 0x10 // Modem configuration
    #define MDMCFG3 0x11 // Modem configuration
    #define MDMCFG2 0x12 // Modem configuration
    #define MDMCFG1 0x13 // Modem configuration
    #define MDMCFG0 0x14 // Modem configuration
    #define DEVIATN 0x15 // Modem deviation setting
    #define MCSM2 0x16 // Main Radio Cntrl State Machine config
    #define MCSM1 0x17 // Main Radio Cntrl State Machine config
    #define MCSM0 0x18 // Main Radio Cntrl State Machine config
    #define FOCCFG 0x19 // Frequency Offset Compensation config
    #define BSCFG 0x1A // Bit Synchronization configuration
    #define AGCCTRL2 0x1B // AGC control
    #define AGCCTRL1 0x1C // AGC control
    #define AGCCTRL0 0x1D // AGC control
    #define WOREVT1 0x1E // High byte Event 0 timeout
    #define WOREVT0 0x1F // Low byte Event 0 timeout
    #define WORCTRL 0x20 // Wake On Radio control
    #define FREND1 0x21 // Front end RX configuration
    #define FREND0 0x22 // Front end TX configuration
    #define FSCAL3 0x23 // Frequency synthesizer calibration
    #define FSCAL2 0x24 // Frequency synthesizer calibration
    #define FSCAL1 0x25 // Frequency synthesizer calibration
    #define FSCAL0 0x26 // Frequency synthesizer calibration
    #define RCCTRL1 0x27 // RC oscillator configuration
    #define RCCTRL0 0x28 // RC oscillator configuration
    #define FSTEST 0x29 // Frequency synthesizer cal control
    #define PTEST 0x2A // Production test
    #define AGCTEST 0x2B // AGC test
    #define TEST2 0x2C // Various test settings
    #define TEST1 0x2D // Various test settings
    #define TEST0 0x2E // Various test settings

    // Strobe commands
    #define RF_SRES 0x30 // Reset chip.
    #define RF_SFSTXON 0x31 // Enable/calibrate freq synthesizer
    #define RF_SXOFF 0x32 // Turn off crystal oscillator.
    #define RF_SCAL 0x33 // Calibrate freq synthesizer & disable
    #define RF_SRX 0x34 // Enable RX.
    #define RF_STX 0x35 // Enable TX.
    #define RF_SIDLE 0x36 // Exit RX / TX
    #define RF_SAFC 0x37 // AFC adjustment of freq synthesizer
    #define RF_SWOR 0x38 // Start automatic RX polling sequence
    #define RF_SPWD 0x39 // Enter pwr down mode when CSn goes hi
    #define RF_SFRX 0x3A // Flush the RX FIFO buffer.
    #define RF_SFTX 0x3B // Flush the TX FIFO buffer.
    #define RF_SWORRST 0x3C // Reset real time clock.
    #define RF_SNOP 0x3D // No operation.

    // Status registers
    #define PARTNUM 0x30 // Part number
    #define VERSION 0x31 // Current version number
    #define FREQEST 0x32 // Frequency offset estimate
    #define LQI 0x33 // Demodulator estimate for link quality
    #define RSSI 0x34 // Received signal strength indication
    #define MARCSTATE 0x35 // Control state machine state
    #define WORTIME1 0x36 // High byte of WOR timer
    #define WORTIME0 0x37 // Low byte of WOR timer
    #define PKTSTATUS 0x38 // Current GDOx status and packet status
    #define VCO_VC_DAC 0x39 // Current setting from PLL cal module
    #define TXBYTES 0x3A // Underflow and # of bytes in TXFIFO
    #define RXBYTES 0x3B // Overflow and # of bytes in RXFIFO

    // Other memory locations
    #define PATABLE 0x3E
    #define TXFIFO 0x3F
    #define RXFIFO 0x3F

    // Masks for appended status bytes
    #define RSSI_RX 0x00 // Position of LQI byte
    #define LQI_RX 0x01 // Position of LQI byte
    #define CRC_OK 0x80 // Mask "CRC_OK" bit within LQI byte
    #define NUM_RXBYTES 0x7F // Mask "# of bytes" field in _RXBYTES

    // Definitions to support burst/single access:
    #define WRITE_BURST 0x40
    #define READ_SINGLE 0x80
    #define READ_BURST 0xC0

    // Packet length = 255
    // Data rate = 249.939
    // Address config = No address check
    // Base frequency = 914.999969
    // Carrier frequency = 914.999969
    // Whitening = false
    // RX filter BW = 541.666667
    // TX power = 0
    // Device address = 0
    // Channel spacing = 199.951172
    // Deviation = 126.953125
    // CRC enable = true
    // CRC autoflush = false
    // Modulated = true
    // Preamble count = 4
    // Manchester enable = false
    // Data format = Normal mode
    // Modulation format = 2-GFSK
    // Sync word qualifier mode = 30/32 sync word bits detected
    // Packet length mode = Variable packet length mode. Packet length configured by the first byte after sync word
    // Channel number = 0
    // PA ramping = false

    static const registerSetting_t preferredSettings[]=
    {
    {IOCFG2, 0x29},
    {IOCFG1, 0x2E},
    {IOCFG0, 0x06},
    {FIFOTHR, 0x07},
    {SYNC1, 0xD3},
    {SYNC0, 0x91},
    {PKTLEN, 0xFF},
    {PKTCTRL1, 0x04},
    {PKTCTRL0, 0x05},
    {FSCTRL1, 0x0C},
    {FREQ2, 0x23},
    {FREQ1, 0x31},
    {FREQ0, 0x3B},
    {MDMCFG4, 0x2D},
    {MDMCFG3, 0x3B},
    {MDMCFG2, 0x13},
    {MDMCFG1, 0x22},
    {MDMCFG0, 0xF8},
    {DEVIATN, 0x62},
    {MCSM2, 0x07},
    {MCSM1, 0x30},
    {MCSM0, 0x10},
    {FOCCFG, 0x1D},
    {BSCFG, 0x1C},
    {AGCCTRL2, 0xC7},
    {AGCCTRL1, 0x00},
    {AGCCTRL0, 0xB0},
    {WORCTRL, 0xFB},
    {FREND1, 0xB6},
    {FSCAL3, 0xEA},
    {FSCAL2, 0x2A},
    {FSCAL1, 0x00},
    {FSCAL0, 0x1F},
    {TEST0, 0x09},
    };



    unsigned char strobe(unsigned char strobe) {
    unsigned char statusByte = 0;

    // Check for valid strobe command
    if((strobe == 0xBD) || ((strobe >= RF_SRES) && (strobe <= RF_SNOP))) {
    // Clear the Status read flag
    RF1AIFCTL1 &= ~(RFSTATIFG);

    // Wait for radio to be ready for next instruction
    while( !(RF1AIFCTL1 & RFINSTRIFG));

    // Write the strobe instruction
    if ((strobe > RF_SRES) && (strobe < RF_SNOP)) {

    RF1AINSTRB = strobe;
    if ( (RF1AIN&0x04)== 0x04 ){ // chip at sleep mode
    if ( (strobe == RF_SXOFF) || (strobe == RF_SPWD) || (strobe == RF_SWOR) ) { }
    else {
    while ((RF1AIN&0x04)== 0x04); // chip-ready ?
    // Delay for ~810usec at 1.05MHz CPU clock, see erratum RF1A7
    __delay_cycles(850);
    }
    }
    while( !(RF1AIFCTL1 & RFSTATIFG) );
    }
    else { // chip active mode (SRES)
    RF1AINSTRB = strobe;
    }
    statusByte = RF1ASTATB;
    }
    return statusByte;
    }


    void cc430_write_burst_reg(unsigned char addr, unsigned char *buffer, unsigned char count) {

    unsigned char i;

    while (!(RF1AIFCTL1 & RFINSTRIFG)); // Wait for the Radio to be ready for next instruction
    RF1AINSTRW = ((addr | RF_REGWR)<<8 ) + buffer[0]; // Send address + Instruction

    for (i = 1; i < count; i++)
    {
    RF1ADINB = buffer[i]; // Send data
    while (!(RFDINIFG & RF1AIFCTL1)); // Wait for TX to finish
    }
    i = RF1ADOUTB; // Reset RFDOUTIFG flag which contains status byte
    }


    void cc430_write_reg(unsigned char addr, unsigned char value) {

    while (!(RF1AIFCTL1 & RFINSTRIFG)); // Wait for the Radio to be ready for next instruction
    RF1AINSTRB = (addr | RF_REGWR); // Send address + Instruction

    RF1ADINB = value; // Write data in

    __no_operation();
    }

    //****************************************************************************//
    // Set VCore Up
    //****************************************************************************//
    unsigned int SetVCoreUp (unsigned char level)
    {
    unsigned int PMMRIE_backup,SVSMHCTL_backup;

    // Open PMM registers for write access
    PMMCTL0_H = 0xA5;

    // Disable dedicated Interrupts to prevent that needed flags will be cleared
    PMMRIE_backup = PMMRIE;
    PMMRIE &= ~(SVSMHDLYIE | SVSMLDLYIE | SVMLVLRIE | SVMHVLRIE | SVMHVLRPE);
    // Set SVM highside to new level and check if a VCore increase is possible
    SVSMHCTL_backup = SVSMHCTL;
    PMMIFG &= ~(SVMHIFG | SVSMHDLYIFG);
    SVSMHCTL = SVMHE | SVMHFP | (SVSMHRRL0 * level);
    // Wait until SVM highside is settled
    while ((PMMIFG & SVSMHDLYIFG) == 0);

    // Disable full-performance mode to save energy
    //SVSMHCTL &= ~_HAL_PMM_SVSFP ;

    // Check if a VCore increase is possible
    if ((PMMIFG & SVMHIFG) == SVMHIFG){ //-> Vcc is to low for a Vcore increase
    // recover the previous settings
    PMMIFG &= ~SVSMHDLYIFG;
    SVSMHCTL = SVSMHCTL_backup;
    // Wait until SVM highside is settled
    while ((PMMIFG & SVSMHDLYIFG) == 0);
    // Clear all Flags
    PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    // backup PMM-Interrupt-Register
    PMMRIE = PMMRIE_backup;

    // Lock PMM registers for write access
    PMMCTL0_H = 0x00;
    return PMM_STATUS_ERROR; // return: voltage not set
    }
    // Set also SVS highside to new level //-> Vcc is high enough for a Vcore increase
    SVSMHCTL |= SVSHE | (SVSHRVL0 * level);
    // Set SVM low side to new level
    SVSMLCTL = SVMLE | SVMLFP | (SVSMLRRL0 * level);
    // Wait until SVM low side is settled
    while ((PMMIFG & SVSMLDLYIFG) == 0);
    // Clear already set flags
    PMMIFG &= ~(SVMLVLRIFG | SVMLIFG);
    // Set VCore to new level
    PMMCTL0_L = PMMCOREV0 * level;
    // Wait until new level reached
    if (PMMIFG & SVMLIFG)
    while ((PMMIFG & SVMLVLRIFG) == 0);
    // Set also SVS/SVM low side to new level
    PMMIFG &= ~SVSMLDLYIFG;
    SVSMLCTL |= SVSLE | (SVSLRVL0 * level);
    // wait for lowside delay flags
    while ((PMMIFG & SVSMLDLYIFG) == 0);

    // Disable SVS/SVM Low
    // Disable full-performance mode to save energy
    // SVSMLCTL &= ~(_HAL_PMM_DISABLE_SVSL_+_HAL_PMM_DISABLE_SVML_+_HAL_PMM_SVSFP );

    // Clear all Flags
    PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    // backup PMM-Interrupt-Register
    PMMRIE = PMMRIE_backup;

    // Lock PMM registers for write access
    PMMCTL0_H = 0x00;
    return PMM_STATUS_OK; // return: OK
    }


    void main(void) {
    unsigned char i;
    unsigned char actlevel;
    WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer


    P1DIR |= BIT0;
    P1OUT &= ~BIT0;

    actlevel = (PMMCTL0 & PMMCOREV_3); // Get actual VCore

    while(actlevel < 2) {
    actlevel++;
    SetVCoreUp (actlevel);
    }

    // Write registers to radio
    for(i = 0; i < (sizeof(preferredSettings)/sizeof(registerSetting_t)); i++) {
    cc430_write_reg(preferredSettings[i].addr, preferredSettings[i].data);
    }

    /* enable global interrupts */
    _BIS_SR(GIE);

    while(1) {
    switch(RF_MODE) {

    case TX_MODE:

    cc430_send();
    break;

    case RX_MODE:

    /* initialize the RX chain and wait for a packet */
    cc430_receive();

    /* do not do anything with the data, just flush it and get a new packet */
    ReceiveOff();

    break;
    default:
    break;
    }
    }
    }


    void cc430_send(void)
    {
    unsigned char u;

    /* byte number 0 contains the length byte, not including itself */
    TxBuffer[0] = TX_PKT_LENGTH-1;

    /* fill the buffer with data */
    for(u=1; u<TX_PKT_LENGTH; u++){
    TxBuffer[u] = 0x45;
    }

    cc430_write_burst_reg(TXFIFO, TxBuffer, TX_PKT_LENGTH);

    /* Force the radio into IDLE and flush FIFO's */
    ReceiveOff();

    /* transmit data */
    Transmit( TxBuffer, TX_PKT_LENGTH);

    return;

    }

    void Transmit(unsigned char *buffer, unsigned char length)
    {

    // BIT9 is the Sync recieved/sent and end-of-packet.
    RF1AIES |= BIT9; // edge select, high to low (end-of-packet)
    RF1AIFG &= ~BIT9; // Clear pending interrupts
    RF1AIE |= BIT9; // Enable TX end-of-packet interrupt

    strobe( RF_STX ); // Strobe STX

    /* set global value to indicate start of transmission */
    transmitting = 1;

    /* blink LED to indicate busy wait for RF to complete */
    P1OUT |= BIT0;
    while(transmitting);
    P1OUT &= ~BIT0;

    RF1AIE &= ~BIT9; // disable TX end-of-packet interrupt

    }

    void cc430_receive(void)
    {

    RF1AIES |= BIT9; // Falling edge of RFIFG9
    RF1AIFG &= ~BIT9; // Clear a pending interrupt
    RF1AIE |= BIT9; // Enable the interrupt

    /* set global value to indicate active RX mode */
    receiving = 1;

    strobe( RF_SRX );

    /* blink LED to indicate busy wait for RF to complete */
    P1OUT &= ~BIT0;
    while(receiving);
    P1OUT |= BIT0;

    RF1AIE &= ~BIT9; // disable RX end-of-packet interrupt

    }

    void ReceiveOff(void){
    P3OUT &= ~0x40; // Clear RX
    P1OUT |= 0x01; // Set TX

    RF1AIE &= ~BIT9; // Disable RX interrupts
    RF1AIFG &= ~BIT9; // Clear pending IFG

    strobe( RF_SIDLE );
    strobe( RF_SFRX );
    }

    #pragma vector=CC1101_VECTOR
    __interrupt void CC1101_ISR(void) {

    switch(__even_in_range(RF1AIV,32)) // Prioritizing Radio Core Interrupt
    {
    case 20:
    // If device isn't tranmitting -> receive // RFIFG9
    if(receiving){ // RX end of packet
    RF1AIE &= ~BIT9; // Disable TX end-of-packet interrupt
    receiving = 0;
    }

    if(transmitting) // TX end of packet
    {
    RF1AIE &= ~BIT9; // Disable TX end-of-packet interrupt
    transmitting = 0;
    }
    break;
    }
    }