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.

eZ430-RF2500 - Wake On Radio (WOR) example.

Other Parts Discussed in Thread: CC2500, SIMPLICITI, MSP430F2274

There has been alot of interest in Wake-On-Radio. But very little useful code to implement it.

Here is a working example / template for a wake on radio project.

You can download the complete project here: http://mtaylor.ca/home/e107_files/public/1273603830_2_FT0_wor.example.zip

The code supplied for the Access Point has a complete GUI menu.
Program one device with the AP code and open up Hyperterminal / Putty.
Press 'M' to bring up the GUI menu.
This is what you will see:

What would you like to do?
 (0) Wake Up Device
 (1) Toggle LEDs
 (2) Turn Device Off

Pressing '0' will send the wake up command which is a stream of packets containing the code 65.
The green LED will be on while its sending the packets. Packets should be sent for 2x the WOR interval.

The ED will now be on and you will see that both of its LEDs are on. Press '1' to toggle the LEDs.
Pressing '2' will turn the LEDs off and place the ED back into sleep mode.



The End Device has a very simple function. Program it and connect it to the battery pack.
The ED will wake up every 1884 ms. To adjust this time, change the values of WOREVT1 and WOREVT0.
To determine what values to use, simply plug the desired delay into the Excel calculator.

When the ED wakes up it checks to make sure the packet recieved contains code 65. To ensure it is the wakeup command.
The LED is then turned on. Further packets containing the message 'TEST' will cause the LED to change state.
When the 'STOP' packet is recieved, WOR mode is re-enabled.

Note: both devices need to be set to the same channel to allow communication. Changing channels allows you to use multiple devices at the same time.

 

End Device Code:

//-------End Device Code---------
//---------Matt Taylor-----------

#include "msp430x22x4.h"
#include "radios/family1/mrfi_spi.h"
#include "mrfi.h"

//Global Variables
int i;
int WOR_Enabled=1; //Controls whether WakeOnRadio is ON (1) or OFF (0)

//Function Prototypes
void MCU_Init(void);
void packetHandling(mrfiPacket_t packet); //Determines appropriate action for recieved packet

//WOR Code from Thomas Watteyne's Tutorial
void wor_init();
void wor_start();
void wor_stop();

//-------------------------MAIN-------------------------------------------------
void main(void)
{
    WDTCTL = WDTPW + WDTHOLD; //Stop WDT
    MCU_Init();
    //---------------------Start Wakeup Protocol----------
    //--------------------Code from Chat program----------
    BSP_Init();
    MRFI_Init();
    int channel=20; //Channels from 0 to 200
    MRFI_WakeUp();
    MRFI_RxIdle();
    mrfiSpiWriteReg(CHANNR,channel);
    MRFI_RxOn();
    P1DIR |= 0x03;
    //---------------------Start Wakeup Protocol----------
    if (WOR_Enabled==1) {
        wor_init();
        wor_start();
        char output[] = {"\r\nDevice set to channel: 20 \r\nEntering Sleep Mode"};
        TXString(output, (sizeof output)-1);
    }
    if (WOR_Enabled==0) {
        char output[] = {"\r\nDevice Ready"};
        TXString(output, (sizeof output)-1);
    }
    __bis_SR_register(GIE+LPM4_bits);
    //----------------------------------------------------
}//end main

//-------------------------MCU INITIATE-----------------------------------------
void MCU_Init()
{
    BCSCTL1 = CALBC1_8MHZ; //Set DCO
    DCOCTL = CALDCO_8MHZ;
    BCSCTL3 |= LFXT1S_2; //LFXT1 = VLO
    TACCTL0 = CCIE; //TACCR0 interrupt enabled
    TACCR0 = 12000; //~1 second
    TACTL = TASSEL_1 + MC_1; //ACLK, upmode

    P3SEL |= 0x30; //P3.4,5 = USCI_A0 TXD/RXD
    UCA0CTL1 = UCSSEL_2; //SMCLK
    UCA0BR0 = 0x41; //9600 from 8Mhz
    UCA0BR1 = 0x3;
    UCA0MCTL = UCBRS_2;
    UCA0CTL1 &= ~UCSWRST; //**Initialize USCI state machine**
    IE2 |= UCA0RXIE; //Enable USCI_A0 RX interrupt
    __enable_interrupt();
}

//--------------------------PACKET RECEIVING------------------------------------
void MRFI_RxCompleteISR()
{
    mrfiPacket_t packet;
    if (WOR_Enabled==1)
        wor_stop();
    MRFI_Receive(&packet);
    char received[] = {"\r\nWakeUP received"};
    //If the device is currently sleeping, check if the incoming packet contains the wakeup code (65)
    if (WOR_Enabled==1) {
        if ((MRFI_P_PAYLOAD(&packet))[2]==65) {
            TXString(received, (sizeof received)-1);
            WOR_Enabled=0;
            main(); //Restart main program with WOR disabled
        }
        else { MRFI_WakeUp(); MRFI_RxOn(); }
    }
    else //Wake on radio has been disabled
    {
        packetHandling(packet); //Determine action
    }
}

//------------------DETERMINE ACTION BASED ON COMMAND PACKET--------------------
void packetHandling(mrfiPacket_t packet)
{
    for (int i=9;i<29;i++) //Cycle through the Packet
    {
        if (packet.frame[i-3]=='T' && packet.frame[i-2]=='E' && packet.frame[i-1]=='S' && packet.frame[i]=='T')
            P1OUT ^= 0x03;

        if (packet.frame[i-3]=='S' && packet.frame[i-2]=='T' && packet.frame[i-1]=='O' && packet.frame[i]=='P')
        {
            P1OUT&=~0x03; //LED OFF
            WOR_Enabled=1;
            MCU_Init();
            wor_init();
            wor_start(); //Restart program with WOR enabled
        }
    } //end for
}

//--------------------------WAKE ON RADIO FUNCTIONS-----------------------------
void wor_init()
{
    uint8_t reg;
    //Change the values of WOREVT1 and WOREVT0 to adjust the WOR interval
    //FFFA = 1884ms
    mrfiSpiWriteReg(WOREVT1, 0xFF);
    mrfiSpiWriteReg(WOREVT0, 0xFA);
    /* choose EVENT1[WORCTRL.6-4]                         == 7=0b111        */
    reg  = mrfiSpiReadReg(WORCTRL);
    reg |=  0x70;
    mrfiSpiWriteReg(WORCTRL, reg);
    /* enable frequence calibration RC_CAL[WORCTRL.3]     == 1              */
    reg  = mrfiSpiReadReg(WORCTRL);
    reg |=  0x80;
    mrfiSpiWriteReg(WORCTRL, reg);
    /* choose WOR_RES[WORCTRL.1-0]                        == 00             */
    reg  = mrfiSpiReadReg(WORCTRL);
    reg &= ~0x03;
    mrfiSpiWriteReg(WORCTRL, reg);
    /* choose when to calibrate FS_AUTOCAL[MCSM0.5-4]     == 01             */
    reg  = mrfiSpiReadReg(MCSM0);
    reg &= ~0x20;
    reg |=  0x10;
    mrfiSpiWriteReg(MCSM0, reg);
    /* initial filter by rssi RX_TIME_RSSI[MCSM2.4]       == 0              */
    reg  = mrfiSpiReadReg(MCSM2);
    reg &= ~0x10;
    mrfiSpiWriteReg(MCSM2, reg);
    /* stay in Rx after preamble RX_TIME_QUAL[MCSM2.3]    == 0              */
    reg  = mrfiSpiReadReg(MCSM2);
    reg &= ~0x08;
    mrfiSpiWriteReg(MCSM2, reg);
    /* enable RC oscilator RC_PD[WORCTRL.7]               == 0              */
    reg  = mrfiSpiReadReg(WORCTRL);
    reg &= ~0x80;
    mrfiSpiWriteReg(WORCTRL, reg);
    /* assert GDO2 at SYNC GDO2_CFG[IOCFG2.5-0]           == 0x06           */
    mrfiSpiWriteReg(IOCFG2, 0x06);          //P14=SYNC
}
void wor_start()
{
    /* choose RX_TIME[MCSM2.2-0]                          == 2=0b010        */
    uint8_t reg  = mrfiSpiReadReg(MCSM2);
    reg &= ~0x05;
    reg |=  0x02;
    //mrfiSpiWriteReg(MCSM2, reg);//test
    mrfiSpiWriteReg(MCSM2, 2);//test
    /* from IDLE state, enter WOR */
    MRFI_RxIdle();
    MRFI_RxWor();
}
void wor_stop()
{
    /* choose RX_TIME[MCSM2.2-0]                          == 7=0b111        */
    uint8_t reg  = mrfiSpiReadReg(MCSM2);
    reg |=  0x07;
    //mrfiSpiWriteReg(MCSM2,reg);
    mrfiSpiWriteReg(MCSM2,7);//test
    /* turn radio to IDLE, quitting WOR*/
    MRFI_RxIdle();
}

 

Access Point Code:

//----Access Point Code----
//---------Matt Taylor-----------

#include "msp430x22x4.h"
#include "radios/family1/mrfi_spi.h"
#include "mrfi.h"

//Packets
mrfiPacket_t wake_packet;
mrfiPacket_t stop_packet;
mrfiPacket_t packet;

//Function Prototypes
void GuiMenu();
void handleKeyboard(char); //Function to determine commands based on keystroke
void wakeOnRadio(); //Function to wakeup the radio

//-------------------------------MAIN-------------------------------------------
int main(void)
{
    BSP_Init();
    MRFI_Init();
    P3SEL |= 0x30; //P3.4,5 = USCI_A0 TXD/RXD
    UCA0CTL1 = UCSSEL_2; //SMCLK
    UCA0BR0 = 0x41; //9600 from 8Mhz
    UCA0BR1 = 0x3;
    UCA0MCTL = UCBRS_2;
    UCA0CTL1 &= ~UCSWRST; //Initialize USCI state machine
    IE2 |= UCA0RXIE; //Enable USCI_A0 RX interrupt
    int channel=20; //Channels from 0 to 200
    MRFI_WakeUp();
    MRFI_RxIdle();
    mrfiSpiWriteReg(CHANNR,channel);
    MRFI_RxOn();
    P1DIR |= 0x03; //LED outputs
    //--Clear Screen--
    for (int i=0; i<15; i++) {
        TXString("\r\n",2); }
    GuiMenu();
    __bis_SR_register(GIE+LPM4_bits);
}

//--------------------KEYBOARD INTERUPTS----------------------------------------
#pragma vector=USCIAB0RX_VECTOR
__interrupt void USCI0RX_ISR(void)
{
    char keystroke = UCA0RXBUF; //Capture keystroke
    handleKeyboard(keystroke); //GUI option
}

//--------------------------PACKET RECEIVING------------------------------------
void MRFI_RxCompleteISR()
{
    uint8_t i;
    MRFI_Receive(&packet);
    char output[] = {" "};

    for (i=9;i<29;i++) {
        output[i-9]=packet.frame[i]; }
    TXString(output, (sizeof output));

}
void GuiMenu()
{
    P1OUT &= ~0x03; //LEDs off
    //--Output GUI options--
    TXString( "\r\nWhat would you like to do?", 30 );
    TXString( "\r\n (0) Wake Up Device", 22 );
    TXString( "\r\n (1) Toggle LEDs", 20 );
    TXString( "\r\n (2) Turn Device Off", 22 );
    TXString( "\r\n", 3 );
}

//-----------------CONVERT KEYSTROKE TO COMMAND---------------------------------
void handleKeyboard(char keystroke)
{
    int i=0;
    //----------------------Setup Packets----------------------
    wake_packet.frame[0]=28;
    stop_packet.frame[0]=28;

    for(i=9;i<29;i++) {
        wake_packet.frame[i]=' ';
        stop_packet.frame[i]=' ';
    }
    wake_packet.frame[9]='T';
    wake_packet.frame[10]='E';
    wake_packet.frame[11]='S';
    wake_packet.frame[12]='T';

    stop_packet.frame[9]='S';
    stop_packet.frame[10]='T';
    stop_packet.frame[11]='O';
    stop_packet.frame[12]='P';
    //-------------------------------------------------------

    if (keystroke=='m' || keystroke=='M')
    {
        GuiMenu();
    }
    if (keystroke=='0')
    {
        wakeOnRadio();
        for (i=0;i<5000;i++) { __no_operation(); } //Delay for a bit
        MRFI_Transmit(&wake_packet, MRFI_TX_TYPE_FORCED); //Check if its ready
    }
    if (keystroke=='1')
    {
        MRFI_Transmit(&wake_packet, MRFI_TX_TYPE_FORCED);
        P1OUT ^= 0x01;
        for (i=0;i<3000;i++) { __no_operation(); }
        P1OUT ^= 0x01;
    }

    if (keystroke=='2')
    {
        P1OUT |= 0x01;
        for (i=0;i<30;i++){ //transmit stop packet a few times
            MRFI_Transmit(&stop_packet, MRFI_TX_TYPE_FORCED); }

        P1OUT&=~0x01;
    }

}

//------------------SEND WAKEUP COMMAND----------------------------------------
void wakeOnRadio() //Sends a mass amount of packets to wakeup ED
{
    P1IFG &= ~0x04;
    int counter;
    mrfiPacket_t packetToSend;
    MRFI_SET_PAYLOAD_LEN((&packetToSend),20);
    P1OUT ^= 0x02;

    for (counter=1000;counter>=1;counter--)
    {
        (MRFI_P_PAYLOAD(&packetToSend))[2] = 65;
        MRFI_Transmit(&packetToSend, MRFI_TX_TYPE_FORCED);
    }
    P1OUT ^= 0x02;
}
  • Hi Matt,

    thanks for sharing this with us. For future reference, it might be useful and make it quicker for other E2E members to understand if you could describe the HW platform & background info as well. I am assuming this is for the CC2500 on the eZ430-RF2500T target boards.

    For those who are also interested in Wake-on-Radio on the CC430 for the sub-1GHz freq. band, here is the recently published app note on this topic, with example using the EM430F6137RF900 kits.

     

    Regards,

    Dung

  • Hi, thanks for sharing this code, i relly appreciate your work.

    I tried to compile the code you posted, downloading the entire project, but i'm not able to run it. If i try to run the access point code, it compiles, download, but when i open Putty it gives me a blank screen, if i press 'm' or 'M' it makes no difference. I tried to copy the code in your post and compile in a different project, but nothing. 

    Another question, what libraries have you used in WOR.EXAMPLE/Drivers/gradient? In WOR.EXAMPLE/Drivers/ the other 2 directories are simpliciti? 

    Thanks, sorry for bad english.

  • Make sure you are using the correct COM port.

     

    The gradient drivers are from Thomas Watteyne's tutorial

    The other two driver folders are Board Support Package, and Minimal RF Interface from the demo program.

  • Hi everybody.

    First, I'm sorry for my bad english. I'm just a brazilian nerd. :D

    Matt Taylor, thank you very much for this example. I was searching for a WOR example for MSP430 + CC2500, and it "fell from the sky". :D

    Let me make one small remark about the "wor_init" function.

    In this piece of code:

        /* enable frequence calibration RC_CAL[WORCTRL.3]     == 1              */
        reg  = mrfiSpiReadReg(WORCTRL);
        reg |=  0x80;
        mrfiSpiWriteReg(WORCTRL, reg);

    You aren't enabling the frequence calibration (RC_CAL = 1), but just setting the power down signal to RC oscillator (RC_PD = WORCTRL.7).

    The correct value for setting the RC_CAL would be:

        /* enable frequence calibration RC_CAL[WORCTRL.3]     == 1              */
        reg  = mrfiSpiReadReg(WORCTRL);
        reg |=  0x08;
        mrfiSpiWriteReg(WORCTRL, reg);

    I will try your original code with an MSP430F2274 + RF2500 and post the results of tests soon.

    More one time, thank you very much.

  • The code that taylor posted suffers from stack corruption as it calls main from isr everytime and is not able to run completely.

  • I tried implementing the code on ez430-RF2500 kit. The End device stopped responding after few transmissions from AP. The debug log says stack corruption error. I saw the code and found calling main as eronous, due to which stack corruption is happening. Please help me to get a solution.

  • wake_packet.frame[0]=28;

    stop_packet.frame[0]=28;

    wake_packet.frame[9]='T';

    wake_packet.frame[10]='E';

    wake_packet.frame[11]='S';

    wake_packet.frame[12]='T';

    Hello Matt, My question is why the wake_packet.frame[0] has number 28? and also why the transmission packets are starting from wake_packet.frame[9]?? i tried by changing thos frame numbers but its not working!!! please help me with this. thank you.

  • Hello 

    I have a project that I use the EZ430-RF2500T and I need to use Wake On Radio to save battery.
    I also tried using the example of WOR done by Matt, but after some operations the End Device crashes.
    Has anyone fixed the problem of stack overflow?

    Thank you!

**Attention** This is a public forum