How to use Directed advertising (high duty cycle) in Zephyr development?

Greetings,

Previously we were developing with the nRF5 SDK. At that time, we were able to execute high duty cycle directed advertising with the following code. Using this, the advertising interval would be less than 3.75 ms.

err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY);

Now we are developing with zephyr OS and would like to know how to achieve the above implementation. If you know of any useful information, I would appreciate it if you could share it with us.

  • Sorry for my late reply again.

    I found there is a function "sdc_hci_cmd_le_set_adv_params" & "start_high_duty_directed_adv" in ncs\v2.1.1\nrfxlib\softdevice_controller\include\sdc_hci_cmd_le.h .

    So I wrote a simple code and tried to use these function, but I got the following error.

    00> [00:00:00.000,244] <dbg> main: main: Starting Broadcaster
    00> [00:00:00.000,366] <inf> sdc_hci_driver: SoftDevice Controller build revision: 
    00>                                          f2 e7 5f 6f 23 a2 f3 e8  10 2f c3 35 9e d7 1d fe |.._o#... ./.5....
    00>                                          8f 80 42 f9                                      |..B.             
    00> [00:01:02.758,544] <dbg> main: connected: connected
    00> [00:01:03.371,765] <wrn> bt_l2cap: Ignoring data for unknown channel ID 0x003a
    00> [00:01:07.061,920] <dbg> main: disconnected: Disconnected (reason 0x13)
    00> [00:01:07.061,981] <dbg> main: set_high_duty_adv_params: Set adv params.
    00> [00:01:07.062,103] <dbg> main: start_high_duty_directed_adv: 
    00> [00:01:08.342,895] <err> bt_hci_core: No pending peripheral connection

    Here is the code I wrote. 

    #include <stddef.h>
    #include <zephyr/sys/printk.h>
    #include <zephyr/sys/util.h>
    #include <zephyr/types.h>
    
    #include <zephyr/bluetooth/addr.h>
    #include <zephyr/bluetooth/bluetooth.h>
    #include <zephyr/bluetooth/hci.h>
    
    #include "sdc_hci_cmd_le.h"
    
    #define MODULE main
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(MODULE);
    
    static uint8_t mfg_data[] = {0xff, 0xff, 0x00};
    
    static const struct bt_data ad[] = {
    	BT_DATA(BT_DATA_MANUFACTURER_DATA, mfg_data, 3),
    };
    
    static void connected(struct bt_conn *conn, uint8_t err)
    {
    	if (err)
    	{
    		LOG_DBG("connection failed: %u", err);
    		return;
    	}
    	LOG_DBG("connected");
    	bt_le_adv_stop();
    }
    
    static void set_high_duty_adv_params(const bt_addr_le_t *addr)
    {
    	int err;
    	sdc_hci_cmd_le_set_adv_params_t adv_params;
    
    	adv_params.adv_type = 0x01;
    	adv_params.own_address_type = BT_ADDR_LE_RANDOM;
    	adv_params.peer_address_type = addr->type;
    	for (uint8_t i = 0; i < BT_ADDR_SIZE; i++)
    	{
    		adv_params.peer_address[i] = addr->a.val[i];
    	}
    	adv_params.adv_channel_map = 0b00000111;
    
    	err = sdc_hci_cmd_le_set_adv_params(&adv_params);
    	if (err)
    	{
    		LOG_WRN("Failed to set adv params(err:0x%x)", err);
    		return;
    	}
    	LOG_DBG("Set adv params.");
    }
    
    static void start_high_duty_directed_adv(const bt_addr_le_t *peer)
    {
    	int err;
    
    	set_high_duty_adv_params(peer);
    	sdc_hci_cmd_le_set_adv_enable_t adv_enable;
    	adv_enable.adv_enable = 1;
    	err = sdc_hci_cmd_le_set_adv_enable(&adv_enable);
    
    	if (err)
    	{
    		LOG_ERR("Failed to set adv params(err:0x%x)", err);
    		return;
    	}
    	LOG_DBG("");
    }
    
    static void disconnected(struct bt_conn *conn, uint8_t reason)
    {
    	LOG_DBG("Disconnected (reason 0x%02x)", reason);
    	struct bt_conn_info info;
    	bt_addr_le_t peer_addr;
    	bt_conn_get_info(conn, &info);
    	bt_addr_le_copy(&peer_addr, info.le.remote);
    	start_high_duty_directed_adv(&peer_addr);
    }
    
    BT_CONN_CB_DEFINE(conn_callbacks) = {.connected = connected,
    									 .disconnected = disconnected};
    
    void main(void)
    {
    	int err;
    
    	LOG_DBG("Starting Broadcaster");
    
    	/* Initialize the Bluetooth Subsystem */
    	err = bt_enable(NULL);
    	if (err)
    	{
    		LOG_DBG("Bluetooth init failed (err %d)", err);
    		return;
    	}
    
    	bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad),
    					NULL, 0);
    }

    I can't get how to fix this. Could you help me?

  • I used nRF Connect mobile app as a central.

  • Hi 

    Typically you should not call the sdc functions directly, unless you need to access unique features in the SoftDevice controller that are not supported by the Zephyr host. 

    Did you try to do this using the normal Bluetooth API as I described earlier? 

    Best regards
    Torbjørn

Related