on 2025-01-28 04:06 AM
In this article, we provide a method to modify TX power levels as available in the STM32CubeWBA using ACI_HAL_SET_TX_POWER_LEVEL and read power levels like HCI_READ_TRANSMIT_POWER_LEVEL. This method is implemented usjng the Zephyr example peripheral_hr using the Nucleo-WBA55CG.
The modified version of the main.c file is attached at the end of the article.
First, open the main.c of the peripheral_hr example then replace the original code with the new one accordingly:
Original code line 17-22
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/bluetooth/services/hrs.h>
static bool hrf_ntf_enabled;
New code line 17-38
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/services/bas.h>
#include <zephyr/bluetooth/services/hrs.h>
#include <zephyr/sys/byteorder.h>
static struct bt_conn *default_conn;
static uint16_t default_conn_handle;
#define ACI_HAL_SET_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0xFC0F)
struct aci_set_tx_power {
uint8_t cmd;
uint8_t value[2];
};
struct aci_set_tx_power *param;
struct net_buf *buf, *rsp;
struct bt_hci_cp_read_tx_power_level *param_r;
static bool hrf_ntf_enabled;
Original code line 43-61
#define STATE_CONNECTED 1U
#define STATE_DISCONNECTED 2U
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
printk("Connection failed, err 0x%02x %s\n", err, bt_hci_err_to_str(err));
} else {
printk("Connected\n");
(void)atomic_set_bit(state, STATE_CONNECTED);
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printk("Disconnected, reason 0x%02x %s\n", reason, bt_hci_err_to_str(reason));
(void)atomic_set_bit(state, STATE_DISCONNECTED);
New code line 59-119
#define STATE_CONNECTED 1U
#define STATE_DISCONNECTED 2U
static int get_tx_power(uint16_t handle)
{
int err = 0;
struct bt_hci_rp_read_tx_power_level *rp;
/* HCI_READ_TRANSMIT_POWER_LEVEL */
buf = bt_hci_cmd_create(BT_HCI_OP_READ_TX_POWER_LEVEL, sizeof(*param_r));
if (!buf) {
printk("Failed - buf creation failed \n\r");
return -ENOBUFS;
}
param_r = net_buf_add(buf, sizeof(*param_r));
param_r->handle = sys_cpu_to_le16(handle);
param_r->type = BT_TX_POWER_LEVEL_CURRENT;
err = bt_hci_cmd_send_sync(BT_HCI_OP_READ_TX_POWER_LEVEL, buf, &rsp);
if (err) {
printk("Failed - hci_read_transmit_power_level : %d\n\r", err);
return err;
}
rp = (void *) rsp->data;
printk ("Current TX power level in dBm : %d\n\r",rp->tx_power_level);
net_buf_unref(rsp);
return 0;
}
static void connected(struct bt_conn *conn, uint8_t err)
{
int ret;
if (err) {
printk("Connection failed, err 0x%02x %s\n", err, bt_hci_err_to_str(err));
} else {
printk("Connected\n");
default_conn = bt_conn_ref(conn);
ret = bt_hci_get_conn_handle(default_conn, &default_conn_handle);
(void)atomic_set_bit(state, STATE_CONNECTED);
if(ret) {
printk("No connection handle (err %d)\n", ret);
}
else {
printk("Conn handle : %d\n", default_conn_handle);
get_tx_power(default_conn_handle);
} }
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
bt_conn_unref(conn);
conn = NULL;
printk("Disconnected, reason 0x%02x %s\n", reason, bt_hci_err_to_str(reason));
(void)atomic_set_bit(state, STATE_DISCONNECTED);
Original code line 198-203
printk("Bluetooth initialized\n");
bt_conn_auth_cb_register(&auth_cb_display);
bt_hrs_cb_register(&hrs_cb);
New code line 256-282
printk("Bluetooth initialized\n");
/* Send ACI_HAL_SET_TX_POWER_LEVEL */
buf = bt_hci_cmd_create(ACI_HAL_SET_TX_POWER_LEVEL, 3);
if (!buf) {
return -ENOBUFS;
}
param = net_buf_add(buf, sizeof(*param));
/* See STM32WBA table conversion in Annex A */
param->value[0] = 0x0F;
/* Deprecated and ignored */
param->value[1] = 0x00;
err = bt_hci_cmd_send_sync(ACI_HAL_SET_TX_POWER_LEVEL, buf, &rsp);
if (err) {
printk("Failed - aci_hal_tx_pwr : %d\n\r", err);
return err;
}
else{
printk("Setting PA output level to : 0x%02x \n\r", param->value[0]);
}
net_buf_unref(rsp);
bt_conn_auth_cb_register(&auth_cb_display);
bt_hrs_cb_register(&hrs_cb);
This code sets the desired TX power (-10dBm in this case) and reads the new TX power. If you want to change the TX power to another value, replace the value of "param->value[0]"
/* See STM32WBA table conversion in Annex A */
param->value[0] = 0x0F;
with the value of PA_Level corresponding to the values in dBm you are looking for according to the TX Power Level table in this HTML file. (0x0F is for -10dBm).