This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Enabling 2MBPS and CODED PHYs

Hello, I have a project that's fairly mature and working great but now I want to extend the abilities of the device by using the extended PHYs. I know there are a million threads on this but I can't make any sense out of any of them. I tried looking at the throughput example, and updating my code to match and I still get errors all over the place. I guess I don't even understand how this is supposed to work and what all of it is. I saw a post from years ago that someone was going to create a blog post on what the different advertising types were, etc but I don't think it ever happened.

Here is the relevant code from my project, which I believe I used Blinky as a base example when creating this, along with some questions

static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];                    /**< Buffer for storing an encoded advertising set. */
static uint8_t m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];         /**< Buffer for storing an encoded scan data. */

/**@brief Struct that contains pointers to the encoded advertising data. */
static ble_gap_adv_data_t m_adv_data =
{
    .adv_data =
    {
        .p_data = m_enc_advdata,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    },
    .scan_rsp_data =
    {
        .p_data = m_enc_scan_response_data,
        .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX

    }
};

What do these do/store? the throughput example has two different sets of these, but it doesn't use the scan_rsp_data anywhere.

void advertising_init(void){

    ret_code_t    err_code;
    ble_advdata_t advdata;
    ble_advdata_t srdata;

    ble_uuid_t adv_uuids[] = {{CTCWS_UUID_CONFIG_SERVICE, m_ctcws.uuid_type}};

    // Build and set advertising data.
    memset(&advdata, 0, sizeof(advdata));

    advdata.name_type          = BLE_ADVDATA_FULL_NAME;
    advdata.include_appearance = true;
    advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;


    memset(&srdata, 0, sizeof(srdata));
    srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    srdata.uuids_complete.p_uuids  = adv_uuids;

    err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
    APP_ERROR_CHECK(err_code);

    err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
    APP_ERROR_CHECK(err_code);

    ble_gap_adv_params_t adv_params;

    // Set advertising parameters.
    memset(&adv_params, 0, sizeof(adv_params));

    adv_params.primary_phy      = tx_rate;
    adv_params.primary_phy      = tx_rate;
    adv_params.duration         = advertise_timeout;
    adv_params.properties.type  = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
    adv_params.p_peer_addr     = NULL;
    adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
    adv_params.interval        = advertise_interval;

    err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, tx_power);
    APP_ERROR_CHECK(err_code);

    #ifdef DEBUG
    printf("advertising_init\r\n");
    #endif
}

This all works great at 1MBPS, but changing the primary and secondary phy to either CODED or 2MBPS, and changing the type to  BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED causes me to get an error at one or the other of ble_adv_data no matter how I set up ble_gap_adv_data_t.adv_data or ble_gap_adv_data_t.scan_rsp_data.

I also don't know if this has something to do with MTU? That's my next challenge is extending that, right now I think I'm just using the standard 23 byte MTU for backwards compatibility.

Do I need to do anything with the connection to change speeds? or just the advertising?

Can I get a simple explanation of how to update this (blinky) code to allow 2MPBS and CODED, without just saying "look at the mtu throughput example" like all the other threads? It's not making any sense to me and I can get this to work based on the mtu throughput example.

SDK is 15.2.0 SD is S140 - 6.1.0

Parents
  • Hi Adam, 

    Could you tell which exact error code do you have and on which function? 

    Have you had a look at this blog which has the example code ? https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/testing-long-range-coded-phy-with-nordic-solution-it-simply-works-922075585

    Please be aware that, the PHY change can happens when the devices are in connection. So for 2Mbps most of the device will just advertise in 1Mbps first and then switch to 2Mbps after the connection is established (because not many phones scan in 2Mbps). 

  • Hung, The errors are all over the place depending on how I set up the ble_gap_adv_data_t variables. I get DATA_SIZE and INVALID_PARAM.

    I've read that over and over and for some reason it doesn't simply work. I've copied the code out of the example and it doesn't work. Everything in that example seems to be slightly different than the blinky example my project is originally based on.

    So, how do I change the speed during the connection? I want to give the user/application the option to enable CODED/2MBPS if they want. Advertising and connecting in 1MBPS then changing seems fine, but it would also be great to be able to advertise/connect in CODED.

  • Honestly, I'm not too worried about 2MBPS, but coded is going to be really nice to have in the final application.

    Switching up to 2MBPS at run time would be good.

  • Hi Adam, 
    This code worked for me:

    static void advertising_init(void)
    {
        ret_code_t    err_code;
        ble_advdata_t advdata;
        ble_advdata_t srdata;
    
        ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
    
        memset(&srdata, 0, sizeof(srdata));
        /*srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;*/
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        ble_gap_adv_params_t adv_params;
    
        // Set advertising parameters.
        memset(&adv_params, 0, sizeof(adv_params));
    
        adv_params.primary_phy     = BLE_GAP_PHY_CODED;
        adv_params.secondary_phy   = BLE_GAP_PHY_CODED;
        adv_params.duration        = APP_ADV_DURATION;
        adv_params.properties.type = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED;
        adv_params.p_peer_addr     = NULL;
        adv_params.filter_policy   = BLE_GAP_ADV_FP_ANY;
        adv_params.interval        = APP_ADV_INTERVAL;
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
        APP_ERROR_CHECK(err_code);
    }

    Make sure the srdata is empty. Extended advertising doesn't support scan response packet (which makes sense since it transfer extra data in the data channels)

    To switch between PHY when in connection, please follow the sequence chart here: infocenter.nordicsemi.com/.../group___b_l_e___g_a_p___p_e_r_i_p_h_e_r_a_l___p_h_y___u_p_d_a_t_e.html

  • Hung, this runs for me if I comment out lines 24 and 25, (53/54 below) but I'm not sure if it'll actually work... I don't have a coded phy peer right now. Is it acceptable to remove these lines?

    If I uncomment them I get a DATA_LENGTH error.

    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = m_enc_scan_response_data,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };
    /**@brief Struct that contains pointers to the encoded advertising data for extended advertising types. */
    static ble_gap_adv_data_t m_adv_data_ext =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = NULL,//m_enc_scan_response_data,
            .len    = 0//BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };

    static void advertising_init(void){
    
        ret_code_t    err_code;
        ble_advdata_t advdata;
        ble_advdata_t srdata;
    
        ble_uuid_t adv_uuids[] = {{CTCWS_UUID_CONFIG_SERVICE, m_ctcws.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        if (tx_rate != BLE_GAP_PHY_CODED){  //anything other than coded
    
            err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
            APP_ERROR_CHECK(err_code);
    
            ble_gap_adv_params_t adv_params;
    
            // Set advertising parameters.
            memset(&adv_params, 0, sizeof(adv_params));
    
            adv_params.primary_phy      = BLE_GAP_PHY_1MBPS;
            adv_params.primary_phy      = BLE_GAP_PHY_1MBPS;
            adv_params.duration         = advertise_timeout;
            adv_params.properties.type  = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
            adv_params.p_peer_addr      = NULL;
            adv_params.filter_policy    = BLE_GAP_ADV_FP_ANY;
            adv_params.interval         = advertise_interval;
    
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
            APP_ERROR_CHECK(err_code);
    
            #ifdef DEBUG
            printf("Advertising at 1Mbps\r\n");
            #endif
    
        }//tx_rate != BLE_GAP_PHY_CODED
    
        else{ //tx_rate == BLE_GAP_PHY_CODED
    
            //err_code = ble_advdata_encode(&srdata, m_adv_data_ext.scan_rsp_data.p_data, &m_adv_data_ext.scan_rsp_data.len);
            //APP_ERROR_CHECK(err_code);
    
            ble_gap_adv_params_t adv_params;
    
            // Set advertising parameters.
            memset(&adv_params, 0, sizeof(adv_params));
    
            adv_params.primary_phy      = BLE_GAP_PHY_CODED;
            adv_params.primary_phy      = BLE_GAP_PHY_CODED;
            adv_params.duration         = advertise_timeout;
            adv_params.properties.type  = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED;
            adv_params.p_peer_addr      = NULL;
            adv_params.filter_policy    = BLE_GAP_ADV_FP_ANY;
            adv_params.interval         = advertise_interval;
    
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data_ext, &adv_params);
            APP_ERROR_CHECK(err_code);
    
            #ifdef DEBUG
            printf("Advertising at 125kbps CODED\r\n");
            #endif
    
        }//tx_rate == BLE_GAP_PHY_CODED
    
        err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, tx_power);
        APP_ERROR_CHECK(err_code);
    
        #ifdef DEBUG
        printf("advertising_init\r\n");
        #endif
    }

Reply
  • Hung, this runs for me if I comment out lines 24 and 25, (53/54 below) but I'm not sure if it'll actually work... I don't have a coded phy peer right now. Is it acceptable to remove these lines?

    If I uncomment them I get a DATA_LENGTH error.

    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = m_enc_scan_response_data,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };
    /**@brief Struct that contains pointers to the encoded advertising data for extended advertising types. */
    static ble_gap_adv_data_t m_adv_data_ext =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = NULL,//m_enc_scan_response_data,
            .len    = 0//BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };

    static void advertising_init(void){
    
        ret_code_t    err_code;
        ble_advdata_t advdata;
        ble_advdata_t srdata;
    
        ble_uuid_t adv_uuids[] = {{CTCWS_UUID_CONFIG_SERVICE, m_ctcws.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        if (tx_rate != BLE_GAP_PHY_CODED){  //anything other than coded
    
            err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
            APP_ERROR_CHECK(err_code);
    
            ble_gap_adv_params_t adv_params;
    
            // Set advertising parameters.
            memset(&adv_params, 0, sizeof(adv_params));
    
            adv_params.primary_phy      = BLE_GAP_PHY_1MBPS;
            adv_params.primary_phy      = BLE_GAP_PHY_1MBPS;
            adv_params.duration         = advertise_timeout;
            adv_params.properties.type  = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
            adv_params.p_peer_addr      = NULL;
            adv_params.filter_policy    = BLE_GAP_ADV_FP_ANY;
            adv_params.interval         = advertise_interval;
    
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
            APP_ERROR_CHECK(err_code);
    
            #ifdef DEBUG
            printf("Advertising at 1Mbps\r\n");
            #endif
    
        }//tx_rate != BLE_GAP_PHY_CODED
    
        else{ //tx_rate == BLE_GAP_PHY_CODED
    
            //err_code = ble_advdata_encode(&srdata, m_adv_data_ext.scan_rsp_data.p_data, &m_adv_data_ext.scan_rsp_data.len);
            //APP_ERROR_CHECK(err_code);
    
            ble_gap_adv_params_t adv_params;
    
            // Set advertising parameters.
            memset(&adv_params, 0, sizeof(adv_params));
    
            adv_params.primary_phy      = BLE_GAP_PHY_CODED;
            adv_params.primary_phy      = BLE_GAP_PHY_CODED;
            adv_params.duration         = advertise_timeout;
            adv_params.properties.type  = BLE_GAP_ADV_TYPE_EXTENDED_CONNECTABLE_NONSCANNABLE_UNDIRECTED;
            adv_params.p_peer_addr      = NULL;
            adv_params.filter_policy    = BLE_GAP_ADV_FP_ANY;
            adv_params.interval         = advertise_interval;
    
            err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data_ext, &adv_params);
            APP_ERROR_CHECK(err_code);
    
            #ifdef DEBUG
            printf("Advertising at 125kbps CODED\r\n");
            #endif
    
        }//tx_rate == BLE_GAP_PHY_CODED
    
        err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_adv_handle, tx_power);
        APP_ERROR_CHECK(err_code);
    
        #ifdef DEBUG
        printf("advertising_init\r\n");
        #endif
    }

Children
Related