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.

CC2541 BLE - read RSSI on every connection interval

Other Parts Discussed in Thread: CC2541, CC2540

Hi there, 

On my current project (using CC2541), I need to read RSSI value on every connection interval.

To do that, I implemented the following callback function in keyfobdemo.c.

// GAP Role Callbacks

static gapRolesCBs_t keyFob_PeripheralCBs =
{
     peripheralStateNotificationCB,           
     my_updateRssiCB                                      // I implemented this callback function to read RSSI
};

However, I found that this callback function won't get new RSSI value on every connection interval, but only get new RSSI value when the keyfob receives a non-empty packet (ex. GATT Indication) from Peer Device. This doesn't meet my requirement, since I want to get new RSSI on every connection interval.

Does any one know a method to get RSSI value which will be updated on every connection interval?

Thanks,

Best Regards,
Arthur

  • Hi Arthur,


    sorry that there is no answer to your question. I have exactly the same question and I am looking for an answer. I know that it should be possible, since the BLE monitor gives an RSSI info to every packet. I looked to the hardware registers of the CC2541 directly, but RSSI_VALID in register @0x6199 is always 0 and RSSI value @0x6198 has no reasonable content.

    Have you got an answer meanwhile? If yes, can you post it please.

    Thanks

    Georg

  • If you look at some other threads, you will find that this is a known bug in the BLE 1.4 stack.  It will not update the RSSI value for empty (zero length payload) packets.  You can work around this by either having the device you are connected to send you some data or your (peripheral/slave) device can initiate some sort of request (such as a connection parameter update request or maybe some simpler request) that will return some data.

    However, I tried issuing something innocuous like the following from hci.h:

    extern hciStatus_t HCI_ReadRemoteVersionInfoCmd( uint16 connHandle );

    which after an HCI_CommandStatusEvent (just acknowledges that the command was received) and a ReadRemoteVersionInfoEvent, the RSSI should be updated since there should be real payload in data packets from this command.  This did not work for whatever reason.

    What did work was issuing a Read command from the central/master device where I was reading a value that was updated with the RSSI.  I just couldn't figure out how to make this work using notifications.  Perhaps using an indication may work if the acknowledgement is considered to contain a non-zero payload of data.

  • Hi,

    Hang tight, there will be a new release *soon* with RSSI updated for empty connection packets.

    Best wishes
  • Hi,

    do we have any news about this issue ?

    While operating in peripheral mode the rssi callback never gets called in my case (CC2540).


    I noticed that the "RSSI_READ_EVT" is called but the "HCI_ReadRssiCmd( gapRole_ConnectionHandle )" return value is always 0 (even when I have notifications exchanged)

    Any directions here would be much appreciated.

    Thanks!

  • You should look at the AdvConnEventNotice sample code to see how this is done properly.

    processors.wiki.ti.com/.../CC254X_AdvConnNotice

    and the BLE software developer's reference guide:

    http://www.ti.com/lit/ug/swru271g/swru271g.pdf

    Though you can specify a rate of getting the RSSI via the GAPROLE_RSSI_READ_RATE GAPRole parameter, you can instead use the HCI_ReadRssiCmd call after every connection interval ends which is what it sounds like you might be trying to do.

    As specified in the documentation for HCI_ReadRssiCmd in the hci.h header file:

    /*******************************************************************************
    * @fn HCI_ReadRssiCmd API
    *
    * @brief This BT API is used to read the RSSI of the last packet
    * received on a connection given by the connection handle. If
    * the Receiver Modem test is running (HCI_EXT_ModemTestRx), then
    * the RF RSSI for the last received data will be returned. If
    * there is no RSSI value, then HCI_RSSI_NOT_AVAILABLE will be
    * returned.
    *
    * Related Events: HCI_CommandCompleteEvent
    *
    * input parameters
    *
    * @param connHandle - Connection handle.
    *
    * output parameters
    *
    * @param None.
    *
    * @return hciStatus_t
    */

    you can see that the RSSI is NOT returned by this function call. hciStatus_t is 0 for a normal return and is what you are seeing; this is typical of many HCI calls where they do not directly return info but rather trigger a callback to a function that returns info. The actual RSSI itself will be passed to the callback function you need to specify in the GAP Role Callbacks as defined in peripheral.h:

    /**
    * Callback structure - must be setup by the application and used when gapRoles_StartDevice() is called.
    */
    typedef struct
    {
    gapRolesStateNotify_t pfnStateChange; //!< Whenever the device changes state
    gapRolesRssiRead_t pfnRssiRead; //!< When a valid RSSI is read from controller
    } gapRolesCBs_t;

    So you need to add a callback function in the code where I show below what it would look like in simpleBLEPeripheral.c:

    // NOTE: Added peripheralRSSIreadCB callback
    // GAP Role Callbacks
    static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =
    {
    peripheralStateNotificationCB, // Profile State Change Callbacks
    peripheralRSSIreadCB // When a valid RSSI is read from controller
    };

    The callback function's definition can look like the following:

    static void peripheralRSSIreadCB( int8 newRSSI )

    where the RSSI is passed in as a parameter where you can then do what you want with it. To trigger this callback, you need to either do the HCI_ReadRssiCmd in the ProcessEvent function for the connection end event that I show below for SimpleBLEPeripheral.c or you need to set the GAPROLE_RSSI_READ_RATE GAPRole parameter:

    uint16 SimpleBLEPeripheral_ProcessEvent( uint8 task_id, uint16 events )
    {
    :
    if ( events & SBP_CON_EVT )
    {
    VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );
    return (events ^ SBP_CON_EVT);
    }
    :

    Note that there was a bug where this callback was not called if all the packets during a connection interval had no data, but that was fixed in the TI BLE 1.4.1 stack.

  • Hi,

    first of all, thanks for the quick response.

    I have included the part to handle the SBP_CON_EVT (I didn't have the HCI_EXT_ConnEventNoticeCmd call set in the GAPROLE_CONNECTED state. Now the SBP_CON_EVT is triggered (including HCI_ReadRssiCmd), but the rssi callback never gets called. (I am using TI BLE 1.4.1)

    Note that before the changes suggested, the event "RSSI_READ_EVT" in the peripheral.c was already being triggered (I call GAPROLE_RSSI_READ_RATE upon connection to make sequential calls to the "HCI_ReadRssiCmd" function. GAPRole_SetParameter( GAPROLE_RSSI_READ_RATE, sizeof( uint16 ), &rssi_read_rate );

    Apparently, in my case, both approaches "GAPROLE_RSSI_READ_RATE" or "SBP_CON_EVT " are doing the same thing (calling the HCI_ReadRssiCmd periodically) and in both situations the RSSI callback does not get triggered.


    Ayn further suggestions ?
  • You are correct that both approaches do the same thing in different ways, namely calling HCI_ReadRssiCmd. If you look at peripheral.c you will see that they do the following based on the RSSI_READ_EVT that is triggered from your GAPROLE_RSSI_READ_RATE setting since that sets an OSAL timer for RSSI_READ_EVT:

    if ( events & RSSI_READ_EVT )
    {
    // Only get RSSI when in a connection
    if ( gapRole_state == GAPROLE_CONNECTED )
    {
    // Ask for RSSI
    VOID HCI_ReadRssiCmd( gapRole_ConnectionHandle );

    // Setup next event
    if ( gapRole_RSSIReadRate )
    {
    VOID osal_start_timerEx( gapRole_TaskID, RSSI_READ_EVT, gapRole_RSSIReadRate );
    }
    }
    return ( events ^ RSSI_READ_EVT );
    }

    As for the RSSI callback, do you have something like I showed before setting up the GAP role callback? Then those callbacks were set via the following in the ProcessEvent function:

    static gapRolesCBs_t simpleBLEPeripheral_PeripheralCBs =
    {
    peripheralStateNotificationCB, // Profile State Change Callbacks
    peripheralRSSIreadCB // When a valid RSSI is read from controller
    };
    :
    :
    if ( events & SBP_START_DEVICE_EVT )
    {
    // Start the Device
    VOID GAPRole_StartDevice( &simpleBLEPeripheral_PeripheralCBs );
    :

    That was part of the simpleBLEPeripheral.c sample code, but the RSSI callback function itself is not there and you have to add that yourself as shown above (i.e. "peripheralRSSIreadCB"). I'm using 1.4.0 and this all works for me except for the known bug where the callback is not called for empty packets. Presumably that is fixed in 1.4.1.

    So I am at a loss for why it isn't working for you and I hope that when I move to 1.4.1 this won't break for me too.
  • Hi Richard,

    yes, I have the callback correctly set and it never gets called.
    I am preparing now a different test scenario where big amount of data is transferred. I will post the results today.


    In any case, thanks for the support.

  • Hi,

    I still couldn't manage to make the RSSI values to work. If anyboy has any news, please let me know.
  • Hi,

    I managed to get the RSSI readings in the CENTRAL devices to work by adding StartRssi uppon connection event: GAP_LINK_ESTABLISHED_EVENT
    case(GAP_LINK_ESTABLISHED_EVENT):
    ...
    GAPCentralRole_StartRssi( connHandler, RSSI_READ_TIME );

    However, I am still not able to read RSSI values from PERIPHERAL devices... Uppon connection I set the rate reading parater to != 0, as suggested by the documentation but the callback is never triggered.

    GAPRole_SetParameter( GAPROLE_RSSI_READ_RATE, sizeof( uint16 ), &rssi_read_rate );


    Alternativelly I created a custom periodical call to HCI_ReadRssiCmd which leads to the same result. The callback is never called.

    Debugging I have noticed that neither the HCI_GAP_EVENT_EVENT in the peripheral.c file gets called.
    Perhaps there is a different issue present ?
  • Dear expert,

    I have exactly same problem, readrssi callback never call after called HCI_ReadRssiCmd( gapRole_ConnectionHandle ); ,  I run SDK 1.4.2.2 on CC2541 peripheral device.

    Does anyone find the solution now since there is no result of this issue ?  please help ! 

    Thansk  in advance.