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.

LP-EM-CC2745R10-Q1: changing TX power during runtime

Part Number: LP-EM-CC2745R10-Q1
Other Parts Discussed in Thread: SYSCONFIG

Tool/software:

Hi all,

I am testing basic BLE project using simplelink_lowpower_f3_sdk_8_40_00_61 on the cc2745 Launchpad.

I am attempting to modify the TX power during runtime by utilizing the HCI_EXT_SetTxPowerDbmCmd() function.

I have updated the TX power settings in SysConfig as shown below:

Additionally, I am using characteristic 1 of the Simple GATT Service in the Basic BLE project to send commands to change the TX power value during runtime. Below are my code snippets:

/********* changes in app_simple_gatt.c file*******************/
static void SimpleGatt_changeCB( uint8_t paramId )
{
  int8_t newValue = 0;

  switch( paramId )
  {
    case SIMPLEGATTPROFILE_CHAR1:
      {
        SimpleGattProfile_getParameter( SIMPLEGATTPROFILE_CHAR1, &newValue );

        // Print the new value of char 1
        MenuModule_printf(APP_MENU_PROFILE_STATUS_LINE, 0, "Profile status: Simple profile - "
                          "Char 1 value = " MENU_MODULE_COLOR_YELLOW "%d " MENU_MODULE_COLOR_RESET,
                          newValue);
        if((newValue<=10) & (newValue>=-10))
        {
          set_txpower=1;
          txpower_value=newValue;
          
        }
      
      }
      break;
      //.................//
      }
    /*************** app_simple_gatt.c*************/
    
    /*************** custom task created to change tx power value*************/
    void *SystemThread(void *arg0)
{
    /* 1 second delay */
    uint32_t time = 1;
    // so that the application can send and receive messages.
    ICall_registerApp(&selfEntityloc_sys, &syncEventloc_sys);

    /* Call driver init functions */
    GPIO_init();
    // I2C_init();
    // SPI_init();
    // Watchdog_init();

    while (1)
    {
        sleep(time);
        GPIO_toggle(CONFIG_GPIO_LED_RED);
        if(set_txpower)
        {
            set_txpower=0;//clear tx power flag
            GAP_TerminateLinkReq(0, HCI_DISCONNECT_REMOTE_USER_TERM); //terminate connection
            usleep(100000);
            stop_adv(); //stop adv
            usleep(100000);
            HCI_EXT_SetTxPowerDbmCmd(txpower_value,0); //change tx power
            MenuModule_printf(9, 0,"tx power changed to %d",txpower_value);
            start_adv(); //start adv
        }
    }
}

But I am not able change the TX power using above code.

Please provide me the solution to resolve this issue.

Regards,

Aslam

  • Hello,

    BLE functions need to be called within the context of the BLEAppUtil thread. You may need to use BLEAppUtil_invokeFunction so that the change takes effect.

    Please see common/BLEAppUtil/inc/bleapputil_api.h in your project.

    Please try this and let me know.

    Best,

    Nima Behmanesh

  • Hello Nima,

    Thanks for your suggestion.

    I have modified the code as per your suggestion. Below is the code snippet:

    /****************custom task***************/
    void *SystemThread(void *arg0)
    {
        /* 1 second delay */
        uint32_t time = 1;
        
        /* Call driver init functions */
        GPIO_init();
        // I2C_init();
        // SPI_init();
        // Watchdog_init();
    
        while (1)
        {
            sleep(time);
            GPIO_toggle(CONFIG_GPIO_LED_RED);
            if(set_txpower)
            {
                set_txpower=0;//clear tx power flag
                BLEAppUtil_invokeFunction(set_txpowerCB, NULL);
                
            }
        }
    }
    
    void set_txpowerCB(char *pvalue)
    {
        GAP_TerminateLinkReq(0, HCI_DISCONNECT_REMOTE_USER_TERM); //terminate connection
        usleep(100000);
        stop_adv(); //stop adv
        usleep(100000);
        HCI_EXT_SetTxPowerDbmCmd(txpower_value,0); //change tx power
        MenuModule_printf(9, 0,"tx power changed to %d",txpower_value);
        start_adv(); //start adv
    }

    But still TX power is not changing.

    If I change the TX power using sysconfig, its working. But if I use above method, its not working.

    Regards,

    Aslam

  • Hello Nima,

    Any update on above issue?

    Regards,

    Aslam

  • Hi Aslam,

    I'm going to try it on my end later today, and get back to you either later today or tomorrow.

    I apologise for the late responses!

    Best,

    Nima Behmanesh

  • Hi Aslam,

    I'll need some more time for this. I'll have an answer to you Friday.

    I apologize for the wait!

    Best,

    Nima Behmanesh

  • Hi Aslam,

    I apologize for the late response, though I was able to get it working on my side, so below are the steps.

    1. Make sure that the TX power setting in sysconfig is set to The Controller will choose the Tx Power

    You can find these settings in Broadcaster Configuration > Advertisement Set 1 > Advertisement Set Parameters 1

    2. I then create a global tx_power variable, that will be externed into the app_peripheral.c file. First, we need to add the tx_power variable into simple_gatt_profile.c and then change the value:

    uint8_t tx_power = 0; // My global variable that will be read in app_peripheral.c
    bStatus_t SimpleGattProfile_writeAttrCB( uint16_t connHandle,
                                         gattAttribute_t *pAttr,
                                         uint8_t *pValue, uint16_t len,
                                         uint16_t offset, uint8_t method )
    {
      bStatus_t status = SUCCESS;
      uint8 notifyApp = 0xFF;
    
      if ( pAttr->type.len == ATT_BT_UUID_SIZE )
      {
        // 16-bit UUID
        uint16 uuid = BUILD_UINT16( pAttr->type.uuid[0], pAttr->type.uuid[1]);
        switch ( uuid )
        {
          case SIMPLEGATTPROFILE_CHAR1_UUID:
          {
              // Simple logic for setting the tx_power
              // This could be done a variety of more robust ways.
              // I did it this way just for the example.
              if (*pValue <= 10)
              {
                  tx_power = *pValue;
              }
          }

    I modified simple_gatt_profile.c :: SimpleGattProfile_writeAttrCB but notice, in this function the validation of the value comes in the next case (SIMPLEGATTPROFILE_CHAR3_UUID) statement. I recommend refactoring this, so the value is always validated. However, for the sake of this example, I wanted this to be quick and I understand that your overall implementation will be different so don't pay too much attention to this. The goal is to set the tx_power variable via GATT so that our main application has access to that value, regardless of how that is accomplished.

    3. Now we need to modify app_peripheral.c :: Peripheral_GAPConnEventHandler

    In order to change the TX power, we will need to stop all connections and stop all advertisements to ensure that the radio is no longer in use. I haven't thoroughly tested this, however, I believe that when the radio is in use the tx power cannot be changed. Please see the BLEAPPUTIL_LINK_TERMINATED_EVENT.

    extern uint8_t tx_power;
    
    void Peripheral_GAPConnEventHandler(uint32 event, BLEAppUtil_msgHdr_t *pMsgData)
    {
        switch(event)
        {
            case BLEAPPUTIL_LINK_ESTABLISHED_EVENT:
            {
                /* Check if we reach the maximum allowed number of connections */
                if(linkDB_NumActive() < linkDB_NumConns())
                {
                    /* Start advertising since there is room for more connections */
                    BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
                }
                else
                {
                    /* Stop advertising since there is no room for more connections */
                    BLEAppUtil_advStop(peripheralAdvHandle_1);
                }
                break;
            }
    
            case BLEAPPUTIL_LINK_TERMINATED_EVENT:
            {
                // Stop advertising completely.
                BLEAppUtil_advStop(peripheralAdvHandle_1);
    
                // Set the TX power.
                HCI_EXT_SetTxPowerDbmCmd(tx_power, 0);
    
                // Start advertising again.
                BLEAppUtil_advStart(peripheralAdvHandle_1, &advSetStartParamsSet_1);
                break;
            }
    
            default:
            {
                break;
            }
        }
    }

    Alternatively, you could trigger the termination of connections when you set the tx power, but I just manually disconnect from the device. This will cause a BLEAPPUTIL_LINK_TERMINATED_EVENT to trigger, thus setting the TX power for the advertisement.

    In summary, in order to change the TX power for the advertisement during run time, you must ensure that the radio is not being used, and that the proper sysconfig parameters are in place.

    I hope that helps.

    Best,

    Nima Behmanesh

  • Hello Nima,

    Thanks for the support.

    My previous code itself worked after changing the sysconfig settings to The Controller will choose the Tx Power.

    Regards,

    Aslam