From eead9c1fe4deafad14108a9ba1858c81a4b3d384 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 22 Jun 2023 16:14:09 +0200 Subject: [PATCH] nimble/phy/nrf5340: Add support for high voltage on RADIO This allows to set few more power levels on PHY (up to +3dBm). --- nimble/drivers/nrf5x/src/ble_phy.c | 2 +- nimble/drivers/nrf5x/src/nrf52/phy.c | 6 +++ nimble/drivers/nrf5x/src/nrf53/phy.c | 77 +++++++++++++++++++++++++++- nimble/drivers/nrf5x/src/phy_priv.h | 1 + nimble/drivers/nrf5x/syscfg.yml | 8 +++ 5 files changed, 91 insertions(+), 3 deletions(-) diff --git a/nimble/drivers/nrf5x/src/ble_phy.c b/nimble/drivers/nrf5x/src/ble_phy.c index 223afbff9..84d2ff5e2 100644 --- a/nimble/drivers/nrf5x/src/ble_phy.c +++ b/nimble/drivers/nrf5x/src/ble_phy.c @@ -2019,7 +2019,7 @@ ble_phy_tx_power_set(int dbm) /* Get actual TX power supported by radio */ dbm = phy_txpower_round(dbm); - NRF_RADIO->TXPOWER = dbm; + phy_txpower_set(dbm); g_ble_phy_data.phy_txpwr_dbm = dbm; return 0; diff --git a/nimble/drivers/nrf5x/src/nrf52/phy.c b/nimble/drivers/nrf5x/src/nrf52/phy.c index 6a6eeb882..30a19966b 100644 --- a/nimble/drivers/nrf5x/src/nrf52/phy.c +++ b/nimble/drivers/nrf5x/src/nrf52/phy.c @@ -179,6 +179,12 @@ phy_ppi_init(void) (uint32_t)&(NRF_RADIO->TASKS_DISABLE)); } +void +phy_txpower_set(int8_t dbm) +{ + NRF_RADIO->TXPOWER = dbm; +} + int8_t phy_txpower_round(int8_t dbm) { diff --git a/nimble/drivers/nrf5x/src/nrf53/phy.c b/nimble/drivers/nrf5x/src/nrf53/phy.c index 831040652..ceda769b0 100644 --- a/nimble/drivers/nrf5x/src/nrf53/phy.c +++ b/nimble/drivers/nrf5x/src/nrf53/phy.c @@ -22,6 +22,14 @@ #include #include "../phy_priv.h" +/* + * When the radio is operated on high voltage (see VREQCTRL - Voltage request + * control on page 62 for how to control voltage), the output power is increased + * by 3 dB. I.e. if the TXPOWER value is set to 0 dBm and high voltage is + * requested using VREQCTRL, the output power will be +3 + * */ +#define NRF_TXPOWER_VREQH 3 + #if PHY_USE_DEBUG void phy_debug_init(void) @@ -180,9 +188,50 @@ phy_ppi_init(void) NRF_TIMER0->SUBSCRIBE_CAPTURE[2] = DPPI_CH_SUB(RADIO_EVENTS_END); } +void +phy_txpower_set(int8_t dbm) +{ +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + switch (dbm) { + case ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH: + case ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH: + NRF_VREQCTRL->VREGRADIO.VREQH = 1; + dbm -= NRF_TXPOWER_VREQH; + break; + default: + NRF_VREQCTRL->VREGRADIO.VREQH = 0; + break; + } +#endif + + NRF_RADIO->TXPOWER = dbm; +} + int8_t phy_txpower_round(int8_t dbm) { +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* +3 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_0dBm) + NRF_TXPOWER_VREQH; + } + + /* +2 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg1dBm) + NRF_TXPOWER_VREQH; + } + + /* +1 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg2dBm) + NRF_TXPOWER_VREQH; + } +#endif + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_0dBm) { return (int8_t)RADIO_TXPOWER_TXPOWER_0dBm; } @@ -219,21 +268,45 @@ phy_txpower_round(int8_t dbm) return (int8_t)RADIO_TXPOWER_TXPOWER_Neg8dBm; } +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -9 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) + NRF_TXPOWER_VREQH; + } +#endif + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm) { return (int8_t)RADIO_TXPOWER_TXPOWER_Neg12dBm; } +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -13 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) + NRF_TXPOWER_VREQH; + } +#endif + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm) { return (int8_t)RADIO_TXPOWER_TXPOWER_Neg16dBm; } +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -17 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) + NRF_TXPOWER_VREQH; + } +#endif + if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm) { return (int8_t)RADIO_TXPOWER_TXPOWER_Neg20dBm; } - if (dbm >= (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) { - return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; +#if MYNEWT_VAL(BLE_PHY_NRF5340_VDDH) + /* -37 dBm */ + if (dbm >= ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH) { + return ((int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm) + NRF_TXPOWER_VREQH; } +#endif return (int8_t)RADIO_TXPOWER_TXPOWER_Neg40dBm; } diff --git a/nimble/drivers/nrf5x/src/phy_priv.h b/nimble/drivers/nrf5x/src/phy_priv.h index c73235203..db0664da2 100644 --- a/nimble/drivers/nrf5x/src/phy_priv.h +++ b/nimble/drivers/nrf5x/src/phy_priv.h @@ -83,6 +83,7 @@ void phy_ppi_init(void); #include "nrf52/phy_ppi.h" #endif +void phy_txpower_set(int8_t dbm); int8_t phy_txpower_round(int8_t dbm); #ifdef NRF52_SERIES diff --git a/nimble/drivers/nrf5x/syscfg.yml b/nimble/drivers/nrf5x/syscfg.yml index e483e844b..07c9042f6 100644 --- a/nimble/drivers/nrf5x/syscfg.yml +++ b/nimble/drivers/nrf5x/syscfg.yml @@ -64,6 +64,14 @@ syscfg.defs: works for TX (i.e. ISO Broadcaster). value: 0 + BLE_PHY_NRF5340_VDDH: + description: > + This indicates if VDDH pin of nRF5340 is connected to external + power source. If connected PHY driver will make use of high voltage + operation mode for additional TX power levels (+3, +2, +1, -9, -13, + -17, -37). + value: 0 + BLE_PHY_UBLOX_BMD345_PUBLIC_ADDR: description: > Ublox BMD-345 modules come with public address preprogrammed