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.

CC1310: We are using frequency hopping and want to know how to determine when the frequency change is complete.

Part Number: CC1310

We are testing a custom frequency hopping technique and are using these commands to change the Tx frequency before sending out a packet. As a test, we run the system with 24 transmits at 923 MHz and then switch to 907 before transmitting another packet. When we have no Task_sleep() after the call to set the frequency, the frequency actually transmits at a different frequency, not 907. Adding just 10 mS seems to be enough time for the CC1310 receiver to get the full packet and respond. So I am assuming it takes some time for the transmitter CPU to change the frequency.

My question: Is there a way to determine when the frequency change is complete (frequency has stabilized)? For example, is there a function call or a register that can be read to determine when it is safe to send the packet?

RF_cmdFs.frequency=907;
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, &callback, 0);//Set frequency
Task_sleep(SLEEP_FOR_10MS);
RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTxAdv, RF_PriorityNormal, NULL, 0); //Send a packet

  • When you are changing the frequency from 923 to 907 you will need to run a new setup command also (with a new value for centerFreq).

    To make sure that the new setup command is run, you need to make sure that the RF Core is powered off between the two frequencies

    I tested the code below, and with this one it takes around 1.5 ms to change frequency (du to having to power off and on the RF Core to force a new setup:

    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    
    while(1)
    {
        RF_cmdFs.frequency = 907;
        RF_cmdPropRadioDivSetup.centerFreq = 907;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    
        RF_yield(rfHandle);// Power down the RF Core to force a new setup command after it wakes up
    
        RF_cmdFs.frequency = 923;
        RF_cmdPropRadioDivSetup.centerFreq = 923;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    
        RF_yield(rfHandle); // Power down the RF Core to force a new setup command after it wakes up
    }

    Siri

  • Thank you for the reply. I was powering down the RF core prior to the change but I was not changing the center frequency. I will add that even though all seems to be working to see if it works better. I did find that all I needed was a 2mS wait and it seems to work but I wanted to know if there was a confirmation of the change. From your response I take it that there is no confirmation method, I just need to wait 1.5mS.

    I am also changing the fractional frequency during this time (RF_cmdFs.fractFreq). Is it OK to just that variable when I change RF_cmdPropRadioDivSetup.centerFreq and RF_cmdFs.frequency or is there another variable that must change when I change RF_cmdFs.fractFreq?

    Finally, I noticed something else here and in an earlier experiment: After my HUB receives the sensor's transmission, I change the frequency on both units and send an ACK. Since I do the changes on both units after the transmission is complete, both units are now synchronized in time. I found when that happens, I seem to miss the first ACK. I thought if I added a delay in the receiver until after the transmission started, I would get better results but I did not, the receive never got the first ACK. When I added a 10mS delay to the transmitter, the receiver, who is already listening, always got the first ACK. Does that seem reasonable? The WOR example only shows a one way communication, there is no guide on when or how an reverse message should be sent. It seems like the units work best if the listen and talk are not synchronized and the receiver should be turned on before the transmitter. Would you agree?

  • I do not understand your comment that you have to wait anywhere in the code.

    When the RF Core is powered off (is it is when you do the RF_yield), it will not be turned on again before you say that you want to do something (post the FS command before you run the TX command). From then, it takes around 1.5 ms to turn on the crystal, power up the RF core, do the calibration of the synth etc.

    If you implement a wait for 2 ms and then post the FS command, it will take 2 + 1.5 ms = 3.5 ms before the packet is sent.

    Just add the change to fractFreq to where you change the frequency and centerFreq. No other changes necessary.

    I did a test and did not have to add any delays anywhere to get some kind of ping-pong code up and running.

    Code is shown below, together with the LNA and PA signals for both devices showing when they are in RX and TX.

    However, remember that it is “easy” to make some kind of synchronous protocol if you are guaranteed to not losing any packets so that the units stay in sync, but your protocol needs to handle re-synchronizations etc. when packets are lost.

    You suddenly mention WOR, but not sure how you are planning to use that in your application.

    RF_cmdPropTx.pktLen = PAYLOAD_LENGTH;
    RF_cmdPropTx.pPkt = ackPacket;
    RF_cmdPropTx.startTrigger.triggerType = TRIG_NOW;
    
    /* Modify CMD_PROP_RX command for application needs */
    /* Set the Data Entity queue for received data */
    RF_cmdPropRx.pQueue = &dataQueue;
    /* Discard ignored packets from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushIgnored = 1;
    /* Discard packets with CRC error from Rx queue */
    RF_cmdPropRx.rxConf.bAutoFlushCrcErr = 1;
    /* Implement packet length filtering to avoid PROP_ERROR_RXBUF */
    RF_cmdPropRx.maxPktLen = MAX_LENGTH;
    .
    .
    /* Request access to the radio */
    rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioDivSetup, &rfParams);
    .
    .
    // Unit 1:
    while(1)
    {
        RF_cmdFs.frequency = 868;
        RF_cmdPropRadioDivSetup.centerFreq = 868;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
        RF_yield(rfHandle);// Power down the RF Core to force a new setup command after it wakes up
    
        RF_cmdFs.frequency = 923;
        RF_cmdPropRadioDivSetup.centerFreq = 923;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    
        RF_yield(rfHandle); // Power down the RF Core to force a new setup command after it wakes up
    }
    
    // Unit 2
    while(1)
    {
        RF_cmdFs.frequency = 868;
        RF_cmdPropRadioDivSetup.centerFreq = 868;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropTx, RF_PriorityNormal, NULL, 0);
    
        RF_yield(rfHandle);// Power down the RF Core to force a new setup command after it wakes up
    
        RF_cmdFs.frequency = 923;
        RF_cmdPropRadioDivSetup.centerFreq = 923;
    
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        RF_runCmd(rfHandle, (RF_Op*)&RF_cmdPropRx, RF_PriorityNormal, &callback, RF_EventRxEntryDone);
    
        RF_yield(rfHandle); // Power down the RF Core to force a new setup command after it wakes up
    }
    .
    .
    .
    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(rxPacket, packetDataPointer, (packetLength + 1));
    
            RFQueue_nextEntry();
        }
    }

    Siri