From abd1d047dd4f6e6639cdfbd170b8550b6319a241 Mon Sep 17 00:00:00 2001 From: Andrei Stoica Date: Tue, 22 Oct 2019 13:13:24 +0200 Subject: [PATCH] Bluetooth: controller: enable dynamic TXP over LL_SPLIT arch (#17731) This commit targets solving issue #17731 over the LL_SW_SPLIT arch of the BLE stack in Zephyr. This functionality is exposed to the user as HCI Zephyr Command extensions - BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL - BT_HCI_OP_VS_READ_TX_POWER_LEVEL which enable Tx power read/write operations within BLE radio events on a per role/connection basis. The functionality is enabled upon the Kconfig advanced configuration triggered by - BT_CTLR_TX_PWR_DYNAMIC_CONTROL depending on the enablement of Zephyr HCI vendor-specific command extensions. Necessary low-level radio HAL functionality and power definitions are also supplied to address the high-level functionality of controlling the Tx power. Signed-off-by: Andrei Stoica --- boards/posix/nrf52_bsim/radio_sim_nrfxx.h | 46 ++++ include/bluetooth/hci_vs.h | 31 +++ subsys/bluetooth/controller/Kconfig | 8 + subsys/bluetooth/controller/hci/hci.c | 60 +++++- subsys/bluetooth/controller/include/ll.h | 5 +- subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c | 199 ++++++++++++++++-- subsys/bluetooth/controller/ll_sw/lll.h | 3 + subsys/bluetooth/controller/ll_sw/lll_conn.h | 5 + .../ll_sw/nordic/hal/nrf5/radio/radio.c | 19 +- .../ll_sw/nordic/hal/nrf5/radio/radio.h | 5 +- .../ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h | 39 ++++ .../nordic/hal/nrf5/radio/radio_nrf52810.h | 43 ++++ .../nordic/hal/nrf5/radio/radio_nrf52811.h | 43 ++++ .../nordic/hal/nrf5/radio/radio_nrf52832.h | 43 ++++ .../nordic/hal/nrf5/radio/radio_nrf52833.h | 63 ++++++ .../nordic/hal/nrf5/radio/radio_nrf52840.h | 63 ++++++ .../nordic/hal/nrf5/radio/radio_nrf5340.h | 59 ++++++ .../controller/ll_sw/nordic/lll/lll.c | 14 ++ .../controller/ll_sw/nordic/lll/lll_adv.c | 5 +- .../controller/ll_sw/nordic/lll/lll_adv.h | 4 + .../controller/ll_sw/nordic/lll/lll_master.c | 6 +- .../controller/ll_sw/nordic/lll/lll_scan.c | 5 +- .../controller/ll_sw/nordic/lll/lll_scan.h | 4 + .../controller/ll_sw/nordic/lll/lll_slave.c | 5 +- subsys/bluetooth/controller/ll_sw/ull_adv.c | 8 + .../bluetooth/controller/ll_sw/ull_master.c | 10 + subsys/bluetooth/controller/ll_sw/ull_scan.c | 5 + subsys/bluetooth/controller/ll_sw/ull_slave.c | 5 + 28 files changed, 776 insertions(+), 29 deletions(-) diff --git a/boards/posix/nrf52_bsim/radio_sim_nrfxx.h b/boards/posix/nrf52_bsim/radio_sim_nrfxx.h index 9b9dce9a64f..980b9c70319 100644 --- a/boards/posix/nrf52_bsim/radio_sim_nrfxx.h +++ b/boards/posix/nrf52_bsim/radio_sim_nrfxx.h @@ -225,11 +225,57 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg30dBm) { + return RADIO_TXPOWER_TXPOWER_Neg30dBm; + } + + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { ARG_UNUSED(flags); diff --git a/include/bluetooth/hci_vs.h b/include/bluetooth/hci_vs.h index cdfbf6e22b2..b8c36deac02 100644 --- a/include/bluetooth/hci_vs.h +++ b/include/bluetooth/hci_vs.h @@ -130,6 +130,37 @@ struct bt_hci_cp_vs_set_scan_req_reports { u8_t enable; } __packed; +#define BT_HCI_VS_LL_HANDLE_TYPE_ADV 0x00 +#define BT_HCI_VS_LL_HANDLE_TYPE_SCAN 0x01 +#define BT_HCI_VS_LL_HANDLE_TYPE_CONN 0x02 +#define BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF 0x7F +#define BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000e) +struct bt_hci_cp_vs_write_tx_power_level { + u8_t handle_type; + u16_t handle; + s8_t tx_power_level; +} __packed; + +struct bt_hci_rp_vs_write_tx_power_level { + u8_t status; + u8_t handle_type; + u16_t handle; + s8_t selected_tx_power; +} __packed; + +#define BT_HCI_OP_VS_READ_TX_POWER_LEVEL BT_OP(BT_OGF_VS, 0x000f) +struct bt_hci_cp_vs_read_tx_power_level { + u8_t handle_type; + u16_t handle; +} __packed; + +struct bt_hci_rp_vs_read_tx_power_level { + u8_t status; + u8_t handle_type; + u16_t handle; + s8_t tx_power_level; +} __packed; + /* Events */ struct bt_hci_evt_vs { diff --git a/subsys/bluetooth/controller/Kconfig b/subsys/bluetooth/controller/Kconfig index 705577012f9..1afb8ea5ac2 100644 --- a/subsys/bluetooth/controller/Kconfig +++ b/subsys/bluetooth/controller/Kconfig @@ -289,6 +289,14 @@ config BT_CTLR_TX_PWR_MINUS_40 endchoice +config BT_CTLR_TX_PWR_DYNAMIC_CONTROL + bool "Tx Power Dynamic Control" + depends on BT_HCI_VS_EXT + help + Enable dynamic control of Tx power per role/connection. + Provides HCI VS commands to set and get the current Tx + power on an individual role/connection basis. + config BT_CTLR_SETTINGS bool "Settings System" depends on BT_SETTINGS diff --git a/subsys/bluetooth/controller/hci/hci.c b/subsys/bluetooth/controller/hci/hci.c index 997ed7164aa..fdf232a75ee 100644 --- a/subsys/bluetooth/controller/hci/hci.c +++ b/subsys/bluetooth/controller/hci/hci.c @@ -449,7 +449,8 @@ static void read_tx_power_level(struct net_buf *buf, struct net_buf **evt) rp = hci_cmd_complete(evt, sizeof(*rp)); - status = ll_tx_pwr_lvl_get(handle, type, &rp->tx_power_level); + status = ll_tx_pwr_lvl_get(BT_HCI_VS_LL_HANDLE_TYPE_CONN, + handle, type, &rp->tx_power_level); rp->status = status; rp->handle = sys_cpu_to_le16(handle); @@ -1866,6 +1867,10 @@ static void vs_read_supported_commands(struct net_buf *buf, rp->commands[0] |= BIT(5) | BIT(7); /* Read Static Addresses, Read Key Hierarchy Roots */ rp->commands[1] |= BIT(0) | BIT(1); +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + /* Write Tx Power, Read Tx Power */ + rp->commands[1] |= BIT(5) | BIT(6); +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ #endif /* CONFIG_BT_HCI_VS_EXT */ } @@ -1998,6 +2003,49 @@ static void vs_read_key_hierarchy_roots(struct net_buf *buf, (void)memset(rp->er, 0x00, sizeof(rp->er)); #endif /* CONFIG_SOC_FAMILY_NRF */ } + +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) +static void vs_write_tx_power_level(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_vs_write_tx_power_level *cmd = (void *)buf->data; + struct bt_hci_rp_vs_write_tx_power_level *rp; + u8_t handle_type; + u16_t handle; + u8_t status; + + handle_type = cmd->handle_type; + handle = sys_le16_to_cpu(cmd->handle); + + rp = hci_cmd_complete(evt, sizeof(*rp)); + rp->selected_tx_power = cmd->tx_power_level; + + status = ll_tx_pwr_lvl_set(handle_type, handle, &rp->selected_tx_power); + + rp->status = status; + rp->handle_type = handle_type; + rp->handle = sys_cpu_to_le16(handle); +} + +static void vs_read_tx_power_level(struct net_buf *buf, struct net_buf **evt) +{ + struct bt_hci_cp_vs_read_tx_power_level *cmd = (void *)buf->data; + struct bt_hci_rp_vs_read_tx_power_level *rp; + u8_t handle_type; + u16_t handle; + u8_t status; + + handle_type = cmd->handle_type; + handle = sys_le16_to_cpu(cmd->handle); + + rp = hci_cmd_complete(evt, sizeof(*rp)); + + status = ll_tx_pwr_lvl_get(handle_type, handle, 0, &rp->tx_power_level); + + rp->status = status; + rp->handle_type = handle_type; + rp->handle = sys_cpu_to_le16(handle); +} +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ #endif /* CONFIG_BT_HCI_VS_EXT */ #if defined(CONFIG_BT_HCI_MESH_EXT) @@ -2184,6 +2232,16 @@ int hci_vendor_cmd_handle_common(u16_t ocf, struct net_buf *cmd, case BT_OCF(BT_HCI_OP_VS_READ_KEY_HIERARCHY_ROOTS): vs_read_key_hierarchy_roots(cmd, evt); break; + +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + case BT_OCF(BT_HCI_OP_VS_WRITE_TX_POWER_LEVEL): + vs_write_tx_power_level(cmd, evt); + break; + + case BT_OCF(BT_HCI_OP_VS_READ_TX_POWER_LEVEL): + vs_read_tx_power_level(cmd, evt); + break; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ #endif /* CONFIG_BT_HCI_VS_EXT */ #if defined(CONFIG_BT_HCI_MESH_EXT) diff --git a/subsys/bluetooth/controller/include/ll.h b/subsys/bluetooth/controller/include/ll.h index 10dd175ebb8..6a37ed70101 100644 --- a/subsys/bluetooth/controller/include/ll.h +++ b/subsys/bluetooth/controller/include/ll.h @@ -81,8 +81,11 @@ u8_t ll_feature_req_send(u16_t handle); u8_t ll_version_ind_send(u16_t handle); u8_t ll_terminate_ind_send(u16_t handle, u8_t reason); u8_t ll_rssi_get(u16_t handle, u8_t *rssi); -u8_t ll_tx_pwr_lvl_get(u16_t handle, u8_t type, s8_t *tx_pwr_lvl); +u8_t ll_tx_pwr_lvl_get(u8_t handle_type, + u16_t handle, u8_t type, s8_t *tx_pwr_lvl); void ll_tx_pwr_get(s8_t *min, s8_t *max); +u8_t ll_tx_pwr_lvl_set(u8_t handle_type, + u16_t handle, s8_t *tx_pwr_lvl); u8_t ll_apto_get(u16_t handle, u16_t *apto); u8_t ll_apto_set(u16_t handle, u16_t apto); diff --git a/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c b/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c index b0e106d8acd..c2f4632d4f7 100644 --- a/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c +++ b/subsys/bluetooth/controller/ll_sw/ll_tx_pwr.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "hal/ccm.h" #include "hal/radio.h" @@ -17,36 +18,194 @@ #include "pdu.h" +#include "ll.h" #include "lll.h" -#include "lll_conn.h" -#include "ull_conn_internal.h" #if defined(CONFIG_BT_LL_SW_SPLIT) -u8_t ll_tx_pwr_lvl_get(u16_t handle, u8_t type, s8_t *tx_pwr_lvl) -{ - struct ll_conn *conn; +#include "util/util.h" - conn = ll_connected_get(handle); - if (!conn) { - return BT_HCI_ERR_UNKNOWN_CONN_ID; +#include "lll_scan.h" +#include "ull_scan_types.h" +#include "ull_scan_internal.h" +#include "lll_adv.h" +#include "ull_adv_types.h" +#include "ull_adv_internal.h" +#include "lll_conn.h" +#include "ull_conn_types.h" +#include "ull_conn_internal.h" + +u8_t ll_tx_pwr_lvl_get(u8_t handle_type, + u16_t handle, u8_t type, s8_t *tx_pwr_lvl) +{ + switch (handle_type) { +#if defined(CONFIG_BT_BROADCASTER) &&\ + defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): { + struct ll_adv_set *adv; + +#if !defined(CONFIG_BT_CTLR_ADV_EXT) + /* Ignore handle if AE not enabled */ + handle = 0; +#endif /* CONFIG_BT_CTLR_ADV_EXT */ + /* Allow the app to get Tx power + * when advertising is off + */ + adv = ull_adv_set_get(handle); + if (!adv) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + *tx_pwr_lvl = adv->lll.tx_pwr_lvl; + break; + } +#endif /* CONFIG_BT_BROADCASTER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ +#if defined(CONFIG_BT_OBSERVER) &&\ + defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): { + struct ll_scan_set *scan; + + /* Ignore handle in case of scanner + * as for mesh extensions and scanning + * sets this control is handled + * at a lower-level in the stack. + */ + handle = 0; + /* Allow the app to get Tx power + * when scanning is off + */ + scan = ull_scan_set_get(handle); + if (!scan) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + *tx_pwr_lvl = scan->lll.tx_pwr_lvl; + break; + } +#endif /* CONFIG_BT_OBSERVER && CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL*/ +#if defined(CONFIG_BT_CONN) + case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): { + struct ll_conn *conn; + + conn = ll_connected_get(handle); + if (!conn) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + + if (type) { +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + /* Level desired is maximum available */ + *tx_pwr_lvl = lll_radio_tx_pwr_max_get(); +#else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* Return default if not multiple TXP */ + *tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + } else { +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + /* Current level is requested */ + *tx_pwr_lvl = conn->lll.tx_pwr_lvl; +#else /* !CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* Return default if not multiple TXP */ + *tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + } + break; + } +#endif /* CONFIG_BT_CONN */ + default: { + return BT_HCI_ERR_UNKNOWN_CMD; + } } - /* TODO: check type here for current or maximum */ - - /* TODO: Support TX Power Level other than default when dynamic - * updates is implemented. - */ - *tx_pwr_lvl = RADIO_TXP_DEFAULT; - - return 0; + return BT_HCI_ERR_SUCCESS; } -#endif + + +u8_t ll_tx_pwr_lvl_set(u8_t handle_type, u16_t handle, + s8_t *tx_pwr_lvl) +{ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + if (*tx_pwr_lvl == BT_HCI_VS_LL_TX_POWER_LEVEL_NO_PREF) { + /* If no preference selected, then use default Tx power */ + *tx_pwr_lvl = RADIO_TXP_DEFAULT; + } + + /** + * Check that desired Tx power matches the achievable transceiver + * Tx power capabilities by flooring - if selected power matches than + * is used, otherwise next smaller power available is used. + */ + *tx_pwr_lvl = lll_radio_tx_pwr_floor(*tx_pwr_lvl); +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + + switch (handle_type) { +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) +#if defined(CONFIG_BT_BROADCASTER) + case (BT_HCI_VS_LL_HANDLE_TYPE_ADV): { + struct ll_adv_set *adv; + +#if !defined(CONFIG_BT_CTLR_ADV_EXT) + /* Ignore handle if AE not enabled */ + handle = 0; +#endif /* CONFIG_BT_CTLR_ADV_EXT */ + /* Allow the app to set Tx power + * prior to advertising + */ + adv = ull_adv_set_get(handle); + if (!adv) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + adv->lll.tx_pwr_lvl = *tx_pwr_lvl; + break; + } +#endif /* CONFIG_BT_BROADCASTER */ +#if defined(CONFIG_BT_OBSERVER) + case (BT_HCI_VS_LL_HANDLE_TYPE_SCAN): { + struct ll_scan_set *scan; + + /* Ignore handle in case of scanner + * as for mesh extensions and scanning + * sets this control is handled + * at a lower-level in the stack. + */ + handle = 0; + /* Allow the app to set Tx power + * prior to scanning + */ + scan = ull_scan_set_get(handle); + if (!scan) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + scan->lll.tx_pwr_lvl = *tx_pwr_lvl; + break; + } +#endif /* CONFIG_BT_OBSERVER */ +#if defined(CONFIG_BT_CONN) + case (BT_HCI_VS_LL_HANDLE_TYPE_CONN): { + struct ll_conn *conn; + + conn = ll_connected_get(handle); + if (!conn) { + return BT_HCI_ERR_UNKNOWN_CONN_ID; + } + conn->lll.tx_pwr_lvl = *tx_pwr_lvl; + break; + } +#endif /* CONFIG_BT_CONN */ +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + default: { + return BT_HCI_ERR_UNKNOWN_CMD; + } + } + + return BT_HCI_ERR_SUCCESS; +} +#endif /* CONFIG_BT_LL_SW_SPLIT */ void ll_tx_pwr_get(s8_t *min, s8_t *max) { - /* TODO: Support TX Power Level other than default when dynamic - * updates is implemented. - */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + *min = lll_radio_tx_pwr_min_get(); + *max = lll_radio_tx_pwr_max_get(); +#else *min = RADIO_TXP_DEFAULT; *max = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ } diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h index 1fd718c1bc3..71396cd31f2 100644 --- a/subsys/bluetooth/controller/ll_sw/lll.h +++ b/subsys/bluetooth/controller/ll_sw/lll.h @@ -300,6 +300,9 @@ int lll_prepare(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, void lll_resume(void *param); void lll_disable(void *param); u32_t lll_radio_is_idle(void); +s8_t lll_radio_tx_pwr_min_get(void); +s8_t lll_radio_tx_pwr_max_get(void); +s8_t lll_radio_tx_pwr_floor(s8_t tx_pwr_lvl); int ull_prepare_enqueue(lll_is_abort_cb_t is_abort_cb, lll_abort_cb_t abort_cb, diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn.h b/subsys/bluetooth/controller/ll_sw/lll_conn.h index 3fde531a60d..4d73fe12318 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn.h @@ -112,10 +112,15 @@ struct lll_conn { #if defined(CONFIG_BT_CTLR_CONN_META) struct lll_conn_meta conn_meta; #endif /* CONFIG_BT_CTLR_CONN_META */ + +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + s8_t tx_pwr_lvl; +#endif }; int lll_conn_init(void); int lll_conn_reset(void); + u8_t lll_conn_sca_local_get(void); u32_t lll_conn_ppm_local_get(void); u32_t lll_conn_ppm_get(u8_t sca); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c index 9ad63102518..adf6816ee37 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.c @@ -140,10 +140,10 @@ void radio_phy_set(u8_t phy, u8_t flags) #endif /* CONFIG_BT_CTLR_RADIO_ENABLE_FAST */ } -void radio_tx_power_set(u32_t power) +void radio_tx_power_set(s8_t power) { /* NOTE: valid value range is passed by Kconfig define. */ - NRF_RADIO->TXPOWER = power; + NRF_RADIO->TXPOWER = (u32_t)power; } void radio_tx_power_max_set(void) @@ -151,6 +151,21 @@ void radio_tx_power_max_set(void) NRF_RADIO->TXPOWER = hal_radio_tx_power_max_get(); } +s8_t radio_tx_power_min_get(void) +{ + return (s8_t)hal_radio_tx_power_min_get(); +} + +s8_t radio_tx_power_max_get(void) +{ + return (s8_t)hal_radio_tx_power_max_get(); +} + +s8_t radio_tx_power_floor(s8_t power) +{ + return (s8_t)hal_radio_tx_power_floor(power); +} + void radio_freq_chan_set(u32_t chan) { NRF_RADIO->FREQUENCY = chan; diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h index 444a9f237d0..de289a96399 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio.h @@ -13,8 +13,11 @@ void radio_isr_set(radio_isr_cb_t cb, void *param); void radio_setup(void); void radio_reset(void); void radio_phy_set(u8_t phy, u8_t flags); -void radio_tx_power_set(u32_t power); +void radio_tx_power_set(s8_t power); void radio_tx_power_max_set(void); +s8_t radio_tx_power_min_get(void); +s8_t radio_tx_power_max_get(void); +s8_t radio_tx_power_floor(s8_t power); void radio_freq_chan_set(u32_t chan); void radio_whiten_iv_set(u32_t iv); void radio_aa_set(u8_t *aa); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h index 09fc59c7253..5e80318704f 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf51.h @@ -50,11 +50,50 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg30dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { ARG_UNUSED(phy); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h index 215cfea69e0..8e858d14feb 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52810.h @@ -256,11 +256,54 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { ARG_UNUSED(flags); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h index d87d5bdd197..22deb0710f7 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52811.h @@ -450,11 +450,54 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { switch (phy) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h index 62f6d1eeee5..646598f2cfe 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52832.h @@ -260,11 +260,54 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos4dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { ARG_UNUSED(flags); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h index 9cd1e83e13b..f5bd4535c2e 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52833.h @@ -430,11 +430,74 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos8dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { + return RADIO_TXPOWER_TXPOWER_Pos8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { + return RADIO_TXPOWER_TXPOWER_Pos7dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { + return RADIO_TXPOWER_TXPOWER_Pos6dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { + return RADIO_TXPOWER_TXPOWER_Pos5dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) { + return RADIO_TXPOWER_TXPOWER_Pos2dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { switch (phy) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h index 06414e4bc95..a303e2024e8 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf52840.h @@ -451,11 +451,74 @@ static inline u32_t hal_radio_phy_mode_get(u8_t phy, u8_t flags) return mode; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_power_max_get(void) { return RADIO_TXPOWER_TXPOWER_Pos8dBm; } +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos8dBm) { + return RADIO_TXPOWER_TXPOWER_Pos8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos7dBm) { + return RADIO_TXPOWER_TXPOWER_Pos7dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos6dBm) { + return RADIO_TXPOWER_TXPOWER_Pos6dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos5dBm) { + return RADIO_TXPOWER_TXPOWER_Pos5dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos4dBm) { + return RADIO_TXPOWER_TXPOWER_Pos4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos3dBm) { + return RADIO_TXPOWER_TXPOWER_Pos3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Pos2dBm) { + return RADIO_TXPOWER_TXPOWER_Pos2dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { switch (phy) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h index c2677f36511..6ebdd66825c 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/hal/nrf5/radio/radio_nrf5340.h @@ -404,6 +404,65 @@ static inline u32_t hal_radio_tx_power_max_get(void) return RADIO_TXPOWER_TXPOWER_0dBm; } +static inline u32_t hal_radio_tx_power_min_get(void) +{ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + +static inline u32_t hal_radio_tx_power_floor(s8_t tx_power_lvl) +{ + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_0dBm) { + return RADIO_TXPOWER_TXPOWER_0dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) { + return RADIO_TXPOWER_TXPOWER_Neg1dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) { + return RADIO_TXPOWER_TXPOWER_Neg2dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg3dBm) { + return RADIO_TXPOWER_TXPOWER_Neg3dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg4dBm) { + return RADIO_TXPOWER_TXPOWER_Neg4dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg5dBm) { + return RADIO_TXPOWER_TXPOWER_Neg5dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg6dBm) { + return RADIO_TXPOWER_TXPOWER_Neg6dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg7dBm) { + return RADIO_TXPOWER_TXPOWER_Neg7dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm) { + return RADIO_TXPOWER_TXPOWER_Neg8dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { + return RADIO_TXPOWER_TXPOWER_Neg12dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { + return RADIO_TXPOWER_TXPOWER_Neg16dBm; + } + + if (tx_power_lvl >= (s8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { + return RADIO_TXPOWER_TXPOWER_Neg20dBm; + } + + /* Note: The -30 dBm power level is deprecated so ignore it! */ + return RADIO_TXPOWER_TXPOWER_Neg40dBm; +} + static inline u32_t hal_radio_tx_ready_delay_us_get(u8_t phy, u8_t flags) { switch (phy) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c index fba3d5d49d4..e844ffbe60d 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll.c @@ -432,6 +432,20 @@ u32_t lll_radio_is_idle(void) return radio_is_idle(); } +s8_t lll_radio_tx_pwr_min_get(void) +{ + return radio_tx_power_min_get(); +} + +s8_t lll_radio_tx_pwr_max_get(void) +{ + return radio_tx_power_max_get(); +} + +s8_t lll_radio_tx_pwr_floor(s8_t tx_pwr_lvl) +{ + return radio_tx_power_floor(tx_pwr_lvl); +} static int init_reset(void) { diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c index bfec9531470..a1ec32d8cb0 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.c @@ -144,8 +144,11 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) } radio_reset(); - /* TODO: other Tx Power settings */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + radio_tx_power_set(lll->tx_pwr_lvl); +#else radio_tx_power_set(RADIO_TXP_DEFAULT); +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ #if defined(CONFIG_BT_CTLR_ADV_EXT) /* TODO: if coded we use S8? */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h index ba04eca58d4..18439ca02fe 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_adv.h @@ -40,6 +40,10 @@ struct lll_adv { struct lll_adv_pdu adv_data; struct lll_adv_pdu scan_rsp; + +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + s8_t tx_pwr_lvl; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ }; int lll_adv_init(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c index 2829bf92da5..97c859d4445 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_master.c @@ -139,8 +139,12 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) /* Start setting up of Radio h/w */ radio_reset(); - /* TODO: other Tx Power settings */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + radio_tx_power_set(lll->tx_pwr_lvl); +#else radio_tx_power_set(RADIO_TXP_DEFAULT); +#endif + radio_aa_set(lll->access_addr); radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)), (((u32_t)lll->crc_init[2] << 16) | diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c index 87a9279becb..69eead38941 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.c @@ -147,8 +147,11 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) LL_ASSERT(node_rx); radio_reset(); - /* TODO: other Tx Power settings */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + radio_tx_power_set(lll->tx_pwr_lvl); +#else radio_tx_power_set(RADIO_TXP_DEFAULT); +#endif #if defined(CONFIG_BT_CTLR_ADV_EXT) /* TODO: if coded we use S8? */ diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.h b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.h index aac68ec15d5..e8d83304929 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.h +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_scan.h @@ -37,6 +37,10 @@ struct lll_scan { u16_t interval; u32_t ticks_window; + +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + s8_t tx_pwr_lvl; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ }; int lll_scan_init(void); diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c index d0e56e6b3b0..5bf2531e8ae 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_slave.c @@ -160,8 +160,11 @@ static int prepare_cb(struct lll_prepare_param *prepare_param) /* Start setting up Radio h/w */ radio_reset(); - /* TODO: other Tx Power settings */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + radio_tx_power_set(lll->tx_pwr_lvl); +#else radio_tx_power_set(RADIO_TXP_DEFAULT); +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ lll_conn_rx_pkt_set(lll); diff --git a/subsys/bluetooth/controller/ll_sw/ull_adv.c b/subsys/bluetooth/controller/ll_sw/ull_adv.c index b372ad9bd76..ad99b6c772d 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_adv.c +++ b/subsys/bluetooth/controller/ll_sw/ull_adv.c @@ -12,6 +12,7 @@ #include "hal/ccm.h" #include "hal/ticker.h" +#include "hal/radio.h" #include "util/util.h" #include "util/mem.h" @@ -446,6 +447,9 @@ u8_t ll_adv_enable(u8_t enable) } lll = &adv->lll; +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ pdu_adv = lll_adv_data_peek(lll); if (pdu_adv->tx_addr) { @@ -597,6 +601,10 @@ u8_t ll_adv_enable(u8_t enable) conn_lll->rssi_sample_count = 0; #endif /* CONFIG_BT_CTLR_CONN_RSSI */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + conn_lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* FIXME: BEGIN: Move to ULL? */ conn_lll->role = 1; conn_lll->data_chan_sel = 0; diff --git a/subsys/bluetooth/controller/ll_sw/ull_master.c b/subsys/bluetooth/controller/ll_sw/ull_master.c index 6d6ae383894..f4add5aa433 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_master.c +++ b/subsys/bluetooth/controller/ll_sw/ull_master.c @@ -14,6 +14,8 @@ #include "hal/ticker.h" #include "hal/ccm.h" +#include "hal/radio.h" + #include "ticker/ticker.h" #include "pdu.h" @@ -142,6 +144,10 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window, conn_lll->rssi_sample_count = 0; #endif /* CONFIG_BT_CTLR_CONN_RSSI */ +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + conn_lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* FIXME: BEGIN: Move to ULL? */ conn_lll->latency_prepare = 0; conn_lll->latency_event = 0; @@ -481,6 +487,10 @@ void ull_master_setup(memq_link_t *link, struct node_rx_hdr *rx, lll->handle = ll_conn_handle_get(conn); rx->handle = lll->handle; +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* Use Channel Selection Algorithm #2 if peer too supports it */ if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) { struct node_rx_pdu *rx_csa; diff --git a/subsys/bluetooth/controller/ll_sw/ull_scan.c b/subsys/bluetooth/controller/ll_sw/ull_scan.c index 1b7cbf0961f..8345b4519ea 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_scan.c +++ b/subsys/bluetooth/controller/ll_sw/ull_scan.c @@ -10,6 +10,7 @@ #include "hal/ccm.h" #include "hal/ticker.h" +#include "hal/radio.h" #include "util/util.h" #include "util/mem.h" @@ -175,6 +176,10 @@ u8_t ull_scan_enable(struct ll_scan_set *scan) lll->init_addr_type = scan->own_addr_type; ll_addr_get(lll->init_addr_type, lll->init_addr); +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + ull_hdr_init(&scan->ull); lll_hdr_init(lll, scan); diff --git a/subsys/bluetooth/controller/ll_sw/ull_slave.c b/subsys/bluetooth/controller/ll_sw/ull_slave.c index a1e250bc3cf..29a6ee46150 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_slave.c +++ b/subsys/bluetooth/controller/ll_sw/ull_slave.c @@ -14,6 +14,7 @@ #include "hal/ticker.h" #include "hal/ccm.h" +#include "hal/radio.h" #include "ticker/ticker.h" @@ -167,6 +168,10 @@ void ull_slave_setup(memq_link_t *link, struct node_rx_hdr *rx, lll->handle = ll_conn_handle_get(conn); rx->handle = lll->handle; +#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) + lll->tx_pwr_lvl = RADIO_TXP_DEFAULT; +#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */ + /* Use Channel Selection Algorithm #2 if peer too supports it */ if (IS_ENABLED(CONFIG_BT_CTLR_CHAN_SEL_2)) { struct node_rx_pdu *rx_csa;