LAUNCHXL-CC2640R2: TxPower not changing when HCI_EXT_SetTxPowerCmd() is called

Part Number: LAUNCHXL-CC2640R2
Other Parts Discussed in Thread: ENERGYTRACE, LAUNCHXL-CC26X2R1, SYSCONFIG

Hello,

This is related to the following thread: 

RE: LAUNCHXL-CC26X2R1: What is the meaning of the 3 bytes in pReturnParam for HCI_EXT_SET_TX_POWER event [e2e.ti.com]

In my peripheral application, I'm using HCI_EXT_SetTxPowerCmd(txPowerIndex) to change the transmit power.  I'm passing in an index to the txPowerTable_2400_pa5[] table as the txPowerIndex.  The call returns SUCCESS and I check the status field when the HCI_VE_EVENT_CODE/HCI_EXT_SET_TX_POWER event is generated and that is also a success.  I then call HCI_ReadTransmitPowerLevelCmd(0, HCI_READ_CURRENT_TX_POWER_LEVEL) and it returns the transmit power in dBm and not as an index in the HCI_COMMAND_COMPLETE_EVENT_CODE/HCI_READ_TRANSMIT_POWER event.  The transmit power returned is the one associated with the index I called HCI_EXT_SetTxPowerCmd(txPowerIndex).  At this point, the peripheral application code is working as expected; however, when I use equipment to monitor the transmit power of the advertisements, the transmit power is not actually changing.  It stays at the DEFAULT_TX_POWER setting (5 dBm for my application)  I have the advertisements configured to use GAP_ADV_TX_POWER_NO_PREFERENCE.

Is there something that needs to be done in the peripheral application, besides calling HCI_EXT_SetTxPowerCmd(txPowerIndex), to get the TxPower to change?  Is there some setting that needs to be set to be able to change the TxPower?  Any advice you can offer would be very helpful.

Thanks,

Dawn

  • I should also mention that if I change the setting of DEFAULT_TX_POWER in ble_user_config.c, I can see the transmit power change.  It's during runtime that I can't seem to get the transmit power to change.

  • I also forgot to mention that I'm using SDK v5.10.

  • Hi Dawn,

    Can you try altering the txPower by calling the GapAdv_setParam function with the GAP_ADV_PARAM_TX_POWER paramID. You can mimic the example here for changing the advertising interval at run-time (but change the TX Power instead). I think you're altering the radio settings for the HCI when in reality you want to be setting it for the advertising set you're using.

    NOTE - this was written assuming you're using BLE5. Are you using BLE5 or BLE?

    Best,
    Nate

  • Hi Nathan,

    We are using BLE5.  I tried what you suggested and my advertisements did not change in Transmit Power.  For the advertisements, I changed .txPower from GAP_ADV_TX_POWER_NO_PREFERENCE to GAP_ADV_PROP_TX_POWER as the documentation suggested.  I then call 

    int8_t transmitPower = -20;  // in dBm and not index to table

    GapAdv_setParam(0, GAP_ADV_PARAM_TX_POWER, (void *)&transmitPower);

    However, I don't think this solution will work for us.  We want to change the transmit power during runtime for advertising packets, scan responses, connection commands and continuous wave mode (HCI_EXT_ModemTestTxCmd()).

    Dawn

  • Hello Dawn,

    While Nate prepares a potential response...

    We would just like to also circle-back to this reference thread for review please?

    (+) CC2642R: FCC commands not working after porting TISDK from sdk_3_20_00_68_bak to sdk_4_30_00_54 - Bluetooth forum - Bluetooth®︎ - TI E2E support forums

    It's our understanding that "Rafael" was able to switch the output power (real time) and could verify some differences in the power supply consumption using EnergyTrace (debug monitor) built into the Launchpad EVM.  It seems relevant.

    We realize it isn't an exact duplication of your particular setup but similar enough to share with you.

    If this is not relevant and/or was already reviewed and dismissed, we understand.

    TY,

    Chris

  • Hi Dawn, one thing you might want to check is that you can't change the power reliably after the bluetooth stack has been started.  On the older chips it actually causes a crash in some circumstances.  In my case, I ended up setting the power during the "init" function in my main activity.  If you based your firmware off the simple peripheral example like I did, there is an "_init" function that calls all the GAP setup stuff, and I ended up placing the power setting in that function before calling VOID GAPRole_StartDevice((gapRolesCBs_t *)&ssoBLERoleCB);

    Version 5 of the BLE stack may be different, but my device would actually crash 30-40% of the time if you tried changing the power level with the HCI... functions after you can called GAPRole_StartDevice.

    In my particular case, I store the desired power level somewhere in the flash memory, then retrieve that during the startup sequence before calling GAPRole_StartDevice.   If the calling application wants to change the powerlevel of my device, I set the power level (which simply changes the desired power level in the flash storage), then force the device to reset.  It was the only way I could really get the power level set reliably.

  • Hi Dawn,

    Is this still presenting an issue? If not I'm going to close the thread. Thank you to all who provided input.

    Best,

    Nate

  • I'm still having issues and will have time this week to look into it.  Please leave this thread open.

  • Sounds good. Keep us updated as you learn more.

    Best,

    Nate

  • Hi David, thank you for the ideas.  We don't use GAPRole_StartDevice() and the stack isn't crashing so I don't think this is the issue with our setup.

    Dawn

  • Hi Chris and Rafael,

    I downloaded simple_peripheral_CC26XR1_LAUNCHXL_tirtos_ticlang_PA.zip from the referenced link and compiled it with TI Clang v1.3.0.LTS and SimpleLink CC13x2 26x2 SDK v5.10.0.48.  I'm running it on TI Launchpad CC2642R1/CC2652R1 Development Kit.  I've changed the Tx Power and I don't see nay difference in the Energy Trace Current Graph.  Here are the snaps:

    The first graph is at 5dBm and it shows the advertising peaks at ~8.9nA.  The second graph is at -20dBm and it shows the same level for the advertising peaks.

    Rafael, could you try the project again with SDK v5.10 and let me know what I should be looking for in the EnergyTrace data.

    Thanks,

    Dawn

  • Hi Nathan,

    I tried Rafael's project and didn't see a change in the power but I've also modified SimplePeripheral for my own test.  I changed SimplePeripheral to advertise 1 dataset every 250ms.  I've also changed the periodic timer to 1000 and everytime it expires, I toggle the transmit power between 5dBm and -20dBm.  When I look at the EnergyTrace Current graph, I expect to see a transmit spike once a second that should be the HCI call changing the TxPower.  I then expect to see 4 spikes of advertising data between the HCI calls at either 5dBm or -20dBm.  I expect the 5dBm spikes to be noticeably larger that the -20dBm spikes.  Here's what I'm seeing:

    The HCI Cmd spike shows up at 850ms, 1850ms, 2850ms, 3850ms, 4850ms (Red arrow at 1850ms).  There are 4 high peaks at ~11mA after 1850ms.  I'm assuming this is when the TxPower was set to 5dBm.  After the HCI cmd at 2850ms, there is a small spike at ~8mA which is where I assume the TxPower was set to -20dBm.  However, after the 8mA spike, the remaining three spiked go back to ~11mA.  It's like it tried to change the transmit power but it didn't stick.

    5086.simple_peripheral.c

    I'm attaching simple_peripheral.c so you can try to reproduce what I'm seeing.  In simple_peripheral.c, the toggling and HCI call happen in SimplePeripheral_performPeriodicTask().

    Thanks,

    Dawn

  • Hi Dawn,

    Is it possible your code is resetting the TXPower somewhere? I did some initial testing and I found that if I took an unmodified simple_peripheral example and simply called HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_21_DBM); on the key handler, I got the 26 dB power change I was expecting. I tested with a spectrum analyzer in the lab to confirm.

    I also ran it with energytrace and found that the current consumed does increase/decrease when the tx power is increased/decreased.

    Perhaps you can verify our setup too. It's just the simple_peripheral example with the extended advertising set removed, and the following change to the HandleKeys function in simple_peripheral.c (SDK 5.10 for CC2640R2).

    static void SimplePeripheral_handleKeys(uint8_t keys)
    {
    if (keys & KEY_LEFT)
    {
    // Check if the key is still pressed. Workaround for possible bouncing.
    if (PIN_getInputValue(Board_PIN_BUTTON0) == 0)
    {
    tbm_buttonLeft();
    HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_5_DBM);

    }
    }
    else if (keys & KEY_RIGHT)
    {
    // Check if the key is still pressed. Workaround for possible bouncing.
    if (PIN_getInputValue(Board_PIN_BUTTON1) == 0)
    {
    tbm_buttonRight();
    HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_21_DBM);

    }
    }
    }

    Pictures of Setup (5 dBm left, -21 dBm right). Ignore the spur at 2404 MHz in the right hand picture.

                                  

    Energytrace showing differences in peak currents

    I also see in your code you're calling HCI_EXT_SetTxPowerCmd with an argument of 0x0E for 5 dBm, whereas the HCI_EXT_TX_POWER_5_DBM is defined to 12 = 0x0B. Does that change anything?

    As well, are you using a 2640 or a 2642? You have referenced both in your responses.

  • Hi Nathan,

    I'm using the Launchpad with a CC2652R1.  This is the board I'm running Simple Peripheral and Energy Trace on.  Our custom board uses the CC2642R1 (not the 2640).

    I imported the simple_peripheral project, commented out the code that used advHandleLongRange and made the changes to SimplePeripheral_handleKeys() as you suggested above.  I received a compile error for HCI_EXT_TX_POWER_MINUS_21_DBM and changed it to HCI_EXT_TX_POWER_MINUS_20_DBM.  When I look at the definitions for HCI_EXT_TX_POWERxx that correspond to LL_EXT_TX_POWERxx in ll.h, I see:

    #if defined( CC26XX ) || defined( CC13XX )
    #define LL_EXT_TX_POWER_MINUS_20_DBM             0
    #define LL_EXT_TX_POWER_MINUS_18_DBM             1
    #define LL_EXT_TX_POWER_MINUS_15_DBM             2
    #define LL_EXT_TX_POWER_MINUS_12_DBM             3
    #define LL_EXT_TX_POWER_MINUS_10_DBM             4
    #define LL_EXT_TX_POWER_MINUS_9_DBM               5
    #define LL_EXT_TX_POWER_MINUS_6_DBM               6
    #define LL_EXT_TX_POWER_MINUS_5_DBM               7
    #define LL_EXT_TX_POWER_MINUS_3_DBM               8
    #define LL_EXT_TX_POWER_0_DBM                             9
    #define LL_EXT_TX_POWER_1_DBM                            10
    #define LL_EXT_TX_POWER_2_DBM                            11
    #define LL_EXT_TX_POWER_3_DBM                            12
    #define LL_EXT_TX_POWER_4_DBM                            13
    #define LL_EXT_TX_POWER_5_DBM                            14

    This is where I got 0x0E for 5dBm.  These definitions also seem to align with the table in ti_radio_config.c:

    RF_TxPowerTable_Entry txPowerTable_2400_pa5[TXPOWERTABLE_2400_PA5_SIZE] =
    {
    {-20, RF_TxPowerTable_DEFAULT_PA_ENTRY(6, 3, 0, 2) },
    {-18, RF_TxPowerTable_DEFAULT_PA_ENTRY(8, 3, 0, 3) },
    {-15, RF_TxPowerTable_DEFAULT_PA_ENTRY(10, 3, 0, 3) },
    {-12, RF_TxPowerTable_DEFAULT_PA_ENTRY(12, 3, 0, 5) },
    {-10, RF_TxPowerTable_DEFAULT_PA_ENTRY(15, 3, 0, 5) },
    {-9, RF_TxPowerTable_DEFAULT_PA_ENTRY(16, 3, 0, 5) },
    {-6, RF_TxPowerTable_DEFAULT_PA_ENTRY(20, 3, 0, 8) },
    {-5, RF_TxPowerTable_DEFAULT_PA_ENTRY(22, 3, 0, 9) },
    {-3, RF_TxPowerTable_DEFAULT_PA_ENTRY(19, 2, 0, 12) },
    {0, RF_TxPowerTable_DEFAULT_PA_ENTRY(19, 1, 0, 20) },
    {1, RF_TxPowerTable_DEFAULT_PA_ENTRY(22, 1, 0, 20) },
    {2, RF_TxPowerTable_DEFAULT_PA_ENTRY(25, 1, 0, 25) },
    {3, RF_TxPowerTable_DEFAULT_PA_ENTRY(29, 1, 0, 28) },
    {4, RF_TxPowerTable_DEFAULT_PA_ENTRY(35, 1, 0, 39) },
    {5, RF_TxPowerTable_DEFAULT_PA_ENTRY(23, 0, 0, 57) },
    RF_TxPowerTable_TERMINATION_ENTRY
    };

    The EnergyTrace output I get with the changes to Simple Peripheral is:

    The yellow circled areas seem to correspond to when I push a button but I don't see a change like you see.

    Could the issue be with the txPowerTable and index definitions?

    Dawn

  • Hi Dawn,

    Thank you for the clarification. To change the txpower used in advertising, you will want to use the GapAdv_setParam command. I modified a simple_peripheral example for the CC26X2 that included the following in the SimplePeripheral_processAdvEvent function.

    case GAP_EVT_ADV_END_AFTER_DISABLE:
        Display_printf(dispHandle, SP_ROW_ADVSTATE, 0, "Adv Set %d Disabled",
        *(uint8_t *)(pEventData->pBuf));
        int8_t adv_power = 0;
        bStatus_t mystatus = GapAdv_getParam(advHandleLegacy, GAP_ADV_PARAM_TX_POWER, &adv_power);
        SIMPLEPERIPHERAL_ASSERT(mystatus == SUCCESS);
    
        if(adv_power != -20){
            bStatus_t myadvstatus = GapAdv_setParam(advHandleLegacy, GAP_ADV_PARAM_TX_POWER, &minus_twenty);
            SIMPLEPERIPHERAL_ASSERT(myadvstatus == SUCCESS);
        }
        else{
            GapAdv_setParam(advHandleLegacy, GAP_ADV_PARAM_TX_POWER, &plus_five);
        }
        GapAdv_enable(advHandleLegacy, GAP_ADV_ENABLE_OPTIONS_USE_MAX , 0);
        break;

    I also altered the handle_keys function as such to trigger the GAP_EVT_ADV_END_AFTER_DISABLE event.

    static void SimplePeripheral_handleKeys(uint8_t keys)
    {
      if (keys & KEY_LEFT)
      {
        // Check if the key is still pressed. Workaround for possible bouncing.
        if (PIN_getInputValue(CONFIG_PIN_BTN1) == 0)
        {
          tbm_buttonLeft();
          //GapAdv_disable(advHandleLongRange);
        }
      }
      else if (keys & KEY_RIGHT)
      {
        // Check if the key is still pressed. Workaround for possible bouncing.
        if (PIN_getInputValue(CONFIG_PIN_BTN2) == 0)
        {
          GapAdv_disable(advHandleLegacy);
          tbm_buttonRight();
        }
      }
    }

    This flow is documented in the SimpleLink Academy page on Scanning and Advertising in Task 3 (Albeit for changing the advertising interval).

    This gave me the following energytrace capture, which clearly shows a change in txpower.

    I recommend following this flow to get the same results. Let me know when you get it working!

    Best,

    Nate

  • Hi Nathan, I tried this approach (see posting on Oct 19th) and it did not work for me.  Are you saying that in order to change the Tx Power, both the HCI_EXT_SetTxPowerCmd() and GapAdv_setParam() commands need to be used?  I need the Tx power to be changed for advertising, scan responses, connections and continuous wave mode (HCI_EXT_ModemTestTxCmd()).

    Can we go back to my previous reply.  I noticed differences in the RF_Power table that I'm using and some remarks you made in your reply on Oct 27th.  Can you explain the differences to me?  Also, what Launchpad hardware and SDK are you using for your examples and captures?

    Dawn

  • Hi Dawn,

    Are you saying that in order to change the Tx Power, both the HCI_EXT_SetTxPowerCmd() and GapAdv_setParam() commands need to be used? 

    I'm working on verifying this now. It's taking me longer than expected because I'm trying to monitor the RSSI while in a connection, which is tricky because it means I cannot run tests in conducted mode (because I won't be able to connect to a nearby launchpad). Can you give me more context into what you're trying to do here generally? Are you trying to make short-range and long-range modes for you application? Why is the Modem test command important too?

    I noticed differences in the RF_Power table that I'm using and some remarks you made in your reply on Oct 27th.  Can you explain the differences to me? 

    The -20 vs -21 dBm difference is because my response on Oct 21st was for the CC26X0 devices, whereas you're using a CC26X2 device. The CC26X0's have a HCI_EXT_TX_POWER_MINUS_21_DBM setting, but the CC26X2's have a HCI_EXT_TX_POWER_MINUS_20_DBM setting.

    Also, what Launchpad hardware and SDK are you using for your examples and captures?

    Launchpad : LAUNCHXL-CC26X2R1

    SDK : 5.20

  • Hi Nathan,

    Here's our requirements...Our application advertises legacy and extended and responds to scan responses.  A Central can also connect to our application.  On top of that, the device can be put in continuous wave mode so the electronics team can perform range testing.  We have a couple different custom board designs that use the same firmware so not every custom board will use the default value TxPower.  We want to be able to send a new TxPower over UNPI and save it it NVM and have that new TxPower affect all the transmit modes forever more.

    Dawn

  • Thank you Dawn! I will investigate this further and get back to you within 24 hours.

    Best,

    Nate

  • Hi Dawn,

    Here is a conclusive answer:

    For Advertising, Scan Responses and Connection - Use GapAdv_setParam()

    For the HCI_EXT_ModemTestTxCmd - use HCI_EXT_SetTxPowerCmd()

    Below is the waveform I was able to obtain by running my code where I just call GapAdv_setParam as above.

    This code toggles between 5 dBm and -20 dBm every time advertising stops (either because you push a button or because you're entering a connection interval. See in the screenshot how every time you enter a connection the current consumption changes. This shows to me pretty conclusively that calling GapAdv_setParam should be able to change the txpower for advertising, scan response and connection mode. I also monitored with a packet capture and confirmed through the RSSI that the packet sniffer measured. 

    5 dBm advertising and scan response

    5 dBm connection

    -20 dBm advertising and scan response

    -20 dBm connection

    Here is the code I used to generate these results.

    change_GapAdv_setParam.zip

    As for the HCI_EXT_ModemTestTxCmd, it seems this can be changed with the HCI_EXT_SetTxPowerCmd. Using the 5.20 SDK on a CC26X2 launchpad, I modified a simple_peripheral example to enable PTM in sysconfig, disabled advertising, and ran the following code on the button callback:

          GapAdv_disable(advHandleLegacy);
          if(tx_power == 5){
              if(first_time == 1){
                  HCI_EXT_EnablePTMCmd();
                  first_time = 0;
              }
              else{
                  HCI_EXT_EndModemTestCmd();
              }
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_MINUS_20_DBM);
              HCI_EXT_ModemTestTxCmd(LL_EXT_TX_UNMODULATED_CARRIER, 0x00);
              tx_power = -20;
          }
          else{
              HCI_EXT_EndModemTestCmd();
              HCI_EXT_SetTxPowerCmd(HCI_EXT_TX_POWER_5_DBM);
              HCI_EXT_ModemTestTxCmd(LL_EXT_TX_UNMODULATED_CARRIER, 0x00);
              tx_power = 5;
          }

    Full project is attached here.

    change_HCI_EXT_ModemTestTxCmd_Power.zip

    I hope you can leverage these examples to build your application.

    Best,

    Nate

  • Hi Nathan, I'm slow to implement these suggestions so I wanted to let you know that I'm still working on this.  Please don't close this issue yet.

    Dawn

  • Sounds good. If it's very long in between posts too you can also just open a new thread and include link to the previous one here. Something we try to do on E2E is make our threads short and focused on specific issues so we can search them later efficiently.