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.

RTOS/CC1310: How to switch the RF mode from RX to TX for CC1310 Wake On Radio Example?

Expert 1595 points
Part Number: CC1310

Tool/software: TI-RTOS

Hi,

My application is always in RX WOR mode waiting for incoming data packets. However, I want to switch to TX mode whenever I press a button, this will transmit a data packet to another CC1310 in WOR RX mode. After the packet is transmitted, it returns back to RX WOR mode again until another button press.

In the WOR RX example, the rxTaskFunction has a main loop running. I understand that this main loop wakes up to check for incoming packets.

    /* 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, &RFcallback, 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++;
                break;
            default:
                /* Unhandled status */
                break;
        };
    }

I have setup a hardware interrupt to trigger when a button is press, but I don't know how to continue. How do I stop the main RX loop, change to TX mode, send out a packet and switch back to RX mode again? Can someone advise on this? Thanks in advance!

  • Hi

    You can set a flag in the buttonCallbackFunction and then check this flag in the main loop.

    If the flag is set, transmit a packet, clear the flag, and continue:

    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));
        
        transmitPacket = true;
    }
    .
    .
    .
    .
    /* 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++;
                    break;
                default:
                    /* Unhandled status */
                    break;
            };
            
            // Check if button has been pushed (set a flag in the button callback)
            if (transmitPacket)
            {
                RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
            }
             
            transmitPacket = false;
            
        }

    BR

    Siri

  • Hi Siri,

    Thanks for the tip. I followed your suggestion and also merged the setting from WakeOnRadio TX into the WakeOnRadio RX program. In debugging mode, when I press a button, the transmitPacket flag is set, and the line :

    "RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);" is called.

    However, i am not receiving anything. I have setup another launchpad with SmartRFstudio to monitor for packets transmitted.  I know my receiving setup with SmartRFStudio is working because I have tested it with another launch pad running a WakeOnRadio Tx program. 

    I still can't figure out what is wrong so I am attaching my codes here. Hopefully someone can advise. Thanks!

    WOR_RX_and_TX.c
    /*
     * Copyright (c) 2016-2017, Texas Instruments Incorporated
     * All rights reserved.
     */
    
    /***** Includes *****/
    #include <stdlib.h>
    #include <xdc/std.h>
    #include <xdc/cfg/global.h>
    #include <xdc/runtime/Assert.h>
    #include <xdc/runtime/System.h>
    #include <ti/sysbios/BIOS.h>
    #include <ti/sysbios/knl/Task.h>
    #include <ti/sysbios/knl/Clock.h>
    #include <ti/sysbios/knl/Semaphore.h>
    
    /* Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/PIN.h>
    #include <ti/drivers/PWM.h>
    #include <ti/drivers/NVS.h>
    
    /* Board Header files */
    #include "Board.h"
    
    /* RF settings, defines and helper files */
    #include "RFQueue.h"
    #include "smartrf_settings/smartrf_settings.h"
    
    #include DeviceFamily_constructPath(inc/hw_fcfg1.h)
    
    #include <ti/devices/DeviceFamily.h>
    #include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
    
    /***** Defines *****/
    
    /* Wake-on-Radio wakeups per second */
    #define WOR_WAKEUPS_PER_SECOND  2
    
    /* 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))))
    
    #define WOR_PREAMBLE_TIME_RAT_TICKS(x) \
        ((uint32_t)(4000000*(1.0f/(x))))
    
    /* TX number of random payload bytes */
    #define PAYLOAD_LENGTH 8
    
    /* TX task stack size and priority */
    #define TX_TASK_STACK_SIZE 1024
    #define TX_TASK_PRIORITY   2
    
    /* TI-RTOS Task configuration */
    #define RX_TASK_STACK_SIZE 1024
    #define RX_TASK_PRIORITY   2
    
    
    #define RXEVENT_TASK_STACK_SIZE 256
    #define RXEVENT_TASK_PRIORITY   1
    
    #define BUTTON_TASK_STACK_SIZE 256
    #define BUTTON_TASK_PRIORITY   3
    
    /* 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 packet payload (length +1 to fit length byte) and sequence number */
    static uint8_t packet[PAYLOAD_LENGTH +1];
    
    /* Advanced TX command for sending long preamble */
    static rfc_CMD_PROP_TX_ADV_t RF_cmdPropTxAdv;
    
    /* RX task objects and task stack */
    static Task_Params rxTaskParams;
    static Task_Struct rxTask;
    static uint8_t rxTaskStack[RX_TASK_STACK_SIZE];
    
    static Task_Params rxEventTaskParams;
    static Task_Struct rxEventTask;
    static uint8_t rxEventTaskStack[RXEVENT_TASK_STACK_SIZE];
    
    
    static Semaphore_Params rxEventSemParams;
    static Semaphore_Struct rxEventSemStruct;
    static Semaphore_Handle rxEventSem;
    
    
    /* RF driver object and handle */
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    /* Pin driver object and handle */
    static PIN_Handle ledPinHandle;
    static PIN_Handle buttonPinHandle;
    static PIN_State ledPinState;
    static PIN_State buttonPinState;
    
    static uint8_t pressPin = 0;
    
    // Initialize and create/contrust your clock module somewhere global ex below:
    static Clock_Struct clockStruct1;
    static Clock_Handle clockHandle1;
    
    static bool transmitPacket = false;
    
    /* MAC Address */
    static uint64_t macAddrLsb;
    static uint64_t macAddrMsb;
    static uint64_t macAddress;
    
    /* 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.
     */
    
    PIN_Config pinTable[] =
    {
        BELL | 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 both edge.
     */
    PIN_Config buttonPinTable[] = {
        BUTTON1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES,
        BUTTON2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES,
        BUTTON3 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES,
        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);
            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
    
    /* 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* packetDataPointer;
    
    /* Sniff command for doing combined Carrier Sense and RX*/
    static rfc_CMD_PROP_RX_SNIFF_t RF_cmdPropRxSniff;
    
    static char macID[80];
    
    /***** Prototypes *****/
    static void initializeTxAdvCmdFromTxCmd(rfc_CMD_PROP_TX_ADV_t* RF_cmdPropTxAdv, rfc_CMD_PROP_TX_t* RF_cmdPropTx);
    
    static void rxTaskInit();
    static void rxTaskFunction(UArg arg0, UArg arg1);
    static uint32_t calculateSymbolRate(uint8_t prescaler, uint32_t rateWord);
    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 void RFcallback(RF_Handle h, RF_CmdHandle ch, RF_EventMask e);
    static void rxEvent_fcn(UArg arg0, UArg arg1);
    
    static void buttonCallbackFunction(PIN_Handle handle, PIN_Id pinId);
    static void clockCallback1(UArg u0);
    
    static uint32_t milli_to_ticks(uint32_t milli);
    
    
    /***** Function definitions *****/
    
    /* 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;
    }
    
    
    /* RX task initialization function. Runs once from main() */
    static void rxTaskInit()
    {
        Task_Params_init(&rxTaskParams);
        rxTaskParams.stackSize = RX_TASK_STACK_SIZE;
        rxTaskParams.priority = RX_TASK_PRIORITY;
        rxTaskParams.stack = &rxTaskStack;
        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)
    {
    
        /* Setup callback for button pins */
        if (PIN_registerIntCb(buttonPinHandle, &buttonCallbackFunction) != 0) {
            System_abort("Error registering button callback function");
        }
    
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        /* Route out LNA active pin to LED1 */
        //PINCC26XX_setMux(ledPinHandle, Board_PIN_LED0, PINCC26XX_MUX_RFC_GPO0);
    
        /* 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);
        }
    
    
        /* Initialize TX_ADV command from TX command */
        initializeTxAdvCmdFromTxCmd(&RF_cmdPropTxAdv, &RF_cmdPropTx);
    
        /* Set application specific fields */
        RF_cmdPropTxAdv.pktLen = PAYLOAD_LENGTH +1; /* +1 for length byte */
        RF_cmdPropTxAdv.pPkt = packet;
        RF_cmdPropTxAdv.preTrigger.triggerType = TRIG_REL_START;
        RF_cmdPropTxAdv.preTime = WOR_PREAMBLE_TIME_RAT_TICKS(WOR_WAKEUPS_PER_SECOND);
    
    
        /* 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;
    
        /* 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);
    
        /* 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, &RFcallback, 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, &RFcallback, 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++;
                    break;
                default:
                    /* Unhandled status */
                    break;
            };
    
            // Check if button has been pushed (set a flag in the button callback)
            if (transmitPacket)
            {
                RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
            }
            transmitPacket = false;
        }
    }
    
    /* 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 RFcallback(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
            {
                /* 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 + 2);
    
                /* 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 = dummy + packetDataPointer[0];
    
            } while(RFQueue_nextEntry() == DATA_ENTRY_FINISHED);
        }
    }
    
    void rxEvent_fcn(UArg arg0, UArg arg1)
    {
        while(1)
        {
            // Block task until semaphore be posted
            Semaphore_pend(rxEventSem, BIOS_WAIT_FOREVER);
    
    
        }
    }
    
    
    /* Pin interrupt Callback function board buttons configured in the pinTable. */
    void buttonCallbackFunction(PIN_Handle handle, PIN_Id pinId)
    {
        pressPin = pinId;
    
        /* Disable interrupts during debounce */
        PIN_setConfig(handle, PIN_BM_IRQ, pressPin | PIN_IRQ_DIS);
    
        Clock_setTimeout(clockHandle1,  milli_to_ticks(100));
        Clock_start(clockHandle1);
    }
    
    static void clockCallback1(UArg u0) // Debounce clock
    {
        PIN_Handle buttonHandle = (PIN_State *) u0;
    
        /* Stop the button clock */
        Clock_stop(clockHandle1);
    
        /* Check that there is active button for debounce logic*/
        if (pressPin != PIN_TERMINATE)
        {
            if(PIN_getInputValue(pressPin) == 0)    // Press
            {
    
            }
            else    // Release
            {
                        System_printf("Send ID");
                        transmitPacket = true;
            }
        }
    
        /* Re-enable interrupts to detect button release. */
        PIN_setConfig(buttonHandle, PIN_BM_IRQ, pressPin | PIN_IRQ_BOTHEDGES);
    
        /* Set activeButtonPinId to none... */
        pressPin = PIN_TERMINATE;
    }
    
    uint32_t milli_to_ticks(uint32_t milli)
    {
        return((milli * 1000) / Clock_tickPeriod);
    }
    
    /*
     *  ======== main ========
     */
    int main(void)
    {
        /* Call driver init functions. */
        Board_initGeneral();
    
        /* Open output 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");
        }
    
        /* Read MAC Address */
        macAddrLsb = HWREG(FCFG1_BASE + FCFG1_O_MAC_15_4_0);
        macAddrMsb  =HWREG(FCFG1_BASE + FCFG1_O_MAC_15_4_1);
        macAddress = (uint64_t)(macAddrMsb << 32) + macAddrLsb;
    
        /* Create packet containing MAC Address  */
        packet[0] = PAYLOAD_LENGTH;
        packet[1] = (uint8_t)((macAddress & 0xFF00000000000000UL) >> 56);
        packet[2] = (uint8_t)((macAddress & 0x00FF000000000000UL) >> 48);
        packet[3] = (uint8_t)((macAddress & 0x0000FF0000000000UL) >> 40);
        packet[4] = (uint8_t)((macAddress & 0x000000FF00000000UL) >> 32);
        packet[5] = (uint8_t)((macAddress & 0x00000000FF000000UL) >> 24);
        packet[6] = (uint8_t)((macAddress & 0x0000000000FF0000UL) >> 16);
        packet[7] = (uint8_t)((macAddress & 0x000000000000FF00UL) >> 8);
        packet[8] = (uint8_t)((macAddress & 0x00000000000000FFUL));
    
    
        /* Initialize task */
        rxTaskInit();
    
        Task_Params_init(&rxEventTaskParams);
        rxEventTaskParams.stackSize = RXEVENT_TASK_STACK_SIZE;
        rxEventTaskParams.priority = RXEVENT_TASK_PRIORITY;
        rxEventTaskParams.stack = rxEventTaskStack;
        Task_construct(&rxEventTask, rxEvent_fcn, &rxEventTaskParams, NULL);
    
        Semaphore_Params_init(&rxEventSemParams);
        rxEventSemParams.mode = Semaphore_Mode_BINARY;
        Semaphore_construct(&rxEventSemStruct, 0, &rxEventSemParams);
        rxEventSem = Semaphore_handle(&rxEventSemStruct);
    
        // Clock1: Debounce Clock for 100ms
        Clock_Params clockParams;
        Clock_Params_init(&clockParams);
        clockParams.arg = (UArg)buttonPinHandle;
        clockParams.period = 0; // this will make it one-shot (the timeout period is set in the construct or create function parameters)
        clockParams.startFlag = false;
        Clock_construct(&clockStruct1, clockCallback1, milli_to_ticks(100), &clockParams);
        clockHandle1 = Clock_handle(&clockStruct1);
    
        /* Start BIOS */
        BIOS_start();
    
        return (0);
    }
    

  • You are setting up the advanced TX function RF_cmdPropTxAdv, but are trying to run the ordinary TX function (RF_cmdPropTx). Are there any reasons for why you are setting up the advanced function or is this just copy and paste from the WOR TX example?
    The reason this example uses the advanced command is because you want to transmit a very long preamble since the receiver uses Sniff mode.
    If this is not the case for the packets you are transmitting when a button is pushed, I strongly recommend that you take a look at the rfPacketTX example instead and use that as a reference
  • Hi Siri,

    My application is as follows. I have a transmitter (Device A) and receiver (Device B) pair running the WOR RX and WOR TX examples respectively. The reason why I am using WOR is because both the Device A and Device B are running on batteries.

    I am now trying to introduce a third device (Device C) (powered by the mains). Device C is normally in RX mode, waiting for data from Device A. But there are instances where I want to switch Device B from RX to TX mode, send data to Device C (eg. when a button is pressed) and go back to RX mode again. In addition, there will also be instances where I need to set Device C from RX to TX mode, send a packet to Device B and switch back to RX mode.

    What I am trying to write now is the program for Device B. Because Device A is setup with advance TX function to work with Device B in WOR mode, Device A is also sending to Device C with long preamble. A such, I presume Device C needs to be setup in WOR RX mode too and hence Device B needs to be setup with long preamble too.

    I hope it is not confusing for you.
  • Hi

    The problem is, as I pointed out in my previous post, that you set up the advanced TX function but you use the ordinary TX function when you run the command:

    // Check if button has been pushed (set a flag in the button callback)
    if (transmitPacket)
    {
        RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    }
    transmitPacket = false;

    You need to use the advanced TX command instead:

    // Check if button has been pushed (set a flag in the button callback)
    if (transmitPacket)
    {
        RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTxAdv, RF_PriorityNormal, NULL, 0);
    }
    transmitPacket = false;

    BR

    Siri