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.

How to switch the RF mode from RX to TX for CC1310?

Other Parts Discussed in Thread: CC1101, CC1310, SYSBIOS

Hi...

In my application I have to receive a RF packet from CC1101 and send the RF packet back to CC1101 and the cycle repeats. I am using RFpacket RX program for CC1310 as a starting point. I could able to receive the packet from CC1101 and get the data. Now I want to send the acknowledgement from CC1310.

How to change the RX mode to TX mode in RF packet RX program  for CC1310?

Please suggest the way.

Regards,

Ankur

  • Ankur,
    After you receive a packet you can add logic to run a Tx command. Please refer to the RF packet TX example. You can also create a new TX task by merging it from TX example. You can then trigger TX task (using semaphore post) in the RX callback function. Also please note that the RF packet RX example is setup to run repeatedly in RX mode. You will have to change it not repeat by modifying as below.
    RF_cmdPropRx.pktConf.bRepeatOk = 1; // Change from 1 to 0
    RF_cmdPropRx.pktConf.bRepeatNok = 1; // Change from 1 to 0
    Regards,
    PS
  • Hi Prashanth,

    As suggested I did the changes. Below is my code:

    My application is :

    To receive a packet from CC1101 and send the acknowledgement.

    I am using different LEDs on Smart RF board to check the entry in different stages.

    Led 3 which is in txTask glows(see the code below) but the last LED 4 does not. It does not enter into the error loop for the TX.

    Also if I put 

    RF_cmdPropRx.pktConf.bRepeatOk = 0;
    RF_cmdPropRx.pktConf.bRepeatNok = 0;

    None of LED glows which means it does not enter in the Rx callback. 

    Please suggest some way.

    /* Modify CMD_PROP_RX command for application needs */
    RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 0; /* Discard ignored packets from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */

    RF_cmdPropRx.pktConf.bRepeatOk = 1;
    RF_cmdPropRx.pktConf.bRepeatNok = 1;


    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);

    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    // PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
    /* Enter RX mode and stay forever in RX */
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);


    while(1);
    }

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    if (e & RF_EventRxEntryDone)
    {
    /* Toggle pin to indicate RX */

    PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
    /* Get current unhandled data entry */
    currentDataEntry = RFQueue_getDataEntry();

    /* Handle the packet data, located at &currentDataEntry->data:
    * - Length is the first byte with the current configuration
    * - Data starts from the second byte */
    packetLength = *(uint8_t*)(&currentDataEntry->data);
    packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);

    /* Copy the payload + the status byte to the packet variable */
    memcpy(packet, packetDataPointer, (packetLength + 1));

    if(packet[0] == 0x32)
    {
    PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));
    // num = 1;

    // RF_cmdPropRx.pktConf.bRepeatOk = 0;
    // RF_cmdPropRx.pktConf.bRepeatNok = 0;
    RF_close(h);
    TxTask_init(ledPinHandle);
    }

    RFQueue_nextEntry();
    }
    }

    /*
    * ======== main ========
    */
    int main(void)
    {
    /* Call board init functions. */
    Board_initGeneral();

    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if(!ledPinHandle)
    {
    System_abort("Error initializing board LED pins\n");
    }

    /* Initialize task */
    RxTask_init(ledPinHandle);

    /* Start BIOS */
    BIOS_start();

    return (0);
    }

    static void txTaskFunction(UArg arg0, UArg arg1)
    {
    uint32_t time;
    RF_Params rfParams;
    RF_Params_init(&rfParams);

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = packet1;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdPropTx.startTrigger.pastTrig = 1;
    RF_cmdPropTx.startTime = 0;

    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);

    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);

    /* Get current time */
    time = RF_getCurrentTime();

    uint8_t i;
    for (i=0; i<3; i++)
    {
    // while(1)
    // {
    /* Create packet with incrementing sequence number and random payload */
    // packet[0] = (uint8_t)(seqNumber >> 8);
    // packet[1] = (uint8_t)(seqNumber++);
    packet1[0] = 0x99;
    packet1[1] = 0xAA;
    //packet[2] = 0xAA;
    // uint8_t i;
    // for (i = 2; i < PAYLOAD_LENGTH; i++)
    // {
    // packet[i] = rand();
    // }
    PIN_setOutputValue(pinHandle, Board_LED3,!PIN_getOutputValue(Board_LED3));
    /* Set absolute TX time to utilize automatic power management */
    time += PACKET_INTERVAL;
    RF_cmdPropTx.startTime = time;


    /* Send packet */

    RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);

    if (!(result & RF_EventLastCmdDone))
    {
    PIN_setOutputValue(pinHandle, Board_LED4,!PIN_getOutputValue(Board_LED4));
    /* Error */
    while(1);
    }

    }
    // PIN_setOutputValue(pinHandle, Board_LED4,!PIN_getOutputValue(Board_LED4));


    RxTask_init(ledPinHandle);
    // PIN_setOutputValue(pinHandle, Board_LED4,!PIN_getOutputValue(Board_LED4));
    RF_close(rfHandle);
    //}
    }

    Regards,

    Ankur

  • Ankur, 

    Sorry for the delay in replying. I was able to modify the code to merge TX and RX tasks from rfPacketRx and rfPacketTx examples. Also added two semaphores to manage the task execution. Please see the attached source file. Essentially, the device enters Rx and once the packet is received it will post Tx task. Once the Tx task is complete it will post the Rx task. I tested this code and it now does a Tx as soon as an Rx packet is received. It does this for every packet received.

    Regards,

    Prashanth

    4857.rfPacketRx.c
    /*
     * Copyright (c) 2015, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /***** Includes *****/
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <driverlib/rf_prop_mailbox.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    
    #include <stdlib.h>
    
    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    PIN_Config pinTable[] =
    {
        Board_LED4 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    
    /***** Defines *****/
    #define RX_TASK_STACK_SIZE 1024
    #define RX_TASK_PRIORITY   2
    
    /* TX Configuration */
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH             30 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:
                                       * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
                                       * Max 30 payload bytes
                                       * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */
    
    
    /***** Defines *****/
    #define TX_TASK_STACK_SIZE 1024
    #define TX_TASK_PRIORITY   3
    
    /* TX Configuration */
    #define PAYLOAD_LENGTH      30
    #define PACKET_INTERVAL     (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */
    
    
    /***** Prototypes *****/
    static void txTaskFunction(UArg arg0, UArg arg1);
    static void rxTaskFunction(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    /***** Variable declarations *****/
    static Task_Params rxTaskParams;
    Task_Struct rxTask;    /* not static so you can see in ROV */
    static uint8_t rxTaskStack[RX_TASK_STACK_SIZE];
    static Task_Params txTaskParams;
    Task_Struct txTask;    /* not static so you can see in ROV */
    static uint8_t txTaskStack[TX_TASK_STACK_SIZE];
    
    Semaphore_Struct semTxStruct;
    Semaphore_Handle semTxHandle;
    
    Semaphore_Struct semRxStruct;
    Semaphore_Handle semRxHandle;
    
    
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    #endif
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;
    uint32_t time;
    static uint8_t txPacket[PAYLOAD_LENGTH];
    static uint16_t seqNumber;
    
    static PIN_Handle pinHandle;
    
    static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
    
    
    /***** Function definitions *****/
    void RxTask_init(PIN_Handle ledPinHandle) {
        pinHandle = ledPinHandle;
    
        Task_Params_init(&rxTaskParams);
        rxTaskParams.stackSize = RX_TASK_STACK_SIZE;
        rxTaskParams.priority = RX_TASK_PRIORITY;
        rxTaskParams.stack = &rxTaskStack;
        rxTaskParams.arg0 = (UInt)1000000;
    
        Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL);
    }
    
    static void rxTaskFunction(UArg arg0, UArg arg1)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;  /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;   /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.pktConf.bRepeatOk = 0;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
    
        if (!rfHandle) {
        	/* Request access to the radio */
        	rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        	/* Set the frequency */
        	RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        }
    
        while (1) {
            /* Enter RX mode and stay forever in RX */
            RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
            Semaphore_pend(semRxHandle, BIOS_WAIT_FOREVER);
        }
    
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
            /* Toggle pin to indicate RX */
            PIN_setOutputValue(pinHandle, Board_LED3,!PIN_getOutputValue(Board_LED3));
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet, packetDataPointer, (packetLength + 1));
    
            Semaphore_post(semTxHandle);
    
            RFQueue_nextEntry();
        }
    }
    
    #if 1
    /***** Function definitions *****/
    void TxTask_init(PIN_Handle inPinHandle)
    {
        pinHandle = inPinHandle;
    
        Task_Params_init(&txTaskParams);
        txTaskParams.stackSize = TX_TASK_STACK_SIZE;
        txTaskParams.priority = TX_TASK_PRIORITY;
        txTaskParams.stack = &txTaskStack;
        txTaskParams.arg0 = (UInt)1000000;
    
        Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);
    }
    
    
    static void txTaskFunction(UArg arg0, UArg arg1)
    {
        uint32_t time;
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
        RF_cmdPropTx.pPkt = txPacket;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropTx.startTime = 0;
    
        if (!rfHandle) {
        	/* Request access to the radio */
        	rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        	/* Set the frequency */
        	RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        }
    
        /* Get current time */
        time = RF_getCurrentTime();
        while(1)
        {
            Semaphore_pend(semTxHandle, BIOS_WAIT_FOREVER);
    
            /* Create packet with incrementing sequence number and random payload */
        	txPacket[0] = (uint8_t)(seqNumber >> 8);
        	txPacket[1] = (uint8_t)(seqNumber++);
            uint8_t i;
            for (i = 2; i < PAYLOAD_LENGTH; i++)
            {
            	txPacket[i] = rand();
            }
    
            /* Set absolute TX time to utilize automatic power management */
            time += PACKET_INTERVAL;
            RF_cmdPropTx.startTime = time;
    
            /* Send packet */
            RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
            if (!(result & RF_EventLastCmdDone))
            {
                /* Error */
                while(1);
            }
    
            PIN_setOutputValue(pinHandle, Board_LED4,!PIN_getOutputValue(Board_LED4));
            Semaphore_post(semRxHandle);
    
        }
    }
    #endif
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        Semaphore_Params semParams;
    
        /* Call board init functions. */
        Board_initGeneral();
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if(!ledPinHandle)
        {
            System_abort("Error initializing board LED pins\n");
        }
    
        /* Construct a Semaphore object to be used as a resource lock, inital count 0 */
        Semaphore_Params_init(&semParams);
        Semaphore_construct(&semTxStruct, 0, &semParams);
        Semaphore_construct(&semRxStruct, 0, &semParams);
    
    
        /* Obtain instance handle */
        semTxHandle = Semaphore_handle(&semTxStruct);
        semRxHandle = Semaphore_handle(&semRxStruct);
    
        /* Initialize task */
        RxTask_init(ledPinHandle);
    
        /* Initialize task */
        TxTask_init(ledPinHandle);
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    /***** Includes *****/#include <stdlib.h>#include <xdc/std.h>#include <xdc/cfg/global.h>#include <xdc/runtime/System.h>
    #include <ti/sysbios/BIOS.h>#include <ti/sysbios/knl/Task.h>
    /* Drivers */#include <ti/drivers/rf/RF.h>#include <ti/drivers/PIN.h>#include <driverlib/rf_prop_mailbox.h>
    /* Board Header files */#include "Board.h"
    #include "RFQueue.h"#include "smartrf_settings/smartrf_settings.h"
    #include <stdlib.h>
    /* Pin driver handle */static PIN_Handle ledPinHandle;static PIN_State ledPinState;
    /* * Application LED pin configuration table: *   - All LEDs board LEDs are off. */PIN_Config pinTable[] ={    Board_LED4 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,    Board_LED3 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,    PIN_TERMINATE};

    /***** Defines *****/#define RX_TASK_STACK_SIZE 1024#define RX_TASK_PRIORITY   2
    /* TX Configuration */#define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */#define MAX_LENGTH             30 /* Max length byte the radio will accept */#define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */#define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:                                   * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)                                   * Max 30 payload bytes                                   * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */

    /***** Defines *****/#define TX_TASK_STACK_SIZE 1024#define TX_TASK_PRIORITY   3
    /* TX Configuration */#define PAYLOAD_LENGTH      30#define PACKET_INTERVAL     (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */

    /***** Prototypes *****/static void txTaskFunction(UArg arg0, UArg arg1);static void rxTaskFunction(UArg arg0, UArg arg1);static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    /***** Variable declarations *****/static Task_Params rxTaskParams;Task_Struct rxTask;    /* not static so you can see in ROV */static uint8_t rxTaskStack[RX_TASK_STACK_SIZE];static Task_Params txTaskParams;Task_Struct txTask;    /* not static so you can see in ROV */static uint8_t txTaskStack[TX_TASK_STACK_SIZE];
    Semaphore_Struct semTxStruct;Semaphore_Handle semTxHandle;
    Semaphore_Struct semRxStruct;Semaphore_Handle semRxHandle;

    static RF_Object rfObject;static RF_Handle rfHandle;

    #if defined(__TI_COMPILER_VERSION__)#pragma DATA_ALIGN (rxDataEntryBuffer, 4);#elif defined(__IAR_SYSTEMS_ICC__)#pragma data_alignment = 4#endifstatic uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,                                                                 MAX_LENGTH,                                                                 NUM_APPENDED_BYTES)];
    /* Receive dataQueue for RF Core to fill in data */static dataQueue_t dataQueue;static rfc_dataEntryGeneral_t* currentDataEntry;static uint8_t packetLength;static uint8_t* packetDataPointer;uint32_t time;static uint8_t txPacket[PAYLOAD_LENGTH];static uint16_t seqNumber;
    static PIN_Handle pinHandle;
    static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */

    /***** Function definitions *****/void RxTask_init(PIN_Handle ledPinHandle) {    pinHandle = ledPinHandle;
        Task_Params_init(&rxTaskParams);    rxTaskParams.stackSize = RX_TASK_STACK_SIZE;    rxTaskParams.priority = RX_TASK_PRIORITY;    rxTaskParams.stack = &rxTaskStack;    rxTaskParams.arg0 = (UInt)1000000;
        Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL);}
    static void rxTaskFunction(UArg arg0, UArg arg1){    RF_Params rfParams;    RF_Params_init(&rfParams);
        if( RFQueue_defineQueue(&dataQueue,                            rxDataEntryBuffer,                            sizeof(rxDataEntryBuffer),                            NUM_DATA_ENTRIES,                            MAX_LENGTH + NUM_APPENDED_BYTES))    {        /* Failed to allocate space for all data entries */        while(1);    }
        /* Modify CMD_PROP_RX command for application needs */    RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;  /* Discard ignored packets from Rx queue */    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;   /* Discard packets with CRC error from Rx queue */    RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */    RF_cmdPropRx.pktConf.bRepeatOk = 0;    RF_cmdPropRx.pktConf.bRepeatNok = 0;
        if (!rfHandle) {    /* Request access to the radio */    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
        /* Set the frequency */    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);    }
        while (1) {        /* Enter RX mode and stay forever in RX */        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);        Semaphore_pend(semRxHandle, BIOS_WAIT_FOREVER);    }
    }
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e){    if (e & RF_EventRxEntryDone)    {        /* Toggle pin to indicate RX */        PIN_setOutputValue(pinHandle, Board_LED3,!PIN_getOutputValue(Board_LED3));
            /* Get current unhandled data entry */        currentDataEntry = RFQueue_getDataEntry();
            /* Handle the packet data, located at &currentDataEntry->data:         * - Length is the first byte with the current configuration         * - Data starts from the second byte */        packetLength      = *(uint8_t*)(&currentDataEntry->data);        packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
            /* Copy the payload + the status byte to the packet variable */        memcpy(packet, packetDataPointer, (packetLength + 1));
            Semaphore_post(semTxHandle);
            RFQueue_nextEntry();    }}
    /***** Function definitions *****/void TxTask_init(PIN_Handle inPinHandle){    pinHandle = inPinHandle;
        Task_Params_init(&txTaskParams);    txTaskParams.stackSize = TX_TASK_STACK_SIZE;    txTaskParams.priority = TX_TASK_PRIORITY;    txTaskParams.stack = &txTaskStack;    txTaskParams.arg0 = (UInt)1000000;
        Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);}

    static void txTaskFunction(UArg arg0, UArg arg1){    uint32_t time;    RF_Params rfParams;    RF_Params_init(&rfParams);
        RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;    RF_cmdPropTx.pPkt = txPacket;    RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;    RF_cmdPropTx.startTrigger.pastTrig = 1;    RF_cmdPropTx.startTime = 0;
        if (!rfHandle) {    /* Request access to the radio */    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
        /* Set the frequency */    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);    }
        /* Get current time */    time = RF_getCurrentTime();    while(1)    {        Semaphore_pend(semTxHandle, BIOS_WAIT_FOREVER);
            /* Create packet with incrementing sequence number and random payload */    txPacket[0] = (uint8_t)(seqNumber >> 8);    txPacket[1] = (uint8_t)(seqNumber++);        uint8_t i;        for (i = 2; i < PAYLOAD_LENGTH; i++)        {        txPacket[i] = rand();        }
            /* Set absolute TX time to utilize automatic power management */        time += PACKET_INTERVAL;        RF_cmdPropTx.startTime = time;
            /* Send packet */        RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);        if (!(result & RF_EventLastCmdDone))        {            /* Error */            while(1);        }
            PIN_setOutputValue(pinHandle, Board_LED4,!PIN_getOutputValue(Board_LED4));        Semaphore_post(semRxHandle);
        }}
    /* *  ======== main ======== */int main(void){    Semaphore_Params semParams;
        /* Call board init functions. */    Board_initGeneral();
        /* Open LED pins */    ledPinHandle = PIN_open(&ledPinState, pinTable);    if(!ledPinHandle)    {        System_abort("Error initializing board LED pins\n");    }
        /* Construct a Semaphore object to be used as a resource lock, inital count 0 */    Semaphore_Params_init(&semParams);    Semaphore_construct(&semTxStruct, 0, &semParams);    Semaphore_construct(&semRxStruct, 0, &semParams);

        /* Obtain instance handle */    semTxHandle = Semaphore_handle(&semTxStruct);    semRxHandle = Semaphore_handle(&semRxStruct);
        /* Initialize task */    RxTask_init(ledPinHandle);
        /* Initialize task */    TxTask_init(ledPinHandle);
        /* Start BIOS */    BIOS_start();
        return (0);}

  • Hi Prashanth,

    Thank you so much for this updated code.

    There are two issues I would like to mention to you.

    1) I am not able to get any RX data nor the TX if both(RX & TX) Semaphore_pend command is active in code. However, I could able to get the cycle of RX & TX working properly if I comment these Semaphore_pend command from the both the places.
    What could be the issue with these Semaphore_pend commands?

    2) As mentioned in 1, I could be get the cycle (Rx & Tx) function by commenting the semaphore_ pend command from both the places but code is starting with first Tx and then Rx but my application is first Rx and then Tx and cycle continues.
    How should I change this?

    Please advise.

    Regards,
    Ankur
  • Ankur, 

    You can modify the priorities of the Tx and the Rx tasks to have your Rx task execution first. The highest priority task will be executed first.

    If you want to get familar with the TI-RTOS you can refer to availble online training

    http://processors.wiki.ti.com/index.php/Introduction_to_the_TI-RTOS_Kernel_Workshop#Online_Training_Videos_Available

    Regards,

    Prashanth

  • Hi Prashanth,

    Thank u so much....:)

    Regards
    Ankur
  • Hi

    I have quite the same problem. I am using Wake on radio Rx as a startpoint and I would like to switch from Rx to Tx and Tx to Rx. I don't want to use RF_close() to close my Rx because I could lose datas in this case. So far, I am able to switch once or twice at most but I am using RF_close(). So how could I do?

    Regards

  • Hi,

    You can see the example how Prashanth had done the switching of RX & TX above by using semaphore_post in TX & RX Tasks . In such case you dont need the RF_close(), its just a switching between the two.
    Hope this helps.

    Regards,
    Ankur
  • Hi

    I tried with this example but it seems, it doesn't work for the wake on radio configuration. Maybe I have made a mistake somewhere.

    rfWakeOnRadioRx.c
    /*
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /***** Includes *****/
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    
    /* Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/pin/PINCC26XX.h>
    
    /* Display */
    #include <ti/mw/display/Display.h>
    
    /* Board Header files */
    #include "Board.h"
    
    #include <inc/hw_fcfg1.h>
    
    /* RF settings, defines and helper files */
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    #include "driverlib/rf_prop_mailbox.h"
    
    
    /***** Defines *****/
    /* Wake-on-Radio wakeups per second */
    #define WOR_WAKEUPS_PER_SECOND  2
    
    /* TX number of random payload bytes */
    #define PAYLOAD_LENGTH 30
    
    /* WOR Example configuration defines */
    #define WOR_PREAMBLE_TIME_RAT_TICKS(x) \
        ((uint32_t)(4000000*(1.0f/(x))))
    
    /* Wake-on-Radio mode. Can be:
     * - RSSI only
     * - PQT, preamble detection
     * - Both, first RSSI and then PQT if RSSI  */
    #define WOR_MODE CarrierSenseMode_RSSIandPQT
    
    /* Threshold for RSSI based Carrier Sense in dBm */
    #define WOR_RSSI_THRESHOLD      ((int8_t)(-111))
    
    /* Macro used to set actual wakeup interval */
    #define WOR_WAKE_UP_MARGIN_S 0.005f
    #define WOR_WAKE_UP_INTERVAL_RAT_TICKS(x) \
        ((uint32_t)(4000000*(1.0f/(x) - (WOR_WAKE_UP_MARGIN_S))))
    
    /// \brief macro to convert from ms to Radio Time Ticks
    #define EasyLink_ms_To_RadioTime(ms) (ms*(400000/1000))
    
    /* TI-RTOS Task configuration */
    #define RX_TASK_STACK_SIZE 1024
    #define RX_TASK_PRIORITY   2
    
    #define PACKET_INTERVAL     (uint32_t)(4000000*0.5f) /* Set packet interval to 500ms */
    
    /* TX Configuration */
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH             31 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     1  /* Length byte included in the stored packet */
    
    /***** Type declarations *****/
    /* General wake-on-radio RX statistics */
    struct WorStatistics {
      uint32_t doneIdle;
      uint32_t doneIdleTimeout;
      uint32_t doneRxTimeout;
      uint32_t doneOk;
    };
    
    /* Modes of carrier sense possible */
    enum CarrierSenseMode {
        CarrierSenseMode_RSSI,
        CarrierSenseMode_PQT,
        CarrierSenseMode_RSSIandPQT,
    };
    
    /***** Variable declarations *****/
    /* TX task objects and task stack */
    static Task_Params rxTaskParams;
    static Task_Struct rxTask;
    static uint8_t rxTaskStack[RX_TASK_STACK_SIZE];
    
    /* TX task objects and task stack */
    static Task_Params txTaskParams;
    Task_Struct txTask;    /* not static so you can see in ROV */
    static uint8_t txTaskStack[RX_TASK_STACK_SIZE];
    
    /* TX packet payload (length +1 to fit length byte) and sequence number */
    static uint8_t packet[PAYLOAD_LENGTH +1];
    static uint16_t seqNumber;
    
    /* RF driver object and handle */
    static RF_Object rfObject;
    static RF_Object rfObject1;
    static RF_Handle rfHandle;
    static RF_Handle rfHandle1;
    
    /* Pin driver object and handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;
    static PIN_Handle buttonPinHandle;
    static PIN_State buttonPinState;
    
    /* LCD */
    Display_Handle uartDisplayHandle;
    Display_Handle lcdDisplayHandle;
    
    /* TX Semaphore */
    static Semaphore_Struct txSemaphore;
    static Semaphore_Handle txSemaphoreHandle;
    /* RX Semaphore */
    static Semaphore_Struct rxSemaphore;
    static Semaphore_Handle rxSemaphoreHandle;
    
    /* Advanced TX command for sending long preamble */
    static rfc_CMD_PROP_TX_ADV_t RF_cmdPropTxAdv;
    
    /* General wake-on-radio sniff status statistics and statistics from the RF Core about received packets */
    static volatile struct WorStatistics worStatistics;
    static rfc_propRxOutput_t rxStatistics;
    
    /*
     * Application LED pin configuration table:
     *   - All LEDs board LEDs are off.
     */
    static PIN_Config pinTable[] =
    {
        Board_LED0 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        PIN_TERMINATE
    };
    
    /*
     * Application button pin configuration table:
     *   - Buttons interrupts are configured to trigger on falling edge.
     */
    PIN_Config buttonPinTable[] = {
        Board_BUTTON0 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    	Board_BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
    	Board_BUTTON2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_NEGEDGE,
        PIN_TERMINATE
    };
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    #endif
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    
    /* RX Data Queue and Data Entry pointer to read out received packets */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    
    /* Received packet's length and pointer to the payload */
    static uint8_t packetLength;
    static uint8_t packetNum;
    static uint8_t packetAddress[8];
    static uint8_t* packetDataPointer;
    /* Sniff command for doing combined Carrier Sense and RX*/
    static rfc_CMD_PROP_RX_SNIFF_t RF_cmdPropRxSniff;
    
    PIN_Id pinId;
    Display_Params params;
    //RF_Params rfParams;
    //RF_Params rfParams1;
    int8_t rssi;
    //uint32_t time;
    uint64_t Address;
    //static bool rfParamsConfigured = 0;
    //static bool rfParamsConfigured1 = 0;
    
    /***** Prototypes *****/
    static void rxTaskFunction(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    static void initializeSniffCmdFromRxCmd(rfc_CMD_PROP_RX_SNIFF_t* rxSniffCmd, rfc_CMD_PROP_RX_t* rxCmd);
    static void configureSniffCmd(rfc_CMD_PROP_RX_SNIFF_t* rxSniffCmd, enum CarrierSenseMode mode, uint32_t datarate, uint8_t wakeupPerSecond);
    static uint32_t calculateSymbolRate(uint8_t prescaler, uint32_t rateWord);
    static void txTaskFunction(UArg arg0, UArg arg1);
    static void initializeTxAdvCmdFromTxCmd(rfc_CMD_PROP_TX_ADV_t* RF_cmdPropTxAdv, rfc_CMD_PROP_TX_t* RF_cmdPropTx);
    void buttonCallbackFunction(PIN_Handle handle, PIN_Id pinId);
    static void initLcd();
    
    /***** Function definitions *****/
    /* RX task initialization function. Runs once from main() */
    void rxTaskInit()
    {
        /* Initialize RX semaphore */
    	Task_Params_init(&rxTaskParams);
    	rxTaskParams.stackSize = RX_TASK_STACK_SIZE;
    	rxTaskParams.priority = RX_TASK_PRIORITY;
    	rxTaskParams.stack = &rxTaskStack;
    	rxTaskParams.arg0 = (UInt)1000000;
    
        Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL);
    }
    
    /* RX task function. Executed in Task context by TI-RTOS when the scheduler starts. */
    static void rxTaskFunction(UArg arg0, UArg arg1)
    {
    	if(!lcdDisplayHandle){
        	initLcd();
        }
    
    	RF_Params rfParams;
    	RF_Params_init(&rfParams);
    
    	/* Route out LNA active pin to LED1 */
    	PINCC26XX_setMux(ledPinHandle, Board_LED0, PINCC26XX_MUX_RFC_GPO0);
    
    	/*
    	RF_cmdPropRx.pktConf.bRepeatOk = 0;
    	RF_cmdPropRx.pktConf.bRepeatNok = 0;
    
    	Print initial display content on both UART and any LCD present
    	Display_print0(uartDisplayHandle, 0, 0, "Wake-on-Radio TX");
    	Display_print0(uartDisplayHandle, 1, 6, "TX mode");
    	Display_print0(uartDisplayHandle, 2, 9, "|");
    	Display_print0(uartDisplayHandle, 3, 1, "None __  __ Send TX");
    	Display_print0(uartDisplayHandle, 5, 9, "|");
    	Display_print0(uartDisplayHandle, 6, 6, "RX mode");
    	Display_print0(lcdDisplayHandle, 0, 0, "Wake-on-Radio TX / RX");
    	Display_print0(lcdDisplayHandle, 1, 6, "TX mode");
    	Display_print0(lcdDisplayHandle, 2, 9, "|");
    	Display_print0(lcdDisplayHandle, 3, 1, "None __  __ Send TX");
    	Display_print0(lcdDisplayHandle, 5, 9, "|");
    	Display_print0(lcdDisplayHandle, 6, 6, "RX mode");*/
    
        /* Print initial display content on both UART and any LCD present*/
        Display_print0(uartDisplayHandle, 0, 0, "Wake-on-Radio RX");
        Display_print1(uartDisplayHandle, 1, 0, "Pkts received: %u", packetNum);
        Display_print0(lcdDisplayHandle, 0, 0, "Wake-on-Radio RX");
        Display_print1(lcdDisplayHandle, 1, 0, "Pkts received: %u", packetNum);
        Display_print1(uartDisplayHandle, 2, 0, "RSSI: %d", rssi);
    	Display_print1(lcdDisplayHandle, 2, 0, "RSSI: %d", rssi);
    	Display_print0(uartDisplayHandle, 3, 0, "@ MAC: ");
    	Display_print0(lcdDisplayHandle, 3, 0, "@ MAC: ");
    
        /*if(!rfHandle1)
        {
        	RF_close(rfHandle1);
    		RF_close(rfHandle);
    		RF_yield(rfHandle1);
        }*/
    
    	/* Create queue and data entries */
    	if (RFQueue_defineQueue(&dataQueue,
    							rxDataEntryBuffer,
    							sizeof(rxDataEntryBuffer),
    							NUM_DATA_ENTRIES,
    							MAX_LENGTH + NUM_APPENDED_BYTES))
    	{
    		/* Failed to allocate space for all data entries */
    		while(1);
    	}
    
    	/* Copy all RX options from the SmartRF Studio exported RX command to the RX Sniff command */
    	initializeSniffCmdFromRxCmd(&RF_cmdPropRxSniff, &RF_cmdPropRx);
    
    	/* Configure RX part of RX_SNIFF command */
    	RF_cmdPropRxSniff.pQueue    = &dataQueue;
    	RF_cmdPropRxSniff.pOutput   = (uint8_t*)&rxStatistics;
    	RF_cmdPropRxSniff.maxPktLen = MAX_LENGTH;
    
    	/* Discard ignored packets and CRC errors from Rx queue */
    	RF_cmdPropRxSniff.rxConf.bAutoFlushIgnored = 1;
    	RF_cmdPropRxSniff.rxConf.bAutoFlushCrcErr  = 1;
    
    	RF_cmdPropRxSniff.pktConf.bRepeatOk = 0;
    	RF_cmdPropRxSniff.pktConf.bRepeatNok = 0;
    
    	/* Calculate datarate from prescaler and rate word */
    	uint32_t datarate = calculateSymbolRate(RF_cmdPropRadioDivSetup.symbolRate.preScale,
    										  RF_cmdPropRadioDivSetup.symbolRate.rateWord);
    
    	/* Configure Sniff-mode part of the RX_SNIFF command */
    	configureSniffCmd(&RF_cmdPropRxSniff, WOR_MODE, datarate, WOR_WAKEUPS_PER_SECOND);
    
        if (!rfHandle) {
    		/* Request access to the radio */
    		rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
    		/* Set frequency */
    		//RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, &callback, 0);
    		RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        }
        /* Save the current radio time */
    	RF_cmdPropRxSniff.startTime = RF_getCurrentTime();
    
        /* Enter main loop */
        while(1)
        {
        	/* Set next wakeup time in the future */
            RF_cmdPropRxSniff.startTime += WOR_WAKE_UP_INTERVAL_RAT_TICKS(WOR_WAKEUPS_PER_SECOND);
    
            /* Schedule RX */
            RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRxSniff, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
            /* Log RX_SNIFF status */
            switch(RF_cmdPropRxSniff.status) {
                case PROP_DONE_IDLE:
                    /* Idle based on RSSI */
                    worStatistics.doneIdle++;
                    break;
                case PROP_DONE_IDLETIMEOUT:
                    /* Idle based on PQT */
                    worStatistics.doneIdleTimeout++;
                    break;
                case PROP_DONE_RXTIMEOUT:
                    /* Got valid preamble on the air, but did not find sync word */
                    worStatistics.doneRxTimeout++;
                    break;
                case PROP_DONE_OK:
                    /* Received packet */
                    worStatistics.doneOk++;
                    rssi= RF_getRssi(rfHandle);
                    /* Update display */
                    Display_print1(uartDisplayHandle, 0, 0, "Pkts received: %u", packetNum+1);
                    Display_print1(lcdDisplayHandle, 1, 0, "Pkts received: %u", packetNum+1);
                    Display_print1(uartDisplayHandle, 0, 0, "RSSI: %d", rssi);
    				Display_print1(lcdDisplayHandle, 2, 0, "RSSI: %d", rssi);
    				Display_print4(uartDisplayHandle, 3, 0, "@ : %u.%u.%u.%u", packetAddress[0], packetAddress[1], packetAddress[2], packetAddress[3]);
    				Display_print4(uartDisplayHandle, 4, 0, "@ : %u.%u.%u.%u", packetAddress[4], packetAddress[5], packetAddress[6], packetAddress[7]);
    				Display_print4(lcdDisplayHandle, 3, 0, "@ : %u.%u.%u.%u", packetAddress[0], packetAddress[1], packetAddress[2], packetAddress[3]);
    				Display_print4(lcdDisplayHandle, 4, 0, "@ : %u.%u.%u.%u", packetAddress[4], packetAddress[5], packetAddress[6], packetAddress[7]);
                    break;
                default:
                    /* Unhandled status */
                    break;
            };
            Semaphore_pend(rxSemaphoreHandle, BIOS_WAIT_FOREVER);
        }
    }
    
    /* Calculates datarate from prescaler and rate word */
    static uint32_t calculateSymbolRate(uint8_t prescaler, uint32_t rateWord)
    {
        /* Calculate datarate according to TRM Section 23.7.5.2:
         * f_baudrate = (R * f_ref)/(p * 2^20)
         *   - R = rateWord
         *   - f_ref = 24Mhz
         *   - p = prescaler */
        uint64_t numerator = rateWord*24000000ULL;
        uint64_t denominator = prescaler*1048576ULL;
        uint32_t result = (uint32_t)(numerator/denominator);
        return result;
    }
    
    /* Copies all RX options from the SmartRF Studio exported RX command to the RX Sniff command */
    static void initializeSniffCmdFromRxCmd(rfc_CMD_PROP_RX_SNIFF_t* rxSniffCmd, rfc_CMD_PROP_RX_t* rxCmd)
    {
    
        /* Copy RX configuration from RX command */
        memcpy(rxSniffCmd, rxCmd, sizeof(rfc_CMD_PROP_RX_t));
    
        /* Change to RX_SNIFF command from RX command */
        rxSniffCmd->commandNo = CMD_PROP_RX_SNIFF;
    }
    
    /* Configures Sniff-mode part of the RX_SNIFF command based on mode, datarate and wakeup interval */
    static void configureSniffCmd(rfc_CMD_PROP_RX_SNIFF_t* rxSniffCmd, enum CarrierSenseMode mode, uint32_t datarate, uint8_t wakeupPerSecond)
    {
        /* Enable or disable RSSI */
        if ((mode == CarrierSenseMode_RSSI) || (mode == CarrierSenseMode_RSSIandPQT)) {
            rxSniffCmd->csConf.bEnaRssi        = 1;
        } else {
            rxSniffCmd->csConf.bEnaRssi        = 0;
        }
    
        /* Enable or disable PQT */
        if ((mode == CarrierSenseMode_PQT) || (mode == CarrierSenseMode_RSSIandPQT)) {
            rxSniffCmd->csConf.bEnaCorr        = 1;
            rxSniffCmd->csEndTrigger.triggerType  = TRIG_REL_START;
        } else {
            rxSniffCmd->csConf.bEnaCorr        = 0;
            rxSniffCmd->csEndTrigger.triggerType  = TRIG_NEVER;
        }
    
        /* General Carrier Sense configuration */
        rxSniffCmd->csConf.operation       = 1; /* Report Idle if RSSI reports Idle to quickly exit if not above
                                                     RSSI threshold */
        rxSniffCmd->csConf.busyOp          = 0; /* End carrier sense on channel Busy (the receiver will continue when
                                                     carrier sense ends, but it will then not end if channel goes Idle) */
        rxSniffCmd->csConf.idleOp          = 1; /* End on channel Idle */
        rxSniffCmd->csConf.timeoutRes      = 1; /* If the channel is invalid, it will return PROP_DONE_IDLE_TIMEOUT */
    
        /* RSSI configuration */
        rxSniffCmd->numRssiIdle            = 1; /* One idle RSSI samples signals that the channel is idle */
        rxSniffCmd->numRssiBusy            = 1; /* One busy RSSI samples signals that the channel is busy */
        rxSniffCmd->rssiThr    = (int8_t)WOR_RSSI_THRESHOLD; /* Set the RSSI threshold in dBm */
    
        /* PQT configuration */
        rxSniffCmd->corrConfig.numCorrBusy = 1;   /* One busy PQT samples signals that the channel is busy */
        rxSniffCmd->corrConfig.numCorrInv  = 1;   /* One busy PQT samples signals that the channel is busy */
    
        /* Calculate basic timing parameters */
        uint32_t symbolLengthUs  = 1000000UL/datarate;
        uint32_t preambleSymbols = (1000000UL/wakeupPerSecond)/symbolLengthUs;
        uint8_t syncWordSymbols  = RF_cmdPropRadioDivSetup.formatConf.nSwBits;
    
        /* Calculate sniff mode parameters */
        #define US_TO_RAT_TICKS 4
        #define CORR_PERIOD_SYM_MARGIN 16
        #define RX_END_TIME_SYM_MARGIN 8
        #define CS_END_TIME_MIN_TIME_SYM 30
        #define CS_END_TIME_MIN_TIME_STATIC_US 150
    
        /* Represents the time in which we need to receive corrConfig.numCorr* correlation peaks to detect preamble.
         * When continously checking the preamble quality, this period has to be wide enough to also contain the sync
         * word, with a margin. If it is not, then there is a chance the SNIFF command will abort while receiving the
         * sync word, as it no longer detects a preamble. */
        uint32_t correlationPeriodUs = (syncWordSymbols + CORR_PERIOD_SYM_MARGIN)*symbolLengthUs;
    
        /* Represents the time where we will force a check if preamble is present (only done once).
         * The main idea is that his should be shorter than "correlationPeriodUs" so that if we get RSSI valid, but
         * there is not a valid preamble on the air, we will leave RX as quickly as possible. */
        uint32_t csEndTimeUs = (CS_END_TIME_MIN_TIME_SYM*symbolLengthUs + CS_END_TIME_MIN_TIME_STATIC_US);
    
        /* Represents the maximum time from the startTrigger to when we expect a sync word to be received. */
        uint32_t rxEndTimeUs = (preambleSymbols + syncWordSymbols + RX_END_TIME_SYM_MARGIN)*symbolLengthUs;
    
        /* Set sniff mode timing configuration in sniff command in RAT ticks */
        rxSniffCmd->corrPeriod = (uint16_t)(correlationPeriodUs * US_TO_RAT_TICKS);
        rxSniffCmd->csEndTime  = (uint32_t)(csEndTimeUs * US_TO_RAT_TICKS);
        rxSniffCmd->endTime    = (uint32_t)(rxEndTimeUs * US_TO_RAT_TICKS);
    
        /* Set correct trigger types */
        rxSniffCmd->endTrigger.triggerType   = TRIG_REL_START;
        rxSniffCmd->startTrigger.triggerType = TRIG_ABSTIME;
        rxSniffCmd->startTrigger.pastTrig    = 1;
    }
    
    /* Called for every received packet and command done */
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        /* If we've received a new packet and it's available to read out */
        if (e & RF_EventRxEntryDone)
        {
            do
            {
                /* Toggle LED on RX */
                PIN_setOutputValue(ledPinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1));
    
                /* Get current unhandled data entry */
                currentDataEntry = RFQueue_getDataEntry();
    
                /* Handle the packet data, located at &currentDataEntry->data:
                 * - Length is the first byte with the current configuration
                 * - Data starts from the second byte */
                packetLength      = *(uint8_t*)(&currentDataEntry->data);
                packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
                packetNum		  = *(uint8_t*)(&currentDataEntry->data+2);
                packetAddress[0]	  = *(uint8_t*)(&currentDataEntry->data+3);
                packetAddress[1]	  = *(uint8_t*)(&currentDataEntry->data+4);
                packetAddress[2]	  = *(uint8_t*)(&currentDataEntry->data+5);
                packetAddress[3]	  = *(uint8_t*)(&currentDataEntry->data+6);
                packetAddress[4]	  = *(uint8_t*)(&currentDataEntry->data+7);
                packetAddress[5]	  = *(uint8_t*)(&currentDataEntry->data+8);
                packetAddress[6]	  = *(uint8_t*)(&currentDataEntry->data+9);
                packetAddress[7]	  = *(uint8_t*)(&currentDataEntry->data+10);
    
                memcpy(packet, packetDataPointer, (packetLength + 1));
    
                /* This code block is added to avoid a compiler warning.
                * Normally, an application will reference these variables for
                * useful data. */
                volatile uint8_t dummy;
                dummy = packetLength;
                dummy = packetNum;
                dummy = packetAddress[0];
                dummy = packetDataPointer[0];
    			//Semaphore_post(txSemaphoreHandle);
    		//	RFQueue_nextEntry();
            } while(RFQueue_nextEntry() == DATA_ENTRY_FINISHED);
    
        }
    }
    
    /* TX task initialization function. Runs once from main() */
    void txTaskInit()
    {
        /* Initialize TX semaphore
        Semaphore_construct(&txSemaphore, 0, NULL);
        txSemaphoreHandle = Semaphore_handle(&txSemaphore);*/
    
        /* Initialize and create TX task */
        Task_Params_init(&txTaskParams);
        txTaskParams.stackSize = RX_TASK_STACK_SIZE;
        txTaskParams.priority = RX_TASK_PRIORITY;
        txTaskParams.stack = &txTaskStack;
        txTaskParams.arg0 = (UInt)1000000;
        Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);
    }
    
    /* Pin interrupt Callback function board buttons configured in the pinTable.*/
    void buttonCallbackFunction(PIN_Handle handle, PIN_Id pinId) {
    
        /* Simple debounce logic, only toggle if the button is still pushed (low)*/
        CPUdelay((uint32_t)((48000000/3)*0.050f));
        if (!PIN_getInputValue(pinId)) {
            /* Post TX semaphore to TX task*/
            switch (pinId) {
    			case Board_BUTTON0:
    				/*RF_close(rfHandle);
    				RF_close(rfHandle1);
    				if(rfHandle!=0){
    					RF_yield(rfHandle);
    				}*/
    				txTaskInit();
    				Semaphore_post(txSemaphoreHandle);
    				break;
    			case Board_BUTTON1:
    				/*RF_close(rfHandle1);
    				RF_close(rfHandle);
    				if(rfHandle1!=0){
    					RF_yield(rfHandle1);
    				}*/
    				rxTaskInit();
    				Semaphore_post(rxSemaphoreHandle);
    				break;
    			case Board_BUTTON2:
    				Semaphore_post(txSemaphoreHandle);
    				break;
    			default:
    				/* Do nothing*/
    				break;
            }
        }
    }
    
    /* TX task function. Executed in Task context by TI-RTOS when the scheduler starts. */
    static void txTaskFunction(UArg arg0, UArg arg1)
    {
    	uint32_t time;
    	if(!lcdDisplayHandle){
        	initLcd();
        }
    
    	/* Print initial display content on both UART and any LCD present */
        Display_print0(uartDisplayHandle, 0, 0, "Wake-on-Radio TX");
        Display_print1(uartDisplayHandle, 0, 0, "Pkts sent: %u", seqNumber);
        Display_print0(lcdDisplayHandle, 0, 0, "Wake-on-Radio TX");
        Display_print1(lcdDisplayHandle, 1, 0, "Pkts sent: %u", seqNumber);
    
    	/* Setup callback for button pins
    	if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFunction) != 0) {
    		System_abort("Error registering button callback function");
    	}*/
    
    	RF_Params rfParams1;
    	RF_Params_init(&rfParams1);
    
        /* Initialize TX_ADV command from TX command */
        initializeTxAdvCmdFromTxCmd(&RF_cmdPropTxAdv, &RF_cmdPropTx);
    
        /* Set application specific fields
        RF_cmdPropTxAdv.preTrigger.triggerType = TRIG_REL_START;*/
        RF_cmdPropTxAdv.pktLen = PAYLOAD_LENGTH +1; /* +1 for length byte */
    	RF_cmdPropTxAdv.pPkt = packet;
    	//RF_cmdPropTxAdv.preTrigger.triggerType = TRIG_REL_START;
    	RF_cmdPropTxAdv.startTrigger.triggerType = TRIG_ABSTIME;
    	//RF_cmdPropTxAdv.startTrigger.pastTrig = 1;
    	RF_cmdPropTxAdv.startTime = 0;
    	RF_cmdPropTxAdv.preTime = WOR_PREAMBLE_TIME_RAT_TICKS(WOR_WAKEUPS_PER_SECOND);
    
    //	RF_close(rfHandle1);
    	/* Request access to the radio */
    	if(!rfHandle1){
    		rfHandle1 = RF_open(&rfObject1, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams1);
    
    		/* Set the frequency */
    		RF_runCmd(rfHandle1, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    	}
    	/* Get current time */
    	time = RF_getCurrentTime();
    
        /* Enter main TX loop */
        while(1)
        {
            /* Wait for a button press*/
            Semaphore_pend(txSemaphoreHandle, BIOS_WAIT_FOREVER);
    
            /* Create packet with incrementing sequence number and random payload */
            packet[0] = PAYLOAD_LENGTH;
            packet[1] = (uint8_t)(seqNumber >> 8);
            packet[2] = (uint8_t)(seqNumber++);
            Address = *((uint64_t *)(FCFG1_BASE + FCFG1_O_MAC_15_4_0)) & 0xFFFFFFFFFFFF;
            packet[3] = (uint8_t)(Address >> 56);
            packet[4] = (uint8_t)(Address >> 48);
            packet[5] = (uint8_t)(Address >> 40);
            packet[6] = (uint8_t)(Address >> 32);
            packet[7] = (uint8_t)(Address >> 24);
            packet[8] = (uint8_t)(Address >> 16);
            packet[9] = (uint8_t)(Address >> 8);
            packet[10] = (uint8_t)(Address);
            uint8_t i;
            for (i = 11; i < PAYLOAD_LENGTH +1; i++)
            {
                packet[i] = rand();
            }
    
            time += PACKET_INTERVAL;
            RF_cmdPropTxAdv.startTime = time;
            /* Send packet */
    		RF_runCmd(rfHandle1, (RF_Op*)&RF_cmdPropTxAdv, RF_PriorityNormal, NULL, 0);
    
            /* Update display */
            Display_print1(uartDisplayHandle, 0, 0, "Pkts sent: %u", seqNumber);
            Display_print1(lcdDisplayHandle, 1, 0, "Pkts sent: %u", seqNumber);
            /* Affichage @ MAC */
            Display_print4(uartDisplayHandle, 2, 0, "@ : %u.%u.%u.%u", packet[3],packet[4],packet[5],packet[6]);
            Display_print4(uartDisplayHandle, 3, 0, "@ : %u.%u.%u.%u", packet[7],packet[8],packet[9],packet[10]);
    		Display_print4(lcdDisplayHandle, 2, 0, "@ : %u.%u.%u.%u", packet[3],packet[4],packet[5],packet[6]);
    		Display_print4(lcdDisplayHandle, 3, 0, "@ : %u.%u.%u.%u", packet[7],packet[8],packet[9],packet[10]);
    
            /* Toggle LED */
            PIN_setOutputValue(ledPinHandle, Board_LED1, !PIN_getOutputValue(Board_LED1));
            Semaphore_post(rxSemaphoreHandle);
        }
    }
    
    /* Copy the basic RX configuration from CMD_PROP_RX to CMD_PROP_RX_SNIFF command. */
    static void initializeTxAdvCmdFromTxCmd(rfc_CMD_PROP_TX_ADV_t* RF_cmdPropTxAdv, rfc_CMD_PROP_TX_t* RF_cmdPropTx)
    {
        #define RADIO_OP_HEADER_SIZE 14
    
        /* Copy general radio operation header from TX commmand to TX_ADV */
        memcpy(RF_cmdPropTxAdv, RF_cmdPropTx, RADIO_OP_HEADER_SIZE);
    
        /* Set command to CMD_PROP_TX_ADV */
        RF_cmdPropTxAdv->commandNo = CMD_PROP_TX_ADV;
    
        /* Copy over relevant parameters */
        RF_cmdPropTxAdv->pktConf.bFsOff = RF_cmdPropTx->pktConf.bFsOff;
        RF_cmdPropTxAdv->pktConf.bUseCrc = RF_cmdPropTx->pktConf.bUseCrc;
        RF_cmdPropTxAdv->syncWord = RF_cmdPropTx->syncWord;
    }
    /* Initialisation LCD et Radio*/
     static void initLcd()
    {
        /* Initialize the display and try to open both UART and LCD types of display.*/
        Display_Params_init(&params);
        params.lineClearMode = DISPLAY_CLEAR_BOTH;
    	uartDisplayHandle = Display_open(Display_Type_UART, &params);
    	lcdDisplayHandle = Display_open(Display_Type_LCD, &params);
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
    	Semaphore_Params semParams;
    
        /* Call board init functions. */
        Board_initGeneral();
    
        /* Open LED pins */
        ledPinHandle = PIN_open(&ledPinState, pinTable);
        if(!ledPinHandle)
        {
            System_abort("Error initializing board LED pins\n");
        }
    
        /* Open Button pins*/
        buttonPinHandle = PIN_open(&buttonPinState, buttonPinTable);
        if (!buttonPinHandle) {
            System_abort("Error initializing button pins\n");
        }
    
    
        /* Setup callback for button pins*/
        if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFunction) != 0) {
            System_abort("Error registering button callback function");
        }
    
        /* Construct a Semaphore object to be used as a resource lock, inital count 0*/
    	Semaphore_Params_init(&semParams);
    	Semaphore_construct(&txSemaphore, 0, &semParams);
    	Semaphore_construct(&rxSemaphore, 0, &semParams);
    
    	/* Obtain instance handle*/
    	txSemaphoreHandle = Semaphore_handle(&txSemaphore);
    	rxSemaphoreHandle = Semaphore_handle(&rxSemaphore);
    
    	/* Initialize task */
    	rxTaskInit();
    
    	/* Initialize task */
    	txTaskInit();
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    I include my code, if someone can check it, i will be very grateful.

    Regards

  • I fixed it. I got a mistake in my configuration.
    Thanks a lot Prashanth.
  • hello:

    /* Enter RX mode and stay forever in RX */
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);

    That mean cc1310 will stay  forever in RF ,when it don't receive a packet data .But i want  CC1310  stop  stay forever in RX and close RF after 10ms when it don't receive any packet data . can you have any Suggest to me ?

  • Hello Phoenix rain, 

    CC1310 does not have to stay in Rx for ever. You can configure it to start Rx and abort if no packets are received with in a certain time 

    To acheive this you can use RF_postCmd() instead of RF_runCmd()  RF_runCmd() first posts the cmd and waits for it to complete. You can use RF_postCmd() and wait for your desired amount of time using CPUDelay(). If there is no packet received with in this time then you can use RF_cancelCmd() to end the Rx. Below is a sample code as an example. If a packet is received with in this time then the callback function will be invoked.

    RF_CmdHandle rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);

    CPUdelay(x_cycles); /* Wait for x/3 cycles*/

    RF_cancelCmd(rfHandle, rx_cmd, 0);  /* Abort the RF rx_cmd */

    I hope this helps. 

    Regards,

    PS

  • Prashanth: Why this solution instead of using endTime?
  • TER,
    Thanks for the comment. Using endTime is a more elegant way of doing this.
    Phoenix Rain,
    Like TER suggested you can use endTime instead of the above proposed method.
  • Thank you PrashanthS.
    I use your method.But program stop run next after " RF_cancelCmd(rfHandle, rx_cmd, 0); /* Abort the RF rx_cmd */".do you tested it?
    And i don't know how to Configuration parameters with endTime. Whether need to configure endTrigge? I tested it ,but faied.
    Happy Dragon Boat Festival!
  • Hello Phoenix rain, 

    I did test the modifications I mentioned and it works. The execution reaches the while(1) and does not get stuck at RF_cancelCmd(). 

    This is what I did. Imported the rfPacketRx example project and modfied as below

    static void rxTaskFunction(UArg arg0, UArg arg1)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
    
        /* Modify CMD_PROP_RX command for application needs */
        RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;  /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;   /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.pktConf.bRepeatOk = 1;
        RF_cmdPropRx.pktConf.bRepeatNok = 1;
    
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    
        /* Enter RX mode and stay forever in RX */
       // RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    
        RF_CmdHandle rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    
        CPUdelay(160000); /* Wait for x/3 cycles*/
    
        RF_cancelCmd(rfHandle, rx_cmd, 0);  /* Abort the RF rx_cmd */
    
        while(1);
    }
    

  • Hello Phoenix rain,

    Also when using endTime you can set the triggerType to TRIG_REL_START and endTime to a desired time out value as below. I tested this and it works.

    .endTrigger.triggerType = TRIG_REL_START,
    .endTrigger.bEnaCmd = 0x0,
    .endTrigger.triggerNo = 0x0,
    .endTrigger.pastTrig = 0x0,
    .endTime = 0x00001000,

    Regards,
    Prashanth
  • dear PrashanthS :
    i will test it day after tomorrow ,because i rest recently.Thank you for everything again.
  • Hi Prashanth,

    In this question earlier , I didn't ask anything about the current consumption.
    But currently in this project, minimization of the current is the highest priority.

    Now what should be the best way to do this switching of Rx & Tx with the minimum current consumption?

    I saw the rfwakeon RX example as suggested by TER and able to end the trigger of Rx for every cycle(1sec) but could not able to bring Tx along with this. It works fine(100% reliable) with the complete Rx only cycle. But the moment, I bring Tx , it does not repeat. It executes only once. It stops.

    My application is first Rx & then Tx and cycle is 1sec.

    How to switch to Tx from Rx along with end trigger?

    Please suggest.

    Thanks & regards,
    Ankur
  • Ankur, 

    Are you using the rfwakeOnRx together with rfWakeOnTx?  If so then it should work. If you are using rfWakeOnRx with rfPacketTx then it will not work as rfWakeOnRx needs a long preamble that rfPacketTx does not have. Can you please give further details of your setup and the modifications you made.

    Regards,

    Prashanth

  • Hi Prashanth,

    I am not using rfwakeonRx. I am using rfpacketRx and using the end trigger to end the Rx and ofcourse setting up a wakeup interval in the while loop. I adjust the start time every time it enters the callback and avoids the usage of long preamble. This Rx part works perfectly .
    Now after ending Rx in CC1310, I want to do Tx from CC1310 which is not happening. The moment I bring the Tx command, CC1310 stops. May be I am doing something wrong. I have only one Rx task.
    My setup is
    1) Packet transmitted by CC1101
    2) Packet received by CC1310
    3) Packet transmitted by CC1310 to CC1101
    4) Data generated by CC1310 for 10msec.
    5) CC1310 sleep mode
    6) CC1310 wakes up for the next cycle.

    These whole steps I did earlier but there was no current saving. It was always on forever.
    My application involves only the usage of coin batteries. I want to make the battery life as long as possible.
    I want to do these six steps with minimum power consumption.

    I saw the rfwakeonRx example and put the end trigger functionality for the rfpacketRx. My Rx is fine but how to do other things I am not sure.
    Below is code part:

    static void rxTaskFunction(UArg arg0, UArg arg1)
    {
    RF_Params rfParams;

    RF_Params_init(&rfParams);

    // rfParams.nInactivityTimeout = 0;


    /* Route out LNA active pin to LED1 */
    PINCC26XX_setMux(ledPinHandle, Board_LED4, PINCC26XX_MUX_RFC_GPO0);


    if( RFQueue_defineQueue(&dataQueue,
    rxDataEntryBuffer,
    sizeof(rxDataEntryBuffer),
    NUM_DATA_ENTRIES,
    MAX_LENGTH + NUM_APPENDED_BYTES))
    {
    /* Failed to allocate space for all data entries */
    while(1);
    }

    /* Modify CMD_PROP_RX command for application needs */
    RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
    // RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1; /* Discard ignored packets from Rx queue */
    // RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
    RF_cmdPropRx.pktConf.bRepeatOk = 1;
    RF_cmdPropRx.pktConf.bRepeatNok = 1;
    RF_cmdPropRx.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdPropRx.startTrigger.pastTrig = 1;
    // RF_cmdPropRx.startTime = 0;
    RF_cmdPropRx.endTrigger.triggerType = TRIG_REL_START;


    RF_cmdPropRx.endTime = 0x00003D0900;

    RF_cmdPropTx.startTrigger.triggerType = TRIG_ABSTIME;
    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = txPacket;




    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);


    /* Set the frequency */
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);


    while(1)
    {

    RF_cmdPropRx.startTime += PACKET_INTERVAL;


    /* Schedule RX */
    RF_CmdHandle lastCommand = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);


    RF_pendCmd(rfHandle, lastCommand, RF_EventLastCmdDone);

    txPacket[0] = 0x99;
    txPacket[1] = 0xAA;
    txPacket[2] = 0x2B;


    RF_cmdPropTx.startTime = RF_cmdPropRx.startTime+ PACKET_INTERVAL +32000 ;

    /* Schedule Tx */
    RF_CmdHandle lastCommand1 = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);



    RF_pendCmd(rfHandle, lastCommand1, RF_EventLastCmdDone);


    PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));


    }



    }

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    if (e & RF_EventRxEntryDone)
    {
    /* Toggle pin to indicate RX */
    PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));

    /* Get current unhandled data entry */
    currentDataEntry = RFQueue_getDataEntry();

    /* Handle the packet data, located at &currentDataEntry->data:
    * - Length is the first byte with the current configuration
    * - Data starts from the second byte */
    packetLength = *(uint8_t*)(&currentDataEntry->data);
    packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);


    /* Copy the payload + the status byte to the packet variable */
    memcpy(packet, packetDataPointer, (packetLength + 1));


    RF_cmdPropRx.startTime = RF_getCurrentTime();

    RF_cmdPropRx.endTime = 20000;//5msec




    RFQueue_nextEntry();
    }
    }

    This executes once for Rx and then stops. But works continuous for the only Rx part.
    How to do Tx after Rx and make the cycle complete with all the six steps mentioned above?

    Please suggest.

    Thanks & regards,
    Ankur
  • Ankur,

    Such issues may happen if the previous issued commands are still in the queue. You can use RF_cancelCmd(RF_Handle h, RF_CmdHandle ch, uint8_t mode)  to abort  commands in the queue. 

        while(1)
        {
    
        	RF_cmdPropRx.startTime += PACKET_INTERVAL;
    
        	/* Schedule RX */
        	RF_CmdHandle lastCommand = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
        	RF_pendCmd(rfHandle, lastCommand, RF_EventLastCmdDone);
    
        	RF_cancelCmd(rfHandle, lastCommand, 0);
    
        	txPacket[0] = 0x99;
        	txPacket[1] = 0xAA;
        	txPacket[2] = 0x2B;
    
        	RF_cmdPropTx.startTime = RF_cmdPropRx.startTime+ PACKET_INTERVAL +32000 ;
    
        	/* Schedule Tx */
        	RF_CmdHandle lastCommand1 = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    
        	RF_pendCmd(rfHandle, lastCommand1, RF_EventLastCmdDone);
    
        	RF_cancelCmd(rfHandle, lastCommand1, 0);
    
        	PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
    
        }
    

    Also please note that in your code you are posting a TX command right after an RX command. In such a case a Tx will be triggered even when there is no received packet, which to my understanding is not what you want. To do a TX only when a packet is received, you should trigger a TX in the RX callback function. You can use a separate TX task and post the TX semaphore in the RX callback as mentioned in an earlier example in this thread.

    Regards,

    Prashanth

  • Hi Prashanth,

    Thank you so much.

    Regards,
    Ankur
  • Hi Prasant,

    I am also trying to achieve the same for my project.

    However, the difference is that I want to change the mode of transmission based on key press event.

    For the board that is initialised as Rx first, the issue faced is that although the radio goes from Rx to Tx but is is never able to come back to Tx mode.

    And for the board that is initialised as Tx first, as soon as I try to initialise it to Rx it runs into exception handler stating Hard Fault which I am not able to figure.

    Please suggest some look around that I can check into.

    Also while understanding the example codes I understood that getting into any particular mode is by calling the RF_runcmd and giving the command ID for Rx or Tx. (Please correct if I am wrong)

    But how do one come out of that mode and re-enter again.

    As my final task is 2 accomplish 2-way communication based on key press event.

    Thank you in advance.

    Vikram

  • Hello Vikram, 

    You can use RF_cancelCmd() to come out of one mode and issue a new RF_runCmd(). There is a code snippet in this same thread that you can refer to. Please note that commands are executed in a queue and if a command never returns, you can use RF_cancelCmd() to abort it. 

    Regards,

    Prashanth 

  • Thank you Prashanth,

    So just to verify, I don't need to use the RF_postCmd and RF_pendCmd but I can straight use the RF_runCmd and followed by RF_cancelCmd?

    Regards,
    Vikram
  • Ankur,

    The RF_runCmd() will post the command and will wait for it to complete. In order for you to be able to cancel the command you need to use RF_postCmd().

    Regards,
    Prashanth
  • Hi Ewen,

    Did you get your code working?

    I mean did you programmed both CC1310 boards with the same code and both the boards were able to go into rx and tx mode based on keypress event?

    I cannot make both boards working if loaded the same code.

    One of the board has to be receiving and the other can have tx and rx then only it works.

    Can you please share your code?

    Thank you

    Vikram

  • Hi Prashanth,
    I receive a frame via UART in RX process and want to send this frame, which use TX process but also want RX process wait for sending complete and then wait to receive. I dont know how to do this, please show me.

    Regards,
    Nguyen


    /***** Includes *****/
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>

    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>

    /* Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <driverlib/rf_prop_mailbox.h>

    /* Board Header files */
    #include "Board.h"

    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"

    #include <stdlib.h>

    #include <ti/drivers/UART.h>
    UART_Handle uart;
    UART_Params uartParams;

    #define UARTSTACKSIZE 768

    Task_Struct taskUARTStruct;
    Char taskUARTStack[UARTSTACKSIZE];

    Task_Params uartTaskParams;

    /* Pin driver handle */
    static PIN_Handle ledPinHandle;
    static PIN_State ledPinState;

    Semaphore_Params semParams;

    /*
    * Application LED pin configuration table:
    * - All LEDs board LEDs are off.
    */
    PIN_Config pinTable[] =
    {
    Board_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    Board_LED2 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
    };


    const uint8_t ID_DEVICE[8] = {0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
    #define RF_HEADER0 'L'
    #define RF_HEADER1 'O'
    #define RF_HEADER2 'W'

    uint8_t ucRfSttFrame = 0;

    uint8_t CompareInfo(uint8_t *info);
    uint8_t XuLyDuLieuNhan(uint8_t *data, uint8_t size);

    /***** Defines *****/
    #define RX_TASK_STACK_SIZE 1024
    #define RX_TASK_PRIORITY 3

    /* Packet RX Configuration */
    #define DATA_ENTRY_HEADER_SIZE 8 /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH 100 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES 2 /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES 2 /* The Data Entries data field will contain:
    * 1 Header byte (RF_cmdPropRx.rxConf.bIncludeHdr = 0x1)
    * Max 30 payload bytes
    * 1 status byte (RF_cmdPropRx.rxConf.bAppendStatus = 0x1) */



    /***** Prototypes *****/
    static void rxTaskFunction(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);

    /***** Variable declarations *****/
    static Task_Params rxTaskParams;
    Task_Struct rxTask; /* not static so you can see in ROV */
    static uint8_t rxTaskStack[RX_TASK_STACK_SIZE];

    static RF_Object rfObject;
    static RF_Handle rfHandle;

    uint8_t flag = 1;

    /* Buffer which contains all Data Entries for receiving data.
    * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
    #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
    MAX_LENGTH,
    NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
    #pragma data_alignment = 4
    static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
    MAX_LENGTH,
    NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
    static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
    MAX_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4)));
    #else
    #error This compiler is not supported.
    #endif

    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;

    static PIN_Handle pinHandle;

    static uint8_t packet[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
    //////////////////////////////////////////////////////////////////////////////////

    #define TX_TASK_STACK_SIZE 1024
    #define TX_TASK_PRIORITY 3

    #define PAYLOAD_LENGTH 100
    #define PACKET_INTERVAL (uint32_t)(4000000*0.5f)

    static void txTaskFunction(UArg arg0, UArg arg1);
    static uint8_t txPacket[PAYLOAD_LENGTH];

    static uint8_t txTaskStack[TX_TASK_STACK_SIZE];
    static Task_Params txTaskParams;
    Task_Struct txTask;

    Semaphore_Struct semTxStruct;
    Semaphore_Handle semTxHandle;
    Semaphore_Struct semRxStruct;
    Semaphore_Handle semRxHandle;

    /***** Function definitions *****/
    void RfTask_init(PIN_Handle ledPinHandle) {
    pinHandle = ledPinHandle;

    Task_Params_init(&rxTaskParams);
    rxTaskParams.stackSize = RX_TASK_STACK_SIZE;
    rxTaskParams.priority = RX_TASK_PRIORITY;
    rxTaskParams.stack = &rxTaskStack;
    rxTaskParams.arg0 = (UInt)1000000;
    Task_construct(&rxTask, rxTaskFunction, &rxTaskParams, NULL);

    Task_Params_init(&txTaskParams);
    txTaskParams.stackSize = TX_TASK_STACK_SIZE;
    txTaskParams.priority = TX_TASK_PRIORITY;
    txTaskParams.stack = &txTaskStack;
    txTaskParams.arg0 = (UInt)1000000;
    Task_construct(&txTask, txTaskFunction, &txTaskParams, NULL);
    }

    static void rxTaskFunction(UArg arg0, UArg arg1)
    {
    RF_Params rfParams;
    RF_Params_init(&rfParams);
    if(RFQueue_defineQueue(&dataQueue, rxDataEntryBuffer, sizeof(rxDataEntryBuffer),
    NUM_DATA_ENTRIES, MAX_LENGTH + NUM_APPENDED_BYTES))
    { /* Failed to allocate space for all data entries */
    while(1);
    }
    /* Modify CMD_PROP_RX command for application needs */
    RF_cmdPropRx.pQueue = &dataQueue; /* Set the Data Entity queue for received data */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1; /* Discard ignored packets from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1; /* Discard packets with CRC error from Rx queue */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH; /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
    RF_cmdPropRx.pktConf.bRepeatOk = 0;
    RF_cmdPropRx.pktConf.bRepeatNok = 0;
    if (!rfHandle)
    { /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    }

    // RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    // Semaphore_pend(semRxHandle, BIOS_WAIT_FOREVER);

    while (1)
    { /* Enter RX mode and stay forever in RX */
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    Semaphore_pend(semRxHandle, BIOS_WAIT_FOREVER);
    }
    }

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    if (e & RF_EventRxEntryDone)
    {
    /* Toggle pin to indicate RX */
    PIN_setOutputValue(pinHandle, Board_LED2,!PIN_getOutputValue(Board_LED2));

    /* Get current unhandled data entry */
    currentDataEntry = RFQueue_getDataEntry();

    /* Handle the packet data, located at &currentDataEntry->data:
    * - Length is the first byte with the current configuration
    * - Data starts from the second byte */
    packetLength = *(uint8_t*)(&currentDataEntry->data);
    packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);

    /* Copy the payload + the status byte to the packet variable */
    memcpy(packet, packetDataPointer, (packetLength + 1));

    XuLyDuLieuNhan(packet, packetLength);
    // Semaphore_post(semTxHandle);

    RFQueue_nextEntry();
    }
    }

    struct{
    uint8_t AddrSrc[8];
    uint8_t AddrDst[8];
    uint8_t stt;

    }stInfoFrameRx;

    uint8_t CompareInfo(uint8_t *info)
    {
    int i , j;
    for( i = 0; i < 8; i++)
    {
    if(stInfoFrameRx.AddrSrc[i] != *(info + i)) break;
    if(stInfoFrameRx.AddrDst[i] != *(info + i + 8)) break;
    }
    if(stInfoFrameRx.stt == *(info + 16) && i == 8) return 0; //frame lap lan 2

    for(i = 0; i < 8; i++)
    {
    if(ID_DEVICE[i] != *(info + i + 8)) break;
    }
    if(i == 8) //frame den dich
    {
    for(j = 0; j < 8; j++)
    {
    stInfoFrameRx.AddrSrc[j] = *(info + j);
    stInfoFrameRx.AddrDst[j] = *(info + j + 8);
    }
    stInfoFrameRx.stt = *(info + 16);
    return 2;
    }

    for( i = 0; i < 8; i++)
    {
    stInfoFrameRx.AddrSrc[i] = *(info + i);
    stInfoFrameRx.AddrDst[i] = *(info + i + 8);
    }
    stInfoFrameRx.stt = *(info + 16);
    return 1;
    }

    uint8_t XuLyDuLieuNhan(uint8_t *data, uint8_t size)
    {
    uint8_t i, stt = 0, cs = 0, malenh;
    int len;

    switch(CompareInfo(data + 6))
    {
    case 0:
    Semaphore_post(semRxHandle);
    break;
    case 1:
    Semaphore_post(semTxHandle);
    break;
    case 2:
    Semaphore_post(semRxHandle);
    for(i = 0; i < size; i++)
    {
    switch(stt)
    {
    case 0:
    if(data[i] == RF_HEADER0) stt = 1;
    break;
    case 1:
    if(data[i] == RF_HEADER1) stt = 2;
    break;
    case 2:
    if(data[i] == RF_HEADER2) stt = 3;
    break;
    case 3:
    malenh = data[i];
    cs += data[i];
    stt = 4;
    break;
    case 4:
    len = data[i];
    cs += data[i];
    stt = 5;
    break;
    case 5:
    len = len + (int)data[i] << 8;
    cs += data[i];
    stt = 6;
    break;
    case 6:
    //copy data if necessary
    cs += data[i];
    if(i >= len + 6)
    {
    stt = 7;
    }
    break;
    case 7:
    cs = 0x00 - ~cs;
    if(cs == data[i])
    {
    stt = 0;
    return(malenh);
    }
    stt = 0;
    break;
    }
    if(stt == 0) break;
    }
    break;
    }
    return 0;
    }


    static void txTaskFunction(UArg arg0, UArg arg1)
    {

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = txPacket;

    while(1)
    {
    Semaphore_pend(semTxHandle, BIOS_WAIT_FOREVER);
    /* Set absolute TX time to utilize automatic power management */
    /* Send packet */
    RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    PIN_setOutputValue(pinHandle, Board_LED1,!PIN_getOutputValue(Board_LED1));
    Semaphore_post(semRxHandle);
    }
    }

    void rfFunctionData(uint8_t *data, uint16_t size)
    {
    uint8_t i;
    RF_cmdPropTx.pktLen = size;

    memcpy(txPacket, data, size);
    for(i = 0; i < 8; i++)
    {
    txPacket[i + 6] = ID_DEVICE[i];
    }
    txPacket[22] = ucRfSttFrame + 1;

    txPacket[size] = 0;

    for(i = 3; i < size - 2; i++)
    {
    txPacket[size - 1] += txPacket[i];
    }
    txPacket[size - 1] = 0x00 - ~txPacket[size - 1];

    }

    uint8_t ucUARTframeRx[200];
    uint16_t uiUARTindexRx = 0;
    uint16_t uiUARTlenRx = 0;

    uint8_t ucUARTsttcheck = 0;
    uint8_t ucUARTchecksum = 0;
    uint8_t ucUARTmalenh;

    #define UART_HEADER0 'L'
    #define UART_HEADER1 'O'
    #define UART_HEADER2 'W'

    static void uartTaskFunction(UArg arg0, UArg arg1)
    {
    uint8_t input;
    while (1)
    {
    UART_read(uart, &input, 1);
    switch(ucUARTsttcheck)
    {
    case 0:
    if(input == UART_HEADER0)
    {
    uiUARTindexRx = 0;
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;

    ucUARTsttcheck = 1;
    }
    break;
    case 1:
    if(input == UART_HEADER1)
    {
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTsttcheck = 2;
    }
    else if(input == UART_HEADER0)
    {
    uiUARTindexRx = 0;
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;

    ucUARTsttcheck = 1;
    }
    else ucUARTsttcheck = 0;
    break;
    case 2:
    if(input == UART_HEADER2)
    {
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTsttcheck = 3;
    }
    else if(input == UART_HEADER0)
    {
    uiUARTindexRx = 0;
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTsttcheck = 1;
    }
    else ucUARTsttcheck = 0;
    break;
    case 3:
    ucUARTchecksum = 0;
    ucUARTmalenh = input;
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTchecksum += input;
    ucUARTsttcheck = 4;
    break;
    case 4:
    uiUARTlenRx = input;
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTchecksum += input;
    ucUARTsttcheck = 5;
    break;
    case 5:
    uiUARTlenRx = uiUARTlenRx + ((uint16_t)input << 8);
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTchecksum += input;
    if(uiUARTlenRx != 0) ucUARTsttcheck = 6;
    else ucUARTsttcheck = 7;
    break;
    case 6:
    ucUARTframeRx[uiUARTindexRx] = input;
    uiUARTindexRx++;
    ucUARTchecksum += input;
    if(uiUARTindexRx >= uiUARTlenRx + 6)
    {
    ucUARTsttcheck = 7;
    }
    break;
    case 7:
    ucUARTchecksum = 0x00 - ~ucUARTchecksum;
    ucUARTframeRx[uiUARTindexRx] = input;
    if(ucUARTchecksum == input)
    {
    switch(ucUARTmalenh)
    {
    case 0:
    rfFunctionData(ucUARTframeRx, uiUARTindexRx + 1);
    Semaphore_post(semTxHandle);
    break;
    case 1:
    rfFunctionData(ucUARTframeRx, uiUARTindexRx + 1);
    // Semaphore_post(semTxHandle);
    break;
    }
    }
    ucUARTsttcheck = 0;
    break;
    }
    }
    }

    void UARTtask_init(void)
    {
    Task_Params_init(&uartTaskParams);
    uartTaskParams.stackSize = UARTSTACKSIZE;
    // uartTaskParams.priority = 1;
    uartTaskParams.stack = &taskUARTStack;
    Task_construct(&taskUARTStruct, (Task_FuncPtr)uartTaskFunction, &uartTaskParams, NULL);

    UART_Params_init(&uartParams);
    uartParams.writeDataMode = UART_DATA_BINARY;
    uartParams.readDataMode = UART_DATA_BINARY;
    uartParams.readReturnMode = UART_RETURN_FULL;
    uartParams.readEcho = UART_ECHO_OFF;
    uartParams.baudRate = 115200;
    uart = UART_open(Board_UART0, &uartParams);
    }


    /*
    * ======== main ========
    */
    int main(void)
    {
    /* Call board init functions. */
    Board_initGeneral();

    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if(!ledPinHandle)
    {
    System_abort("Error initializing board LED pins\n");
    }
    Semaphore_Params_init(&semParams);
    Semaphore_construct(&semTxStruct, 0, &semParams);
    Semaphore_construct(&semRxStruct, 0, &semParams);

    /* Obtain instance handle */
    semTxHandle = Semaphore_handle(&semTxStruct);
    semRxHandle = Semaphore_handle(&semRxStruct);


    /* Initialize task */
    RfTask_init(ledPinHandle);

    /* Initialize task */

    UARTtask_init();

    /* Start BIOS */
    BIOS_start();
    return (0);
    }
  • hello Prashant,
    If we use endTime instead of CPUdelay(), we don't have to use RF_cancelCmd ?(correct me if I am wrong) Here I am using endTime as
    RF_cmdPropRx.endTime = RF_convertMsToRatTicks(5000);
    and still code is not able to get into rx callback even if other transmitter is transmitting at every second.

    Regards,
    Omkar
  • Hello Omkar,

    Your understanding about endTime is correct. Does the Rx ever enter callback with out the endTime? Please make sure that all the Rx settings match the Tx settings to receive the packets. You can also try using the basic RF packet Rx example to check if packets are received at all.

    Regards,

    Prashanth 

  • Hello Prashanth,
    Now it is working. I was making the mistake of using - RF_cancelCmd(rfHandle, rx_cmd, 0). I am now waiting for rx till the endTime as defined in while loop as given in RF packet rx :
    while (1) {
    // Enter RX mode and stay forever in RX
    RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    Semaphore_pend(semRxHandle, BIOS_WAIT_FOREVER);
    }
    It is now entering in rx callback and I can see the expected data. Thank you!

    Regards,
    Omkar
  • Hi everybody!

    I have a similar task.

    The data is received on the UART, after which the packet ID is read. Depending on the ID, the packet is transmitted or the Rx mode is enabled or Rx mode aborted. In most cases everything works fine: in the Rx mode, the packet is received over the radio, after which it goes to Idle and can be easily switched to any mode (Tx or Rx - does not matter), also in Tx mode it transmits the packet without problems. Problems begin when I try to exit Rx mode via the RF_CancelCmd (). After "cancel", the CC1310 can send the packet only once, after which the packets are no longer sent (no reaction for new Tx commands). Also receiving packets after "cancel" and then "Rx" does not work at all.

    The code looks similar to others in this thread, but it does not work properly. Please help if it's possible.

    Also the source file is included.

    uart_tx_rx.c
    /* XDCtools Header files */
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <ti/drivers/UART.h>
    #include <driverlib/rf_prop_mailbox.h>
    
    //Example/Board Header files
    #include "Board.h"
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    #include <stdlib.h>
    
    #define TASKSTACKSIZE   1280
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH             64 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:*/
    
    
    
    
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    PIN_Handle pinHandle = NULL;
    static uint8_t packet_tx[MAX_LENGTH];
    static PIN_Handle pinHandle;
    
    
    UART_Handle uart;
    UART_Params uartParams;
    
    RF_Params rfParams;
    RF_CmdHandle rx_cmd;
    
          
    
    static void Tx_Fxn(UArg a0, UArg a1);
    static void Main_Fxn(UArg a0, UArg a1);
    static void Rx_Fxn(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;
    
    static uint8_t packet_rx[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
            
            
    
    Task_Struct task0Struct, task1Struct, task2Struct;
    
    Char task0Stack[TASKSTACKSIZE], task1Stack[TASKSTACKSIZE], task2Stack[TASKSTACKSIZE];
    
    Task_Handle Tx_Task, Main_Task, Rx_Task;
    Semaphore_Struct sem0Struct, sem1Struct;
    Semaphore_Handle Tx_Sem, Rx_Sem;
    
    
    
    
    // Buffer which contains all Data Entries for receiving data.
    // Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core)
    #if defined(__TI_COMPILER_VERSION__)
        #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
            static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
        #pragma data_alignment = 4
            static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
            static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                MAX_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4)));
    #else
        #error This compiler is not supported.
    #endif
    
    
    
    void Tx_Fxn(UArg a0, UArg a1) {
    
        while (1) {
          
            Semaphore_pend(Tx_Sem, BIOS_WAIT_FOREVER);
            
            RF_cmdPropTx.pPkt = packet_tx;
                
            /* Send packet */
            RF_EventMask result = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
                                  
            RF_pendCmd(rfHandle, result, RF_EventLastCmdDone);
          
        }
    }
    
    
    void Main_Fxn(UArg a0, UArg a1) {
    
        if(!rfHandle){
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
    	}
    
        while (1) {
            UART_read(uart,packet_tx,64);
    
    	/*
    	Attention!
    	The ID byte has place #0 for "Rx-Mode" and "Cancel" but place #3 for "Tx-Mode"
    	*/
            
            if(packet_tx[3]=='S'||packet_tx[3]=='D'){ //"Send the packet" command received from UART ("Tx")
              
            Semaphore_post(Tx_Sem);
            }
            else if(packet_tx[0]=='R'){ //"Receive mode on" command received from UART ("Rx")
            
            UART_write(uart, "_RX_", 4);
            Semaphore_post(Rx_Sem);
            }
          
            else if(packet_tx[0]=='U'){ //"Undo RX mode on" command received from UART ("cancel")
             
            UART_write(uart, "Stop", 4);
            RF_cancelCmd(rfHandle, rx_cmd, 0);
               
            }
        }
    }
    
    
    static void Rx_Fxn(UArg arg0, UArg arg1)
    {
      
            
    
        while(1){
          
        Semaphore_pend(Rx_Sem, BIOS_WAIT_FOREVER);
        
       
        //----------------------------------------------------------------------------
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
       
        //----------------------------------------------------------------------------
        
        
        rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
    
        RF_pendCmd(rfHandle, rx_cmd, RF_EventLastCmdDone);
    
        
    
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    
        if (e & RF_EventRxEntryDone)
        {
            
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet_rx, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
            
            UART_write(uart,packet_rx,packetLength); 
        }
    
    }
    
    
    /*
     *  ======== main ========
     *
     */
    int main(void)
    {
        Task_Params taskParams;
        Semaphore_Params semParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initUART();
       
           
        //UART Init
        UART_Params_init(&uartParams);
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
        uart = UART_open(Board_UART0, &uartParams);
        
        //RF Init
        RF_Params_init(&rfParams);
        
        RF_cmdPropTx.pktLen = MAX_LENGTH;
    
        RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 0;  /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 0;   /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.pktConf.bRepeatOk = 0;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
    
            
        /* Construct Task threads */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        
        /*Rx Task*/
        taskParams.stack=&task2Stack;
        taskParams.priority=2;
        taskParams.instance->name = "Rx_Fxn"; 
        taskParams.arg0 = (UInt)1000000;
        Task_construct(&task2Struct, (Task_FuncPtr)Rx_Fxn, &taskParams, NULL);
        Rx_Task = Task_handle(&task2Struct);
        
        /*Tx Task*/
        taskParams.stack = &task0Stack;
        taskParams.priority = 2;
        taskParams.instance->name = "Tx_Fxn";
        Task_construct(&task0Struct, (Task_FuncPtr)Tx_Fxn, &taskParams, NULL);
        Tx_Task = Task_handle(&task0Struct);
        
        /*Main Task */
        taskParams.stack = &task1Stack;
        taskParams.priority = 1;
        taskParams.instance->name = "Main_Fxn";
        Task_construct(&task1Struct, (Task_FuncPtr)Main_Fxn, &taskParams, NULL);
        Main_Task = Task_handle(&task1Struct);
        
        
        //Semaphore init
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        Semaphore_construct(&sem0Struct, 0, &semParams);
        Tx_Sem = Semaphore_handle(&sem0Struct);
        
        Semaphore_construct(&sem1Struct, 0, &semParams);
        Rx_Sem = Semaphore_handle(&sem1Struct);
        
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

    Regards,

    Vladimir

  • Hello Vladimir, 

    From your code when you cancel the Rx, you are calling RF_CancelCmd() even when the device is not in active Rx state. Can you try changing that and run RF_CancelCmd only when rx_cmd is not Null. Can you try this and see if this changes the behavior. 

    Also in your Rx_Fxn, RFQueue_defineQueue() is getting called every time. Can you take it out of the while(1) loop and try.

    Regards,

    Prashanth

  • Hello Prashanth

    Thanks for the answer. Right now I'm trying to make the code working

    Regards,

    Vladimir

  • Hello Prashant,
    I have followed and used the program you modifed for changing from RF_Rx to RF_Tx, however I noticed that after some time ,both the Rx and Tx tasks are blocked and only idle task is running. I also have one clock object of period 1 seconds. What can be the possible reason behind tasks getting blocked? Please let me know if you need more information.

    Regards,
    Omkar
  • Hello Prashanth,

    Sorry for long delay.

    It works now!  Thanks!

    I changed the callback function a little and it helped. 

    Upd: It almost works. A little problem was discovered. After "stop" command it works but the packet that I receive at Rx side from UART is the previously received packet (before "stop").

    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
        if (e & RF_EventRxEntryDone)
        {
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet_rx, packetDataPointer, (packetLength + 1));
            RFQueue_nextEntry();
            if(rx_stop==0){
            UART_write(uart,packet_rx,packetLength);
            }
    }
            
    if(rx_stop==1){ //when "cancel" command was received from uart
      rx_stop=0;
            UART_write(uart,"cancelled",9);
    /*Next 2 strings made code work properly*/ RFQueue_getDataEntry(); RFQueue_nextEntry(); } }

    Also, I attach full code in file: 

    Rx_Tx_Stop.c
    /* XDCtools Header files */
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/System.h>
    
    /* BIOS Header files */
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* TI-RTOS Header files */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/Power.h>
    #include <ti/drivers/power/PowerCC26XX.h>
    #include <ti/drivers/UART.h>
    #include <driverlib/rf_prop_mailbox.h>
    
    
    
    /* Example/Board Header files */
    #include "Board.h"
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    #include <stdlib.h>
    
    
    
    #define TASKSTACKSIZE   1280
    #define DATA_ENTRY_HEADER_SIZE 8  /* Constant header size of a Generic Data Entry */
    #define MAX_LENGTH             64 /* Max length byte the radio will accept */
    #define NUM_DATA_ENTRIES       2  /* NOTE: Only two data entries supported at the moment */
    #define NUM_APPENDED_BYTES     2  /* The Data Entries data field will contain:*/
    
    
    
    
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    PIN_Handle pinHandle = NULL;
    static uint8_t packet_tx[MAX_LENGTH];
    uint8_t rx_flag=0;
    uint8_t tx_flag=0;
    uint8_t rx_stop=0;
    
    
    UART_Handle uart;
    UART_Params uartParams;
    
    RF_Params rfParams;
    
    
    RF_CmdHandle rx_cmd;
    
          
    
    static void Tx_Fxn(UArg a0, UArg a1);
    static void Main_Fxn(UArg a0, UArg a1);
    static void Rx_Fxn(UArg arg0, UArg arg1);
    static void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    
    
    
    /* Buffer which contains all Data Entries for receiving data.
     * Pragmas are needed to make sure this buffer is 4 byte aligned (requirement from the RF Core) */
    #if defined(__TI_COMPILER_VERSION__)
        #pragma DATA_ALIGN (rxDataEntryBuffer, 4);
            static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    #elif defined(__IAR_SYSTEMS_ICC__)
        #pragma data_alignment = 4
            static uint8_t rxDataEntryBuffer[RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                                                                     MAX_LENGTH,
                                                                     NUM_APPENDED_BYTES)];
    #elif defined(__GNUC__)
            static uint8_t rxDataEntryBuffer [RF_QUEUE_DATA_ENTRY_BUFFER_SIZE(NUM_DATA_ENTRIES,
                MAX_LENGTH, NUM_APPENDED_BYTES)] __attribute__ ((aligned (4)));
    #else
        #error This compiler is not supported.
    #endif
    
    
    /* Receive dataQueue for RF Core to fill in data */
    static dataQueue_t dataQueue;
    static rfc_dataEntryGeneral_t* currentDataEntry;
    static uint8_t packetLength;
    static uint8_t* packetDataPointer;
    
    static uint8_t packet_rx[MAX_LENGTH + NUM_APPENDED_BYTES - 1]; /* The length byte is stored in a separate variable */
            
            
    
    Task_Struct task0Struct, task1Struct, task2Struct;
    
    Char task0Stack[TASKSTACKSIZE], task1Stack[TASKSTACKSIZE], task2Stack[TASKSTACKSIZE];
    
    Task_Handle Tx_Task, Main_Task, Rx_Task;
    Semaphore_Struct sem0Struct, sem1Struct;
    Semaphore_Handle Tx_Sem, Rx_Sem;
    
    
    
    
    /*
     * Application pin configuration table:
     *   - The LCD powr domain is enabled.
     *   - LEDs are off.
     *   - Down button interrupt set to trigger on falling edge.
     */
    PIN_Config pinTable[] = {
        Board_LED1     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED2     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED3     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_LED4     | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW  | PIN_PUSHPULL | PIN_DRVSTR_MAX,
        Board_KEY_DOWN | PIN_INPUT_EN       | PIN_PULLUP    | PIN_IRQ_NEGEDGE,
        Board_3V3_EN   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,
        PIN_TERMINATE
    };
    
    
    
    
    void Tx_Fxn(UArg a0, UArg a1) {
          uint64_t temp=0;
          
    while (1) {
          
            Semaphore_pend(Tx_Sem, BIOS_WAIT_FOREVER);
            RF_cmdPropTx.pktLen = MAX_LENGTH;
            RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
            RF_cmdPropTx.pPkt = packet_tx;
          
          
            /* Send packet */
            RF_EventMask result = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
            temp=result & RF_EventLastCmdDone;
            if (temp==0)
            {
               while(1);
            }
                    
        }
    }
    
    
    void Main_Fxn(UArg a0, UArg a1) {
       
        while (1) {
            UART_read(uart,packet_tx,64);
            
            if(packet_tx[3]=='S'||packet_tx[3]=='D'){    
            tx_flag=0;
            rx_stop=0;
            Semaphore_post(Tx_Sem);
            }
            
            else if(packet_tx[0]=='R'){      
            rx_flag=0;
            rx_stop=0;
            UART_write(uart,"_RX_",4);
            Semaphore_post(Rx_Sem);
            }
    
            else if(packet_tx[0]=='A'){
            tx_flag=0;
            Semaphore_post(Tx_Sem);          
            }           
            
            else if(packet_tx[0]=='U'){
            rx_stop=1;
            UART_write(uart,"_ST_",4);
            RF_cancelCmd(rfHandle, rx_cmd, 0);              
            }        
        }
    }
    
    
    static void Rx_Fxn(UArg arg0, UArg arg1)
    {
      if(rx_flag==0){
          rx_flag=1;
        if( RFQueue_defineQueue(&dataQueue,
                                rxDataEntryBuffer,
                                sizeof(rxDataEntryBuffer),
                                NUM_DATA_ENTRIES,
                                MAX_LENGTH + NUM_APPENDED_BYTES))
        {
            /* Failed to allocate space for all data entries */
            while(1);
        }
       
        }
            
        while(1){      
        Semaphore_pend(Rx_Sem, BIOS_WAIT_FOREVER);       
    
        /* Enter RX mode and stay forever in RX */
        if(rx_stop==0){
        rx_cmd = RF_postCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, IRQ_RX_ENTRY_DONE);
        RF_pendCmd(rfHandle, rx_cmd, IRQ_RX_ENTRY_DONE);
        
        }
        }
    }
    
    void callback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e)
    {
    
        if (e & RF_EventRxEntryDone)
        {
    
            /* Get current unhandled data entry */
            currentDataEntry = RFQueue_getDataEntry();
    
            /* Handle the packet data, located at &currentDataEntry->data:
             * - Length is the first byte with the current configuration
             * - Data starts from the second byte */
            packetLength      = *(uint8_t*)(&currentDataEntry->data);
            packetDataPointer = (uint8_t*)(&currentDataEntry->data + 1);
    
            /* Copy the payload + the status byte to the packet variable */
            memcpy(packet_rx, packetDataPointer, (packetLength + 1));
            RFQueue_nextEntry();
            if(rx_stop==0){
            UART_write(uart,packet_rx,packetLength);
            }
    }
            
    if(rx_stop==1){
      rx_stop=0;
            UART_write(uart,"cancelled",9);
            RFQueue_getDataEntry();
            RFQueue_nextEntry();
            }   
    
    }
    
    
    /*
     *  ======== main ========
     *
     */
    int main(void)
    {
        Task_Params taskParams;
        Semaphore_Params semParams;
    
        /* Call board init functions */
        Board_initGeneral();
        Board_initUART();
       
           
        
        UART_Params_init(&uartParams);
        uartParams.writeDataMode = UART_DATA_BINARY;
        uartParams.readDataMode = UART_DATA_BINARY;
        uartParams.readReturnMode = UART_RETURN_FULL;
        uartParams.readEcho = UART_ECHO_OFF;
        uartParams.baudRate = 115200;
        uart = UART_open(Board_UART0, &uartParams);
        
         RF_Params_init(&rfParams);
        
        /* Modify CMD_PROP_RX command for application needs */
        RF_cmdPropTx.pktLen = MAX_LENGTH;
        RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
        RF_cmdPropTx.startTrigger.pastTrig = 1;
        RF_cmdPropRx.pQueue = &dataQueue;           /* Set the Data Entity queue for received data */
        RF_cmdPropRx.rxConf.bAutoFlushIgnored = 0;  /* Discard ignored packets from Rx queue */
        RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 0;   /* Discard packets with CRC error from Rx queue */
        RF_cmdPropRx.maxPktLen = MAX_LENGTH;        /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
        RF_cmdPropRx.pktConf.bRepeatOk = 0 ;
        RF_cmdPropRx.pktConf.bRepeatNok = 0;
        
        /* Request access to the radio */
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        
        
        /* Construct Task threads */
        Task_Params_init(&taskParams);
        taskParams.stackSize = TASKSTACKSIZE;
        
        /*Rx Task*/
        taskParams.stack=&task2Stack;
        taskParams.priority=1;
        taskParams.instance->name = "Rx_Fxn"; 
        taskParams.arg0 = (UInt)1000000;
        Task_construct(&task2Struct, (Task_FuncPtr)Rx_Fxn, &taskParams, NULL);
        Rx_Task = Task_handle(&task2Struct);
        
        /*Tx Task*/
        taskParams.stack = &task0Stack;
        taskParams.priority = 1;
        taskParams.instance->name = "Tx_Fxn";
        Task_construct(&task0Struct, (Task_FuncPtr)Tx_Fxn, &taskParams, NULL);
        Tx_Task = Task_handle(&task0Struct);
        
        /*Main Task */
        taskParams.stack = &task1Stack;
        taskParams.priority = 2;
        taskParams.instance->name = "Main_Fxn";
        Task_construct(&task1Struct, (Task_FuncPtr)Main_Fxn, &taskParams, NULL);
        Main_Task = Task_handle(&task1Struct);
        
        
    
        Semaphore_Params_init(&semParams);
        semParams.mode = Semaphore_Mode_BINARY;
        Semaphore_construct(&sem0Struct, 0, &semParams);
        Tx_Sem = Semaphore_handle(&sem0Struct);
        
        Semaphore_construct(&sem1Struct, 0, &semParams);
        Rx_Sem = Semaphore_handle(&sem1Struct);
        
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

  • Hello Prashanth.

    I have as somewhat similar problem. I loaded rfWakeonTx in my cc1310 tx module and the respective rfwakeonRx in my rx module. communication is perfect. However I would like the tx controller to stay in deep sleep when the button is not pressed. It looks like the cpu is continously active and the multimeter shows a 10mA consumption current. I need it to wake up only on button press. Can you tell me how to do this?