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.

CC2652R: Transmit BLE iBeacon packet with rfPacketTx app

Part Number: CC2652R
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hello,

For internal tests I would need to send valid BLE iBeacon packets using RF Core Driver, without BLE stack. I've looked at configuring rfPacketTx in sys cfg to transmit in Custom BLE, 1 Mbps, BT4. I'd need an example of how to configure the app and build a BLE packet so it would be picked up by a BLE central scanner.

Thank you,

Igor

  • Hello Igor,

    Besides the necessary SysConfig change, I have attached simple modifications to the rfPacketTx.c file so that it sends BLE non-connectable advertisements.  Please note that none of the comments have been changed accordingly.  I have validated reception of these packets inside of Smart RF Studio, please determine whether this will suit your application as well.  You can also reference the rflib API documentation if further modifications are required.

    /*
     * Copyright (c) 2019, 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 *****/
    /* Standard C Libraries */
    #include <stdlib.h>
    #include <unistd.h>
    
    /* TI Drivers */
    #include <ti/drivers/rf/RF.h>
    #include <ti/drivers/GPIO.h>
    //#include <ti/drivers/pin/PINCC26XX.h>
    
    /* Driverlib Header files */
    #include DeviceFamily_constructPath(driverlib/rf_ble_mailbox.h)
    
    /* Board Header files */
    #include "ti_drivers_config.h"
    #include <ti_radio_config.h>
    
    /***** Defines *****/
    
    /* Do power measurement */
    //#define POWER_MEASUREMENT
    
    /* Packet TX Configuration */
    #define PAYLOAD_LENGTH      30
    #ifdef POWER_MEASUREMENT
    #define PACKET_INTERVAL     5  /* For power measurement set packet interval to 5s */
    #else
    #define PACKET_INTERVAL     500000  /* Set packet interval to 500000us or 500ms */
    #endif
    
    /***** Prototypes *****/
    
    /***** Variable declarations *****/
    static RF_Object rfObject;
    static RF_Handle rfHandle;
    
    static uint8_t packet[PAYLOAD_LENGTH];
    static uint16_t seqNumber;
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfig(CONFIG_GPIO_GLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        GPIO_write(CONFIG_GPIO_GLED, CONFIG_GPIO_LED_OFF);
    
        RF_cmdBleAdvNc_bt5le1madvnc_0.pParams->advLen = PAYLOAD_LENGTH;
        RF_cmdBleAdvNc_bt5le1madvnc_0.pParams->pAdvData = packet;
        RF_cmdBleAdvNc_bt5le1madvnc_0.startTrigger.triggerType = TRIG_NOW;
    
        /* Request access to the radio */
    #if defined(DeviceFamily_CC26X0R2)
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams);
    #else
        rfHandle = RF_open(&rfObject, &RF_prop_bt5le1madvnc_0, (RF_RadioSetup*)&RF_cmdBle5RadioSetup_bt5le1madvnc_0, &rfParams);
    #endif// DeviceFamily_CC26X0R2
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs_bt5le1madvnc_0, RF_PriorityNormal, NULL, 0);
    
        while(1)
        {
            /* Create packet with incrementing sequence number and random payload */
            packet[0] = (uint8_t)(seqNumber >> 8);
            packet[1] = (uint8_t)(seqNumber++);
            uint8_t i;
            for (i = 2; i < PAYLOAD_LENGTH; i++)
            {
                packet[i] = rand();
            }
    
            /* Send packet */
            RF_EventMask terminationReason = RF_EventCmdAborted | RF_EventCmdPreempted;
            while(( terminationReason & RF_EventCmdAborted ) && ( terminationReason & RF_EventCmdPreempted ))
            {
                // Re-run if command was aborted due to SW TCXO compensation
                terminationReason = RF_runCmd(rfHandle, (RF_Op*)&RF_cmdBleAdvNc_bt5le1madvnc_0,
                                              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_cmdBleAdvNc_bt5le1madvnc_0)->status;
            switch(cmdStatus)
            {
                case BLE_DONE_OK:
                    // Packet transmitted successfully
                    break;
                case BLE_DONE_STOPPED:
                    // received CMD_STOP while transmitting packet and finished
                    // transmitting packet
                    break;
                case BLE_DONE_ABORT:
                    // Received CMD_ABORT while transmitting packet
                    break;
                case BLE_ERROR_PAR:
                    // Observed illegal parameter
                    break;
                case BLE_ERROR_NO_SETUP:
                    // Command sent without setting up the radio in a supported
                    // mode using CMD_PROP_RADIO_SETUP or CMD_RADIO_SETUP
                    break;
                case BLE_ERROR_NO_FS:
                    // Command sent without the synthesizer being programmed
                    break;
                case BLE_ERROR_TXUNF:
                    // TX underflow observed during operation
                    break;
                default:
                    // Uncaught error event - these could come from the
                    // pool of states defined in rf_mailbox.h
                    while(1);
            }
    
    #ifndef POWER_MEASUREMENT
            GPIO_toggle(CONFIG_GPIO_GLED);
    #endif
            /* Power down the radio */
            RF_yield(rfHandle);
    
    #ifdef POWER_MEASUREMENT
            /* Sleep for PACKET_INTERVAL s */
            sleep(PACKET_INTERVAL);
    #else
            /* Sleep for PACKET_INTERVAL us */
            usleep(PACKET_INTERVAL);
    #endif
    
        }
    }
    

    Regards,
    Ryan

  • Hello Ryan,

    Thank you for the sample code. I've run this and I see the data in SmartRF Studio if transmitting on data channel 17. If I change to an advertisement channel,  the payload is not seen by a regular BLE scanner. I've attached the screenshot from SysConfig.

    Thank you,

    Igor

  • Hi Igor,

    Understood. Can you describe your scanner setup? Are you only sending a single packet or continuously sending packets? If you are using a smart phone scanner, then its possible the app may not report a single advertisement and multiple are needed.

    Best Regards,

    Jan

  • Hello Jan,

    I use Silabs Bluetooth NCP Commander for scanning, with a Silabs MG21 dev kit. The scanner set to observation mode, in continuous scanning mode. The GUI collects and displays all advertisements that are picked up even once and updates the ones already discovered. To avoid the chance of missing rfPacketTx packets, I've set the delay to 100ms.

    Attached screenshots from smartrf studio with channel 17 (when it picks up data), channel 37 (custom packets are not picked up), and a view of NCP Commander.

    Thank you,

    Igor

  • Hi,

    Got it. Thank you for the in-depth analysis! Can you confirm that the CC2652 is actually transmitting? You can verify this by checking the power draw or connecting the RF output to a spectrum analyzer.

    Best Regards,

    Jan

  • hi Jan,

    I use as a confirmation for myself the led toggling of the LaunchPad and that it's not crashed or stuck in debugger. Unfortunately, I don't have means of checking the power draw or using a spectrum analyzer. 

    But I agree, it might not transmit when channel is changed, but behave as it would. I'll try to instrument the switch statements in the code and see if any errors occur.

    Thank you,

    Igor

  • Hi Igor,

    Sounds good! Let us know once you had a chance to make the modifications and re-test.

    Best Regards,

    Jan

  • hi Jan,

    I've added while(1) in all error cases, and the code is running. I suppose it is transmitting.

    .

            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().
                    while(1);
                    break;
                case RF_EventCmdAborted:
                    // Abrupt command termination caused by RF_cancelCmd() or
                    // RF_flushCmd().
                    while(1);
                    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_cmdBleAdvNc_bt5le1madvnc_1)->status;
            switch(cmdStatus)
            {
                case BLE_DONE_OK:
                    // Packet transmitted successfully
                    break;
                case BLE_DONE_STOPPED:
                    // received CMD_STOP while transmitting packet and finished
                    // transmitting packet
                    break;
                case BLE_DONE_ABORT:
                    // Received CMD_ABORT while transmitting packet
                    while(1);
                    break;
                case BLE_ERROR_PAR:
                    // Observed illegal parameter
                    while(1);
                    break;
                case BLE_ERROR_NO_SETUP:
                    // Command sent without setting up the radio in a supported
                    // mode using CMD_PROP_RADIO_SETUP or CMD_RADIO_SETUP
                    while(1);
                    break;
                case BLE_ERROR_NO_FS:
                    // Command sent without the synthesizer being programmed
                    while(1);
                    break;
                case BLE_ERROR_TXUNF:
                    // TX underflow observed during operation
                    while(1);
                    break;
                default:
                    // Uncaught error event - these could come from the
                    // pool of states defined in rf_mailbox.h
                    while(1);
            }

  • Thanks Igor,

    I am also observing wakeups every 500 ms as expected and a current profile which indicates radio transmissions

    Jan and I will try to further evaluate whether radio packets are being sent out at the expected frequency.

    Regards,
    Ryan

  • hi Ryan and Jen, thank you for your support. Looking forward to learn about your findings.

  • Hi Igor,

    Just wanted to provide a quick update. We reproduced the behavior you are reporting on our side. Advertising on channel 17 works fine but other channels seems to not be picked up by the smartrf receiver. We will continue looking into this and provide an update as soon as possible.

    Best Regards,

    Jan

  • Hi Jan,

    I compared BLE command parameters between rfPacketTx SysConfig's ti_radio_config.c generated file and the Smart RF Studio 7 settings, at which point I discovered that ti_radio_config.c is maintaining the same rfc_CMD_BLE_ADV_NC_t whitening.init value whereas Smart RF Studio 7 changes this value per channel.

    I copied the Debug/syscfg/ti_radio_config.c file into rfPacketTx's main directory, excluded ti_radio_config.c from building in the SysConfig Editor ("Show Generated Files" View), and manually edited the value of whitening.init to reflect the value shown in the same channel for Smart RF Studio 7.  After re-building and running rfPacketTx, I found that at least channel 18 was working whereas it hadn't before.  Thus this would appear to be a Prop RF SysConfig bug.

    For advertising channel 37, I noticed that rfc_CMD_BLE_ADV_NC_t channel value differs between the generated ti_radio_config.c and Smart RF Studio 7 settings.  Therefore you may need to change this value as well.  You can either use the steps I outlined above or implement changes in the rfPacketTx.c file

    // PSEUDO-CODE FOR ADVERTISING CHANNEL 37
    
    RF_cmdBleAdvNc_bt5le1madvnc_0.channel = 0x25;
    RF_cmdBleAdvNc_bt5le1madvnc_0.whitening.init = 0x65;
    RF_cmdBleAdvNc_bt5le1madvnc_0.whitening.bOverride = 1;
    
    RF_cmdFs_bt5le1madvnc_0.frequency = 0x0962;

    Regards,
    Ryan

  • Hi Ryan,

    Thanks for the update! I've applied your changes in code, and I can see the advertisement from rfPacketTx in SmartRF studio, as in screenshot below (Mac filled with 0x66, payload with 0xCC). But, my ble scanner still does not pick up these advertisements. Verified with a Nordic sniffer + Wireshark, still the advertisement is not picked up. Am I missing something in the cofiguration?

    Thank you,

    Igor

  • Hi Ryan,

    I have another update. It seems that the advertisement are trickling down and it is transmitting.

    Not sure why not all advertisements are picked up (added a sequence number at the end of payload, the code is below). I'm not expecting 100% of advs to be picked up, but there are quite a lot of gaps. Attached screenshot from Wireshark. The last column, Data, is the sequence number.

    Thank you,

    Igor

    static uint8_t packet[] = { 0x02, 0x01, 0x06,
                                0x06, 0x08, 0x54, 0x49, 0x53, 0x49, 0x4D,
                                0x04, 0xFF, 0xCC, 0xCC, 0x00};
    static uint16_t seqNumber;
    static uint16_t baddr[3] = {0x6666, 0x6666, 0x6666};
    
    /***** Function definitions *****/
    
    void *mainThread(void *arg0)
    {
        RF_Params rfParams;
        RF_Params_init(&rfParams);
    
        GPIO_setConfig(CONFIG_GPIO_GLED, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
    
        GPIO_write(CONFIG_GPIO_GLED, CONFIG_GPIO_LED_OFF);
    
        RF_cmdBleAdvNc_bt5le1madvnc_1.pParams->advLen = sizeof(packet);
        RF_cmdBleAdvNc_bt5le1madvnc_1.pParams->pAdvData = packet;
        RF_cmdBleAdvNc_bt5le1madvnc_1.pParams->pDeviceAddress = baddr;
        //RF_cmdBleAdvNc_bt5le1madvnc_1.channel = 17;
        RF_cmdBleAdvNc_bt5le1madvnc_1.startTrigger.triggerType = TRIG_NOW;
    
        RF_cmdBleAdvNc_bt5le1madvnc_1.channel = 0x25;
        RF_cmdBleAdvNc_bt5le1madvnc_1.whitening.init = 0x65;
        RF_cmdBleAdvNc_bt5le1madvnc_1.whitening.bOverride = 1;
    
        RF_cmdFs_bt5le1madvnc_1.frequency = 0x0962;
    
        /* Request access to the radio */
    #if defined(DeviceFamily_CC26X0R2)
        rfHandle = RF_open(&rfObject, &RF_prop, (RF_RadioSetup*)&RF_cmdPropRadioSetup, &rfParams);
    #else
        rfHandle = RF_open(&rfObject, &RF_prop_bt5le1madvnc_1, (RF_RadioSetup*)&RF_cmdBle5RadioSetup_bt5le1madvnc_1, &rfParams);
    #endif// DeviceFamily_CC26X0R2
    
        /* Set the frequency */
        RF_postCmd(rfHandle, (RF_Op*)&RF_cmdFs_bt5le1madvnc_1, RF_PriorityNormal, NULL, 0);
    
        while(1)
        {
            /* Create packet with incrementing sequence number and random payload */
            packet[sizeof(packet) - 1] = seqNumber++;
    
            /* Send packet */
            RF_EventMask terminationReason = RF_EventCmdAborted | RF_EventCmdPreempted;

  • hi Ryan, it seems that the advertisements on channel 37 are picked up fine. I wasn't testing this properly.

    I've tried to change configuration to transmit on other advertisement channels, but then I cannot receive the advertisements. I've made these changes in my code for channel 39:

        RF_cmdBleAdvNc_bt5le1madvnc_1.channel = 0x27;
        RF_cmdFs_bt5le1madvnc_1.frequency = 2480;

    I don't see the advertisements in neither regular scanner nor smart studio.

    Thanks, Igor

  • Hi Igor,

    Glad you were able to see the advertisements on channel 37! Regarding channel 38, did you copy/paste the RF configuration generated by smartRF as well?

    Best Regards,

    Jan

  • Hi Jan, Ryan,

    I managed to extract frequency settings from SmartRF studio for channel 39, and I can see the advertisements. I think my question is solved now. 

    Thank you for your help!

    Igor