From 28b496598a65643f6473a1833e01166385c1a697 Mon Sep 17 00:00:00 2001 From: Marcos Lopez Date: Tue, 24 Oct 2023 18:28:19 +0200 Subject: [PATCH] drivers: ieee802154: dw1000: set_txpower implementation Add implementation to change the register for Transmit Power Control. The function will set TX power below or above the nominal calibration value - within the full ranges allowed by the TX_POWER register. Signed-off-by: Marcos Lopez --- drivers/ieee802154/ieee802154_dw1000.c | 90 ++++++++++++++++++++- drivers/ieee802154/ieee802154_dw1000_regs.h | 68 +++++++++++++++- 2 files changed, 152 insertions(+), 6 deletions(-) diff --git a/drivers/ieee802154/ieee802154_dw1000.c b/drivers/ieee802154/ieee802154_dw1000.c index f7154e785922080..b45a26a2e243125 100644 --- a/drivers/ieee802154/ieee802154_dw1000.c +++ b/drivers/ieee802154/ieee802154_dw1000.c @@ -770,11 +770,95 @@ static int dwt_filter(const struct device *dev, return -ENOTSUP; } -static int dwt_set_power(const struct device *dev, int16_t dbm) +uint8_t dwt_encode_power_tx(int16_t target_mdb) +{ + uint8_t target_int_x2; + uint8_t coarse_steps; + uint8_t coarse_x2; + uint8_t fine_steps; + uint8_t coarse_reg; + uint8_t fine_reg; + uint8_t reg; + + if (target_mdb < 0) { + return DWT_TX_POWER_CTRL_MIN; + } else if (target_mdb > DWT_TX_POWER_CTRL_MAX_MDB) { + return DWT_TX_POWER_CTRL_MAX; + } + + target_int_x2 = target_mdb << 1; + coarse_steps = target_int_x2 / DWT_TX_POWER_CTRL_COARSE_STEPS_MDB_X2; + + if (coarse_steps > DWT_TX_POWER_CTRL_COARSE_MASK) { + coarse_steps = DWT_TX_POWER_CTRL_COARSE_MASK; + } + + coarse_x2 = coarse_steps * DWT_TX_POWER_CTRL_COARSE_STEPS_MDB_X2; + fine_steps = (target_int_x2 - coarse_x2) / DWT_TX_POWER_CTRL_FINE_STEPS_MDB_X2; + + if (fine_steps > DWT_TX_POWER_CTRL_FINE_MASK) { + fine_steps = DWT_TX_POWER_CTRL_FINE_MASK; + } + + coarse_reg = DWT_TX_POWER_CTRL_COARSE_MASK - coarse_steps; + fine_reg = fine_steps; + reg = (coarse_reg << 5) | fine_reg; + + return reg; +} + +static int dwt_set_txpower(const struct device *dev, int16_t dbm) { struct dwt_context *ctx = dev->data; + uint8_t chan = ctx->rf_cfg.channel; + int16_t mdbm = dbm * 10; + uint32_t tx_power = 0; + void *dwt_txpwr_mdb; + + if (ctx->rf_cfg.prf == DWT_PRF_16M) { + dwt_txpwr_mdb = (void *)dwt_txpwr_16_mdb; + } else { + dwt_txpwr_mdb = (void *)dwt_txpwr_64_mdb; + } + +#ifdef CONFIG_IEEE802154_DW1000_ENABLE_MANUAL_TX_POWER_CONTROL + /* Manual Transmit Power Control */ + uint16_t phr_sd_mdb; + uint8_t phr_sd; + + phr_sd_mdb = ((uint16_t *)dwt_txpwr_mdb)[dwt_ch_to_cfg[chan]]; + phr_sd = dwt_encode_power_tx(phr_sd_mdb + mdbm); + tx_power |= ((uint32_t)phr_sd << DWT_TX_POWER_TXPOWSD_SHIFT); + tx_power |= ((uint32_t)phr_sd << DWT_TX_POWER_TXPOWPHR_SHIFT); +#else + /* Smart Transmit Power Control */ + uint16_t norm_mdb; + uint16_t p500_mdb; + uint16_t p250_mdb; + uint16_t p125_mdb; + uint8_t norm; + uint8_t p500; + uint8_t p250; + uint8_t p125; + + norm_mdb = ((uint16_t (*)[4])dwt_txpwr_mdb)[dwt_ch_to_cfg[chan]][0]; + p500_mdb = ((uint16_t (*)[4])dwt_txpwr_mdb)[dwt_ch_to_cfg[chan]][1]; + p250_mdb = ((uint16_t (*)[4])dwt_txpwr_mdb)[dwt_ch_to_cfg[chan]][2]; + p125_mdb = ((uint16_t (*)[4])dwt_txpwr_mdb)[dwt_ch_to_cfg[chan]][3]; + + norm = dwt_encode_power_tx(norm_mdb + mdbm); + p500 = dwt_encode_power_tx(p500_mdb + mdbm); + p250 = dwt_encode_power_tx(p250_mdb + mdbm); + p125 = dwt_encode_power_tx(p125_mdb + mdbm); + + tx_power = norm; + tx_power |= ((uint32_t)p500 << DWT_TX_POWER_BOOSTP500_SHIFT); + tx_power |= ((uint32_t)p250 << DWT_TX_POWER_BOOSTP250_SHIFT); + tx_power |= ((uint32_t)p125 << DWT_TX_POWER_BOOSTP125_SHIFT); +#endif - LOG_INF("set_txpower not supported %p", ctx); + dwt_reg_write_u32(dev, DWT_TX_POWER_ID, 0, tx_power); + LOG_INF("Relative transmit power changed to %d dB", dbm); return 0; } @@ -1669,7 +1753,7 @@ static struct ieee802154_radio_api dwt_radio_api = { .cca = dwt_cca, .set_channel = dwt_set_channel, .filter = dwt_filter, - .set_txpower = dwt_set_power, + .set_txpower = dwt_set_txpower, .start = dwt_start, .stop = dwt_stop, .configure = dwt_configure, diff --git a/drivers/ieee802154/ieee802154_dw1000_regs.h b/drivers/ieee802154/ieee802154_dw1000_regs.h index 7f551f9b415e5e1..124cfc741f54400 100644 --- a/drivers/ieee802154/ieee802154_dw1000_regs.h +++ b/drivers/ieee802154/ieee802154_dw1000_regs.h @@ -687,6 +687,16 @@ /* TX Power Control */ #define DWT_TX_POWER_ID 0x1E #define DWT_TX_POWER_LEN 4 + +/* Units of TX Power Control. From User Manual 7.2.31.1 */ +#define DWT_TX_POWER_CTRL_COARSE_MASK 6 +#define DWT_TX_POWER_CTRL_COARSE_STEPS_MDB_X2 50 +#define DWT_TX_POWER_CTRL_FINE_MASK 0x1F +#define DWT_TX_POWER_CTRL_FINE_STEPS_MDB_X2 10 +#define DWT_TX_POWER_CTRL_MAX_MDB 305 +#define DWT_TX_POWER_CTRL_MAX 0x1F +#define DWT_TX_POWER_CTRL_MIN 0xC0 + /* * Mask and shift definition for Smart Transmit Power Control: * @@ -726,11 +736,13 @@ * of the PHY header (PHR) portion of the frame. */ #define DWT_TX_POWER_TXPOWPHR_MASK 0x0000FF00UL +#define DWT_TX_POWER_TXPOWPHR_SHIFT 8 /* * This power setting is applied during the transmission * of the synchronisation header (SHR) and data portions of the frame. */ #define DWT_TX_POWER_TXPOWSD_MASK 0x00FF0000UL +#define DWT_TX_POWER_TXPOWSD_SHIFT 16 /* Channel Control */ #define DWT_CHAN_CTRL_ID 0x1F @@ -1925,8 +1937,7 @@ const uint8_t dwt_pgdelay_defs[] = { DWT_TC_PGDELAY_CH7 }; -#ifdef CONFIG_ENABLE_MANUAL_TX_POWER_CONTROL - +#ifdef CONFIG_IEEE802154_DW1000_ENABLE_MANUAL_TX_POWER_CONTROL /* * Default from Table 20: Reference values Register file: @@ -1942,6 +1953,19 @@ const uint32_t dwt_txpwr_64[] = { 0xD1D1D1D1 }; +/* + * Defaults decoded from Table 20 at 64 MHz to mdB + * For each channel: TXPOWPHR=TXPOWSD + */ +const uint16_t dwt_txpwr_64_mdb[] = { + 135, + 135, + 105, + 180, + 75, + 85, +}; + /* * Default from Table 20: Reference values Register file: * 0x1E – Transmit Power Control for Manual Transmit Power Control @@ -1956,8 +1980,20 @@ const uint32_t dwt_txpwr_16[] = { 0x92929292 }; -#else +/* + * Defaults decoded from Table 20 at 16 MHz to mdB + * For each channel: TXPOWPHR=TXPOWSD + */ +const uint16_t dwt_txpwr_16_mdb[] = { + 180, + 180, + 150, + 255, + 140, + 140, +}; +#else /* * Defaults from Table 19: Reference values for Register file: @@ -1973,6 +2009,19 @@ const uint32_t dwt_txpwr_64[] = { 0x5171B1D1 }; +/* + * Defaults decoded from Table 19 to mdB + * For each channel: BOOSTNORM, BOOSTP500, BOOST250, BOOST125 + */ +const uint16_t dwt_txpwr_64_mdb[][4] = { + {110, 135, 160, 185}, + {110, 135, 160, 185}, + {105, 130, 155, 180}, + {180, 205, 230, 255}, + {90, 110, 130, 150}, + {85, 110, 160, 185} +}; + /* * Defaults from Table 19: Reference values for Register file: * 0x1E – Transmit Power Control for Smart Transmit Power Control @@ -1987,6 +2036,19 @@ const uint32_t dwt_txpwr_16[] = { 0x32527292 }; +/* + * Defaults decoded from Table 19 at 16 MHz to mdB + * For each channel: BOOSTNORM, BOOSTP500, BOOST250, BOOST125 + */ +const uint16_t dwt_txpwr_16_mdb[][4] = { + {180, 205, 230, 255}, + {180, 205, 230, 255}, + {150, 175, 200, 225}, + {255, 280, 305, 305}, + {140, 165, 190, 220}, + {140, 165, 190, 215} +}; + #endif enum dwt_pulse_repetition_frequency {