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.

CC2640R2F: How to run BLE advertisements with custom frequency?

Part Number: CC2640R2F

Hi team,

My customer need assistance.

In the chip documentation it states that you can set the radio frequency with a CMD_FS command and then you can send BLE advertisements the frequency field set to 255 in order to use the frequency that you set with the CMD_FS command. However, I've been having trouble getting this to work. I've been able to start advertising on a specific channel solely through the BLE advertisement command "rfc_bleAdvPar_t", and if I then go to change the radio frequency manually with CMD_FS I get a success status code but the radio stops working entirely (I have confirmed this with a spectrum analyzer). I have tried this with frequencies equal to the 3 different BLE advertisement channels as well. Am I issuing these commands incorrectly? Thank you for the help, I've attach my code which recreates this problem.

1033.rfPacketTx.c
/***** Includes *****/
/* Standard C Libraries */
#include <stdlib.h>
#include <unistd.h>

/* TI Drivers */
#include <ti/drivers/rf/RF.h>
#include <ti/drivers/PIN.h>
#include <ti/drivers/pin/PINCC26XX.h>

/* Driverlib Header files */
//#include DeviceFamily_constructPath(driverlib/rf_prop_mailbox.h)
#include DeviceFamily_constructPath(driverlib/rf_ble_mailbox.h)

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

/***** Defines *****/

/* Packet TX Configuration */
#define PAYLOAD_LENGTH      6
//#define PACKET_INTERVAL     500000  /* Set packet interval to 500000us or 500ms */
#define PACKET_INTERVAL     50000 // us -> 50ms

/***** Prototypes *****/

/***** Variable declarations *****/
static RF_Object rfObject;
static RF_Handle rfHandle;

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

static uint8_t packet[PAYLOAD_LENGTH] = {0x00, 0xDE, 0xAD, 0xBE, 0xEF};

rfc_bleAdvOutput_t BLE_output = {0};
extern rfc_bleAdvPar_t bleAdvPar;
/*
 * Application LED pin configuration table:
 *   - All LEDs board LEDs are off.
 */
PIN_Config pinTable[] =
{
    Board_PIN_LED1 | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,
    PIN_TERMINATE
};

/***** Function definitions *****/
int64_t count = 0;
void *mainThread(void *arg0)
{
    RF_Params rfParams;
    RF_Params_init(&rfParams);

    /* Open LED pins */
    ledPinHandle = PIN_open(&ledPinState, pinTable);
    if (ledPinHandle == NULL)
    {
        while(1);
    }

    bleAdvPar.advLen   = PAYLOAD_LENGTH;
    bleAdvPar.pAdvData = packet;
    bleAdvPar.scanRspLen = PAYLOAD_LENGTH;
    bleAdvPar.pScanRspData = packet; 
    RF_cmdBle5GenericTx.pOutput = &BLE_output;

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

    /* Set the frequency */
    RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
   
    uint32_t cmdStatus = ((volatile RF_Op*)&RF_cmdFs)->status;
    // Setup BLE

    while(1)
    {
        /* Send packet */
        RF_EventMask terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdBle5GenericTx,
                                                    RF_PriorityNormal, NULL, 0);
        switch(terminationReason)
        {
            case RF_EventLastCmdDone:
                // A stand-alone radio operation command or the last radio
                // operation command in a chain finished.
                break;
            case RF_EventCmdCancelled:
                // Command cancelled before it was started; it can be caused
                // by RF_cancelCmd() or RF_flushCmd().
                break;
            case RF_EventCmdAborted:
                // Abrupt command termination caused by RF_cancelCmd() or
                // RF_flushCmd().
                break;
            case RF_EventCmdStopped:
                // Graceful command termination caused by RF_cancelCmd() or
                // RF_flushCmd().
                break;
            default:
                // Uncaught error event
                while(1);
        }

        uint32_t cmdStatus = ((volatile RF_Op*)&RF_cmdBle5GenericTx)->status;
        switch(cmdStatus)
        {
            case BLE_DONE_OK:
                // Operation ended normally
                break;
            case BLE_DONE_CONNECT:
                // CONNECT_IND or AUX_CONNECT_RSP received or transmitted
                break;
            case BLE_ERROR_PAR:
                // Illegal parameter
                break;
            case BLE_ERROR_NO_SETUP:
                // Operation using Rx or Tx attemted when not in BLE mode
                break;
            case BLE_ERROR_NO_FS:
                // Operation using Rx or Tx attemted without frequency synth configured
                break;
            default:
                // Uncaught error event - these could come from the
                // pool of states defined in rf_mailbox.h
                while(1);
        }


        PIN_setOutputValue(ledPinHandle, Board_PIN_LED1,!PIN_getOutputValue(Board_PIN_LED1));

        /* Sleep for PACKET_INTERVAL us */
        usleep(PACKET_INTERVAL);

        //count++;
        //if (count == 21){
        //    //RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        //    //RF_runCmd(rfHandle, (RF_Op*)&RF_cmdFs, RF_PriorityNormal, NULL, 0);
        //    /* Send packet */
        //    RF_cmdBle5GenericTx.channel = 255;
        //}
    }
}

8741.smartrf_settings.c
//*********************************************************************************
// Generated by SmartRF Studio version 2.28.0 (build#364)
// The applied template is compatible with CC2640R2 SDK version 1.50.xx.xx or newer.
// Device: CC2640R2F Rev. F (2.5). 
//
//*********************************************************************************


//*********************************************************************************
// Parameter summary
// Adv. Address: 010203040506 
// Adv. Data: 255 
// BLE Channel: 17 
// Extended Header: 09 09 010203040506 babe 
// Frequency: 2440.005 MHz
// PDU Payload length: 13 
// TX Power: 2 dBm 
// Whitening: true 

#include "smartrf_settings.h"

#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_bt5.h)

// TI-RTOS RF Mode Object
RF_Mode RF_ble =
{
    .rfMode = RF_MODE_BLE,
    .cpePatchFxn = &rf_patch_cpe_bt5,
    .mcePatchFxn = 0,
    .rfePatchFxn = 0
};


// Overrides for CMD_BLE5_RADIO_SETUP
uint32_t pOverridesCommon[] =
{
    // override_ble5_setup_override_common.xml
    // Rx: Set LNA IB trim value based on the selected defaultPhy.mainMode setting. (NOTE: The value 0x8 is a placeholder. The value to use should be set during run-time by radio driver function.)
    ADI_HALFREG_OVERRIDE(0,4,0xF,0x8),
    // Rx: Set LNA IB offset used for automatic software compensation to 0
    (uint32_t)0x00008883,
    // Synth: Use 24 MHz crystal, enable extra PLL filtering
    (uint32_t)0x02010403,
    // Synth: Set fine top and bottom code to 127 and 0
    HW_REG_OVERRIDE(0x4020, 0x7F00),
    // Synth: Configure faster calibration
    HW32_ARRAY_OVERRIDE(0x4004, 1),
    // Synth: Configure faster calibration
    (uint32_t)0x1C0C0618,
    // Synth: Configure faster calibration
    (uint32_t)0xC00401A1,
    // Synth: Configure faster calibration
    (uint32_t)0x21010101,
    // Synth: Configure faster calibration
    (uint32_t)0xC0040141,
    // Synth: Configure faster calibration
    (uint32_t)0x00214AD3,
    // Synth: Decrease synth programming time-out by 64 us (0x0300 RAT ticks = 192 us)
    (uint32_t)0x03000243,
    // Bluetooth 5: Set correct total clock accuracy for received AuxPtr assuming local sleep clock of 50 ppm
    (uint32_t)0x0E490823,
    // override_frontend_xs_rfn.xml
    // Rx: Set RSSI offset to adjust reported RSSI by -2 dB
    (uint32_t)0x000288A3,
    (uint32_t)0xFFFFFFFF
};


// Overrides for CMD_BLE5_RADIO_SETUP
uint32_t pOverrides1Mbps[] =
{
    // override_ble5_setup_override_1mbps.xml
    // Rx: Set LNA IB trim to normal trim value. (NOTE: The value 0x8 is a placeholder. The value to use should be set during run-time by radio driver function.)
    ADI_HALFREG_OVERRIDE(0,4,0xF,0x8),
    // Rx: Configure AGC to use gain table for improved performance
    HW_REG_OVERRIDE(0x6084, 0x05F8),
    (uint32_t)0xFFFFFFFF
};


// Overrides for CMD_BLE5_RADIO_SETUP
uint32_t pOverrides2Mbps[] =
{
    // override_ble5_setup_override_2mbps.xml
    // Rx: Set LNA IB trim to normal trim value. (NOTE: The value 0x8 is a placeholder. The value to use should be set during run-time by radio driver function.)
    ADI_HALFREG_OVERRIDE(0,4,0xF,0x8),
    (uint32_t)0xFFFFFFFF
};


// Overrides for CMD_BLE5_RADIO_SETUP
uint32_t pOverridesCoded[] =
{
    // override_ble5_setup_override_coded.xml
    // Rx: Set LNA IB trim to 0xF (maximum)
    ADI_HALFREG_OVERRIDE(0,4,0xF,0xF),
    // Rx: Override AGC target gain to improve performance
    HW_REG_OVERRIDE(0x6088, 0x001B),
    (uint32_t)0xFFFFFFFF
};


// CMD_BLE5_RADIO_SETUP
// Bluetooth 5 Radio Setup Command for all PHYs
rfc_CMD_BLE5_RADIO_SETUP_t RF_cmdBle5RadioSetup =
{
    .commandNo = 0x1820,
    .status = 0x0000,
    .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    .startTime = 0x00000000,
    .startTrigger.triggerType = 0x0,
    .startTrigger.bEnaCmd = 0x0,
    .startTrigger.triggerNo = 0x0,
    .startTrigger.pastTrig = 0x0,
    .condition.rule = 0x1,
    .condition.nSkip = 0x0,
    .defaultPhy.mainMode = 0x1,
    .defaultPhy.coding = 0x0,
    .__dummy0 = 0x00,
    .config.frontEndMode = 0x0, //0x2
    .config.biasMode = 0x1,
    .config.analogCfgMode = 0x0,
    .config.bNoFsPowerUp = 0x0,
    .txPower = 0x7217, // Turn up power?
    .pRegOverrideCommon = pOverridesCommon,
    .pRegOverride1Mbps = pOverrides1Mbps,
    .pRegOverride2Mbps = pOverrides2Mbps,
    .pRegOverrideCoded = pOverridesCoded
};


// CMD_FS
// Frequency Synthesizer Programming Command
rfc_CMD_FS_t RF_cmdFs =
{
    .commandNo = 0x0803,
    .status = 0x0000,
    .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    .startTime = 0x00000000,
    .startTrigger.triggerType = 0x0,
    .startTrigger.bEnaCmd = 0x0,
    .startTrigger.triggerNo = 0x0,
    .startTrigger.pastTrig = 0x0,
    .condition.rule = 0x1,
    .condition.nSkip = 0x0,
    .frequency = 2480,//0x0962,
    .fractFreq = 0x0000, //0x0147,
    .synthConf.bTxMode = 0x0, // Tx mode?
    .synthConf.refFreq = 0x0,
    .__dummy0 = 0x00,
    .__dummy1 = 0x00,
    .__dummy2 = 0x00,
    .__dummy3 = 0x0000
};

static uint64_t devAddress = { 0xEEEEEEEEEEEE };

// Structure for CMD_BLE_ADV_NC.pParams
rfc_bleAdvPar_t bleAdvPar =
{
    .pRxQ = 0, // INSERT APPLICABLE POINTER: (dataQueue_t*)&xxx
    .rxConfig.bAutoFlushIgnored = 0x0,
    .rxConfig.bAutoFlushCrcErr = 0x0,
    .rxConfig.bAutoFlushEmpty = 0x0,
    .rxConfig.bIncludeLenByte = 0x0,
    .rxConfig.bIncludeCrc = 0x0,
    .rxConfig.bAppendRssi = 0x0,
    .rxConfig.bAppendStatus = 0x0,
    .rxConfig.bAppendTimestamp = 0x0,
    .advConfig.advFilterPolicy = 0x0,
    .advConfig.deviceAddrType = 0x0,
    .advConfig.peerAddrType = 0x0,
    .advConfig.bStrictLenFilter = 0x0,
    .advConfig.chSel = 0x0,
    .advConfig.privIgnMode = 0x0,
    .advConfig.rpaMode = 0x0,
    .advLen = 0x07,
    .scanRspLen = 0x00,
    .pAdvData = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    .pScanRspData = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
    .pDeviceAddress = (uint16_t*) &devAddress, // INSERT APPLICABLE POINTER: (uint16_t*)&xxx
    .pWhiteList = 0, // INSERT APPLICABLE POINTER: (uint32_t*)&xxx
    .__dummy0 = 0x0000,
    .__dummy1 = 0x00,
    .endTrigger.triggerType = 0x1,
    .endTrigger.bEnaCmd = 0x0,
    .endTrigger.triggerNo = 0x0,
    .endTrigger.pastTrig = 0x0,
    .endTime = 0x00000000
};

rfc_CMD_BLE5_ADV_NC_t RF_cmdBle5GenericTx = 
{
    .commandNo = 0x182D,
    .status    = 0x0000,                                                    
    .pNextOp   = 0,
    .startTime = 0x00000000,
    .startTrigger.triggerType = 0x0,
    .startTrigger.bEnaCmd = 0x0,
    .startTrigger.triggerNo = 0x0,
    .startTrigger.pastTrig = 0x0,
    .condition.rule = 0x1,
    .condition.nSkip = 0x0,
    .channel = 255,//255, // use existing frequency 37
    .whitening = 0,
    //.whitening.init = 0x51,
    //.whitening.bOverride = 0x1,
    .phyMode.mainMode = 0x0,
    .phyMode.coding = 0x0,
    .rangeDelay = 0x00,
    .txPower = 0x9330,                                
    .pParams = &bleAdvPar, 
    .pOutput = 0,
};

6014.smartrf_settings.h

Could you help look into it? Thank you for your help.

  • Hi Chong,

    There appear to be some files missing in your original post.  From the rfPacketTx.c application which is available, there is a bleAdvPar structure which is unused.  Otherwise, radio issues can be expected if the original RF session is not closed and further is not given for the frequency synthesizer to finalize changes.  You should be using RF_yield to resolve the current issue.  Here is a relevant E2E post with proposed switching method: https://e2e.ti.com/f/1/t/1124734 

    Regards,
    Ryan

  • Hi Ryan,

    I got the response from customer:

    To clarify, the main goal we are trying to achieve is setting up BLE advertisements on a custom frequency; we tried to switch the frequency while running to test if we were setting the frequency correctly. Ideally we would like to set up the radio for BLE advertisements on a custom frequency when initializing the radio at the beginning. I have tried the following to set the frequency to 2402 (advertisement channel 37) and I am getting successful status codes, but the frequency has still not been set:
    /* Request access to the radio */
    rfHandle = RF_open(& rfObject, & RF_ble, (RF_RadioSetup*)& RF_cmdBle5RadioSetup, & rfParams);
    RF_cmdFs. frequency = 2402;
    RF_cmdBle5GenericTx. channel = 255; // Use existing frequency
    RF_postCmd( rfHandle, (RF_Op*)& RF_cmdFs, RF_PriorityNormal, NULL, 0);
    RF_yield( rfHandle);
    The rest of the code after this snippet is the same in rfPacketTx.c in which I call RF_cmdBle5GenericTx in a loop. Is there something else I'm missing?
    Thank you for the help.
  • This is likely caused by invalid Smart RF settings.  Please have the customer re-evaluate the default rfPacketTx example by communicating with a second device connected to the Smart RF Studio Packet RX mode.  They should export any Smart RF packet changes they make and directly apply them to their rfPacketTx project to confirm that communication is still possible.  There is a SimpleLink Academy Lab which helps in this regard.  After confirming operation with these modifications they can further evaluate changing channels without setting the variable to 255.

    Regards,
    Ryan

  • Hi Ryan,

    I got the response from customer:

    Our goal is to run BLE advertisements at a specific frequency and we want to use the CMD_FS command in order to set a particular fractional frequency (ex, 2480.0005 MHz). The BLE advertisement commands don't allow us to set a fractional frequency so we modified the rfPacketTx example in order to try to set the BLE advertisement frequency manually with a CMD_FS and then running advertisement commands with the channel field set to 255 in order to use the frequency we set with CMD_FS. Is it not possible to run BLE advertisements this way?

  • They should be using the advertising channels 37 (2402 MHz), 38 (2426 MHz), and 39 (2480 MHz).  They can view how the frequency, channel, and whitening parameters are changed accordingly by reviewing the Command View from Smart RF Studio 7.

    Regards,
    Ryan

  • Hi Ryan,

    I got the response from customer:

    For our system design we want to analyze the impact of fractional offsets in LO frequency (impact of CFO). We are tuning to the advertisement channels but we want to be able to tune the LO to fractional frequencies and analyze how the advertisements are impacted (packet error rate, etc). So for example, I want to send an advertisement at 2.4265 GHz instead of at 2.426 GHz. Can you please tell us how to do that?

    Best,
    Alexander
  • In this scenario, you would keep the frequency, channel, and whitening for channel 38 but modify the fractFreq parameter of the CMD_FS accordingly, in this case setting to 0x8000 could produce the desired effect.  They should further investigate use of SmartRF Studio to analyze their configuration, then migrate changes to the Proprietary RF example accordingly.

    Regards,
    Ryan