How to Set TX Power for Response Packets in periodic_sync_conn?

HI

I am currently using the nRF54L15 chip with NCS 3.2.1, carrying out secondary development based on the periodic_sync_conn sample project. I intend to adjust the transmit (TX) power before the response data is reported. I have found that the function below can be called to modify TX power; however, this function only works for adjusting the TX power of the advertising broadcaster and has no effect on the TX power used for response transmissions. Which function should I invoke to configure the TX power specifically for response packets?

static void set_tx_power(uint8_t handle_type, uint16_t handle, int8_t tx_pwr_lvl)
{
    struct bt_hci_cp_vs_write_tx_power_level *cp;
    struct bt_hci_rp_vs_write_tx_power_level *rp;
    struct net_buf *buf, *rsp = NULL;
    int err;

    buf = bt_hci_cmd_alloc(K_FOREVER);
    if (!buf) {
        printk("Unable to allocate command buffer\n");
        return;
    }

    cp = net_buf_add(buf, sizeof(*cp));
    cp->handle = sys_cpu_to_le16(handle);
    cp->handle_type = handle_type;
    cp->tx_power_level = tx_pwr_lvl;

    err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL,
                   buf, &rsp);
    if (err) {
        printk("Set Tx power err: %d\n", err);
        return;
    }

    rp = (void *)rsp->data;
    printk("Actual Tx Power: %d\n", rp->selected_tx_power);

    net_buf_unref(rsp);
}
Thanks!
Parents
  • Hi Joey!

    To control TX power for PAwR response packets on the sync/responder side, use the same HCI VS command you already have, but change is the handle type:

    • Do not use BT_HCI_VS_LL_HANDLE_TYPE_ADV (0x00) — that only affects advertising.
    • Use SDC_HCI_VS_TX_POWER_HANDLE_TYPE_SYNC (0x03) — this controls TX power for Periodic Sync, including PAwR responses.
    • Handle: the periodic sync HCI handle from bt_hci_get_adv_sync_handle().

    Note: Handle type 0x03 (Periodic Sync) is a Nordic-specific extension added in the SoftDevice Controller (sdc_hci_vs.h). It is not defined in Zephyr’s standard hci_vs.h, which only lists handle types 0x00–0x02 (Advertiser, Scanner/Initiator, Connection).

    Call it after periodic sync is established, and before sending response data with bt_le_per_adv_set_response_data().

    Also, make sure CONFIG_BT_HAS_HCI_VS=y is enabled.

  • Thanks!

    I’ve followed the instructions to add the transmit power configuration to the relevant section. How do I confirm the output power is running at the value I set? Since periodic_sync_conn transmits data for only a very short time, can a spectrum analyzer capture this signal successfully?

  • Capturing the periodic_sync_conn signal directly on a spectrum analyzer would be very difficult, as it only transmits in very short bursts.

    To verify TX output power, we normally recommend flashing the Direct Test Mode (DTM) sample or the Radio Test sample, both of which produce a continuous TX signal that can be reliably captured by a spectrum analyzer. The nRF Connect for Desktop Direct Test Mode app also provides a simple graphical interface for this.

    However, since you most likely want to run your own application during testing, it is more challenging as the DTM and Radio Test approaches do require flashing dedicated test firmware, which temporarily replaces your application. It will require modifications in your case.

    If you only wish to check that the tx power is increasing and decreasing with changing the configuration but not with any precise reading, you can search for your device with the nrf connect app or iOS or android, and check that the RSSI is changed accordingly.

  • Does the transmit power value read out via this function represent the actual RF transmit power being output?

    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_alloc(K_FOREVER);
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            printk("Read Tx power err: %d\n", err);
            return;
        }

        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;

        net_buf_unref(rsp);
    }
Reply
  • Does the transmit power value read out via this function represent the actual RF transmit power being output?

    static void get_tx_power(uint8_t handle_type, uint16_t handle, int8_t *tx_pwr_lvl)
    {
        struct bt_hci_cp_vs_read_tx_power_level *cp;
        struct bt_hci_rp_vs_read_tx_power_level *rp;
        struct net_buf *buf, *rsp = NULL;
        int err;

        *tx_pwr_lvl = 0xFF;
        buf = bt_hci_cmd_alloc(K_FOREVER);
        if (!buf) {
            printk("Unable to allocate command buffer\n");
            return;
        }

        cp = net_buf_add(buf, sizeof(*cp));
        cp->handle = sys_cpu_to_le16(handle);
        cp->handle_type = handle_type;

        err = bt_hci_cmd_send_sync(BT_HCI_OP_VS_READ_TX_POWER_LEVEL,
                       buf, &rsp);
        if (err) {
            printk("Read Tx power err: %d\n", err);
            return;
        }

        rp = (void *)rsp->data;
        *tx_pwr_lvl = rp->tx_power_level;

        net_buf_unref(rsp);
    }
Children
No Data
Related