Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

softdevice S140 v6.0.0: how to set the channel mask for different channels

Hi

Can you please provide an example/pseudo-code on how the channel_mask member in the ble_gap_adv_params_t struct is used? The only examples provided in the SDK and the migration document set the entire member to {0} and it is unclear how this should used. In other words, what should we set the channel_mask to if we want to use channels 37, 38, and 39. We have tried the pseudocode below but starting advertising failed:-

s_adv_params.channel_mask[0] = 0xFF;
s_adv_params.channel_mask[1] = 0xFF;
s_adv_params.channel_mask[2] = 0xFF;
s_adv_params.channel_mask[3] = 0xFF;
s_adv_params.channel_mask[4] = 0x1F;

We are using softdevice S140 v6.0.0 and SDK 15.0.0 on an nRF52840 PDK.

Thanks

Youssif

Parents Reply Children
  • Hi Lexi,

    The 40 BLE channels are each represented by 1 bit. In total there are 5 array elements (0 to 4), 8 bits for each array element. The LSB contained in array element 0 represents channel index 0, and bit 39 ( MSB in array element 4) represents channel index 39.

    channel_mask[4] is therefore the 8 upper channels. If you only want to advertise on 38, you will need set bit 39 and 37 high, so that would be adv_params.channel_mask[4] = 0xA0; (1010 0000 in binary).

    Using the advertising module, you could place it ble_advertising.c in the function ble_advertising_start(), right before sd_ble_gap_adv_set_configure() is called. The SDK15.0 ble_advertising_start() function would then look like this:

    uint32_t ble_advertising_start(ble_advertising_t * const p_advertising,
                                   ble_adv_mode_t            advertising_mode)
    {
        uint32_t ret;
    
        if (p_advertising->initialized == false)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
        p_advertising->adv_mode_current = advertising_mode;
    
        // Delay starting advertising until the flash operations are complete.
        if (flash_access_in_progress())
        {
            p_advertising->advertising_start_pending = true;
            return NRF_SUCCESS;
        }
    
       memset(&p_advertising->peer_address, 0, sizeof(p_advertising->peer_address));
    
        if (  ((p_advertising->adv_modes_config.ble_adv_directed_high_duty_enabled) && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY))
            ||((p_advertising->adv_modes_config.ble_adv_directed_enabled)           && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED_HIGH_DUTY))
            ||((p_advertising->adv_modes_config.ble_adv_directed_enabled)           && (p_advertising->adv_mode_current == BLE_ADV_MODE_DIRECTED))
           )
        {
            if (p_advertising->evt_handler != NULL)
            {
                p_advertising->peer_addr_reply_expected = true;
                p_advertising->evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST);
            }
            else
            {
                p_advertising->peer_addr_reply_expected = false;
            }
        }
    
        p_advertising->adv_mode_current = adv_mode_next_avail_get(p_advertising, advertising_mode);
    
        // Fetch the whitelist.
        if ((p_advertising->evt_handler != NULL) &&
            (p_advertising->adv_mode_current == BLE_ADV_MODE_FAST || p_advertising->adv_mode_current == BLE_ADV_MODE_SLOW) &&
            (p_advertising->adv_modes_config.ble_adv_whitelist_enabled) &&
            (!p_advertising->whitelist_temporarily_disabled))
        {
            p_advertising->whitelist_in_use         = false;
            p_advertising->whitelist_reply_expected = true;
            p_advertising->evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST);
        }
        else
        {
            p_advertising->whitelist_reply_expected = false;
        }
    
        // Initialize advertising parameters with default values.
        memset(&p_advertising->adv_params, 0, sizeof(p_advertising->adv_params));
    
        p_advertising->adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
    
        // Use 1MBIT as primary phy if no phy was selected.
        if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_primary_phy))
        {
            p_advertising->adv_params.primary_phy = p_advertising->adv_modes_config.ble_adv_primary_phy;
        }
        else
        {
            p_advertising->adv_params.primary_phy = BLE_GAP_PHY_1MBPS;
        }
    
        if (p_advertising->adv_modes_config.ble_adv_extended_enabled)
        {
            // Use 1MBIT as secondary phy if no phy was selected.
            if (phy_is_valid(&p_advertising->adv_modes_config.ble_adv_primary_phy))
            {
                p_advertising->adv_params.secondary_phy = p_advertising->adv_modes_config.ble_adv_secondary_phy;
            }
            else
            {
                p_advertising->adv_params.secondary_phy = BLE_GAP_PHY_1MBPS;
            }
        }
        p_advertising->adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
    
        // Set advertising parameters and events according to selected advertising mode.
        switch (p_advertising->adv_mode_current)
        {
            case BLE_ADV_MODE_DIRECTED_HIGH_DUTY:
                ret = set_adv_mode_directed_high_duty(p_advertising, &p_advertising->adv_params);
                break;
    
            case BLE_ADV_MODE_DIRECTED:
                ret = set_adv_mode_directed(p_advertising, &p_advertising->adv_params);
                break;
    
            case BLE_ADV_MODE_FAST:
                ret = set_adv_mode_fast(p_advertising, &p_advertising->adv_params);
                break;
    
            case BLE_ADV_MODE_SLOW:
                ret = set_adv_mode_slow(p_advertising, &p_advertising->adv_params);
                break;
    
            case BLE_ADV_MODE_IDLE:
                p_advertising->adv_evt = BLE_ADV_EVT_IDLE;
                break;
    
            default:
                break;
        }
    
        if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE)
        {
            p_advertising->adv_params.channel_mask[4] = 0xA0;
            ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params);
            if (ret != NRF_SUCCESS)
            {
                return ret;
            }
            ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag);
    
            if (ret != NRF_SUCCESS)
            {
                return ret;
            }
        }
    
        if (p_advertising->evt_handler != NULL)
        {
            p_advertising->evt_handler(p_advertising->adv_evt);
        }
    
        return NRF_SUCCESS;
    }

  • Thank you so much for such amazing explanation, I understood after a long time searching the net, just one more question, I am trying to find RSSI values based on advertising channel because the rssi values are different in each channel and save them on a log file. I am using 2 peaces of nrf52840 preview DK board and SDK 15.0 I have not found yet an example which is close to work on. would you please help me. I am trying to turn off some channels to just received RSSI based on one of them but I can not received the channel number on the receiver board.  (used bms example on transmitter board (as beacon) and central example on receiver) . really appreciate your help

Related