mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-08-23 02:10:01 +00:00
nimble/ll: Add support for RX/TX power with RF path compensation
This allows host to compensate RX/TX power on RF path. This was affecting following qualification test cases: LL/DDI/ADV/BV-34-C HCI/CCO/BV-18-C HCI/CCO/BV-19-C HCI/CCO/BV-20-C
This commit is contained in:
@@ -60,6 +60,9 @@ int ble_ll_hci_chk_phy_masks(uint8_t *cmdbuf, uint8_t *txphy, uint8_t *rxphy);
|
||||
/* Returns true if Extended Advertising HCI commands are in use */
|
||||
bool ble_ll_hci_adv_mode_ext(void);
|
||||
|
||||
/* Get TX power compensation rounded to integer dB */
|
||||
int8_t ble_ll_get_tx_pwr_compensation(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -127,6 +127,9 @@ int ble_phy_txpower_round(int dbm);
|
||||
/* Get the transmit power */
|
||||
int ble_phy_txpwr_get(void);
|
||||
|
||||
/* Set RX path power compensation value rounded to integer dB */
|
||||
void ble_phy_set_rx_pwr_compensation(int8_t compensation);
|
||||
|
||||
/* Disable the PHY */
|
||||
void ble_phy_disable(void);
|
||||
|
||||
|
||||
@@ -561,7 +561,7 @@ ble_ll_adv_aux_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte)
|
||||
}
|
||||
|
||||
if (aux->ext_hdr & (1 << BLE_LL_EXT_ADV_TX_POWER_BIT)) {
|
||||
dptr[0] = advsm->adv_txpwr;
|
||||
dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation();
|
||||
dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE;
|
||||
}
|
||||
|
||||
@@ -638,7 +638,7 @@ ble_ll_adv_aux_scannable_pdu_make(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_b
|
||||
if (advsm->props & BLE_HCI_LE_SET_EXT_ADV_PROP_INC_TX_PWR) {
|
||||
*ext_hdr_len += BLE_LL_EXT_ADV_TX_POWER_SIZE;
|
||||
*ext_hdr |= (1 << BLE_LL_EXT_ADV_TX_POWER_BIT);
|
||||
dptr[0] = advsm->adv_txpwr;
|
||||
dptr[0] = advsm->adv_txpwr + ble_ll_get_tx_pwr_compensation();
|
||||
dptr += BLE_LL_EXT_ADV_TX_POWER_SIZE;
|
||||
}
|
||||
|
||||
|
||||
@@ -48,6 +48,9 @@ static uint8_t g_ble_ll_hci_le_event_mask[BLE_HCI_SET_LE_EVENT_MASK_LEN];
|
||||
static uint8_t g_ble_ll_hci_event_mask[BLE_HCI_SET_EVENT_MASK_LEN];
|
||||
static uint8_t g_ble_ll_hci_event_mask2[BLE_HCI_SET_EVENT_MASK_LEN];
|
||||
|
||||
static int16_t rx_path_pwr_compensation;
|
||||
static int16_t tx_path_pwr_compensation;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
static enum {
|
||||
ADV_MODE_ANY,
|
||||
@@ -717,6 +720,62 @@ ble_ll_is_valid_adv_mode(uint8_t ocf)
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
ble_ll_read_tx_power(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
int8_t min;
|
||||
int8_t max;
|
||||
|
||||
min = ble_phy_txpower_round(-127);
|
||||
max = ble_phy_txpower_round(126);
|
||||
|
||||
rspbuf[0] = min;
|
||||
rspbuf[1] = max;
|
||||
|
||||
*rsplen = 2;
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_read_rf_path_compensation(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
put_le16(rspbuf, tx_path_pwr_compensation);
|
||||
*rsplen = sizeof(int16_t);
|
||||
|
||||
put_le16(rspbuf + 2, rx_path_pwr_compensation);
|
||||
*rsplen += sizeof(int16_t);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_write_rf_path_compensation(const uint8_t *cmdbuf)
|
||||
{
|
||||
int16_t rx;
|
||||
int16_t tx;
|
||||
|
||||
tx = get_le16(cmdbuf);
|
||||
rx = get_le16(cmdbuf + 2);
|
||||
|
||||
if ((tx < -1280) || (tx > 1280) || (rx < -1280) || (rx > 1280)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
tx_path_pwr_compensation = tx;
|
||||
rx_path_pwr_compensation = rx;
|
||||
|
||||
ble_phy_set_rx_pwr_compensation(rx_path_pwr_compensation / 10);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int8_t
|
||||
ble_ll_get_tx_pwr_compensation(void)
|
||||
{
|
||||
return tx_path_pwr_compensation / 10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process a LE command sent from the host to the controller. The HCI command
|
||||
* has a 3 byte command header followed by data. The header is:
|
||||
@@ -1089,6 +1148,17 @@ ble_ll_hci_le_cmd_proc(uint8_t *cmdbuf, uint16_t ocf, uint8_t *rsplen,
|
||||
rc = ble_ll_ext_conn_create(cmdbuf, len);
|
||||
break;
|
||||
#endif
|
||||
case BLE_HCI_OCF_LE_RD_TRANSMIT_POWER:
|
||||
rc = ble_ll_read_tx_power(rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_RD_RF_PATH_COMPENSATION:
|
||||
rc = ble_ll_read_rf_path_compensation(rspbuf, rsplen);
|
||||
break;
|
||||
case BLE_HCI_OCF_LE_WR_RF_PATH_COMPENSATION:
|
||||
if (len == BLE_HCI_LE_WR_RF_PATH_COMPENSATION_LEN) {
|
||||
rc = ble_ll_write_rf_path_compensation(cmdbuf);
|
||||
}
|
||||
break;
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
case BLE_HCI_OCF_LE_SET_PRIVACY_MODE:
|
||||
if (len == BLE_HCI_LE_SET_PRIVACY_MODE_LEN) {
|
||||
@@ -1465,6 +1535,10 @@ ble_ll_hci_init(void)
|
||||
/* Set page 2 to 0 */
|
||||
memset(g_ble_ll_hci_event_mask2, 0, BLE_HCI_SET_EVENT_MASK_LEN);
|
||||
|
||||
/* reset RF path compensation values */
|
||||
rx_path_pwr_compensation = 0;
|
||||
tx_path_pwr_compensation = 0;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
/* after reset both legacy and extended advertising commands are allowed */
|
||||
hci_adv_mode = ADV_MODE_ANY;
|
||||
|
||||
@@ -328,7 +328,7 @@
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_TX_POWER (0 << 7)
|
||||
#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_38 \
|
||||
( \
|
||||
@@ -343,8 +343,8 @@
|
||||
)
|
||||
|
||||
/* Octet 39 */
|
||||
#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1)
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) == 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2)
|
||||
#else
|
||||
|
||||
@@ -33,6 +33,7 @@ struct ble_phy_obj
|
||||
{
|
||||
uint8_t phy_stats_initialized;
|
||||
int8_t phy_txpwr_dbm;
|
||||
int16_t rx_pwr_compensation;
|
||||
uint8_t phy_chan;
|
||||
uint8_t phy_state;
|
||||
uint8_t phy_transition;
|
||||
@@ -275,7 +276,8 @@ ble_phy_isr(void)
|
||||
/* Construct BLE header before handing up */
|
||||
ble_hdr = &g_ble_phy_data.rxhdr;
|
||||
ble_hdr->rxinfo.flags = 0;
|
||||
ble_hdr->rxinfo.rssi = -77; /* XXX: dummy rssi */
|
||||
/* XXX: dummy rssi */
|
||||
ble_hdr->rxinfo.rssi = -77 + g_ble_phy_data.rx_pwr_compensation;
|
||||
ble_hdr->rxinfo.channel = g_ble_phy_data.phy_chan;
|
||||
ble_hdr->rxinfo.phy = BLE_PHY_1M;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
@@ -312,6 +314,8 @@ ble_phy_init(void)
|
||||
g_ble_phy_data.phy_state = BLE_PHY_STATE_IDLE;
|
||||
g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
|
||||
|
||||
g_ble_phy_data.rx_pwr_compensation = 0;
|
||||
|
||||
/* XXX: emulate ISR? */
|
||||
|
||||
return 0;
|
||||
@@ -515,6 +519,12 @@ ble_phy_txpwr_get(void)
|
||||
return g_ble_phy_data.phy_txpwr_dbm;
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_set_rx_pwr_compensation(int8_t compensation)
|
||||
{
|
||||
g_ble_phy_data.rx_pwr_compensation = compensation;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy setchan
|
||||
*
|
||||
|
||||
@@ -84,6 +84,7 @@ struct ble_phy_obj
|
||||
uint8_t phy_privacy;
|
||||
uint8_t phy_tx_pyld_len;
|
||||
uint8_t *rxdptr;
|
||||
int8_t rx_pwr_compensation;
|
||||
uint32_t phy_aar_scratch;
|
||||
uint32_t phy_access_address;
|
||||
struct ble_mbuf_hdr rxhdr;
|
||||
@@ -593,7 +594,8 @@ ble_phy_rx_end_isr(void)
|
||||
/* Set RSSI and CRC status flag in header */
|
||||
ble_hdr = &g_ble_phy_data.rxhdr;
|
||||
assert(NRF_RADIO->EVENTS_RSSIEND != 0);
|
||||
ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
|
||||
ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) +
|
||||
g_ble_phy_data.rx_pwr_compensation;
|
||||
|
||||
dptr = g_ble_phy_data.rxdptr;
|
||||
|
||||
@@ -832,6 +834,8 @@ ble_phy_init(void)
|
||||
/* Set phy channel to an invalid channel so first set channel works */
|
||||
g_ble_phy_data.phy_chan = BLE_PHY_NUM_CHANS;
|
||||
|
||||
g_ble_phy_data.rx_pwr_compensation = 0;
|
||||
|
||||
/* Toggle peripheral power to reset (just in case) */
|
||||
NRF_RADIO->POWER = 0;
|
||||
NRF_RADIO->POWER = 1;
|
||||
@@ -1287,6 +1291,12 @@ ble_phy_txpwr_get(void)
|
||||
return g_ble_phy_data.phy_txpwr_dbm;
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_set_rx_pwr_compensation(int8_t compensation)
|
||||
{
|
||||
g_ble_phy_data.rx_pwr_compensation = compensation;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy setchan
|
||||
*
|
||||
|
||||
@@ -111,6 +111,7 @@ struct ble_phy_obj
|
||||
uint8_t phy_txtorx_phy_mode;
|
||||
uint8_t phy_cur_phy_mode;
|
||||
uint8_t phy_bcc_offset;
|
||||
int8_t rx_pwr_compensation;
|
||||
uint32_t phy_aar_scratch;
|
||||
uint32_t phy_access_address;
|
||||
struct ble_mbuf_hdr rxhdr;
|
||||
@@ -957,7 +958,8 @@ ble_phy_rx_end_isr(void)
|
||||
/* Set RSSI and CRC status flag in header */
|
||||
ble_hdr = &g_ble_phy_data.rxhdr;
|
||||
assert(NRF_RADIO->EVENTS_RSSIEND != 0);
|
||||
ble_hdr->rxinfo.rssi = -1 * NRF_RADIO->RSSISAMPLE;
|
||||
ble_hdr->rxinfo.rssi = (-1 * NRF_RADIO->RSSISAMPLE) +
|
||||
g_ble_phy_data.rx_pwr_compensation;
|
||||
|
||||
dptr = (uint8_t *)&g_ble_phy_rx_buf[0];
|
||||
dptr += 3;
|
||||
@@ -1347,6 +1349,8 @@ ble_phy_init(void)
|
||||
g_ble_phy_data.phy_cur_phy_mode = BLE_PHY_MODE_1M;
|
||||
g_ble_phy_data.phy_txtorx_phy_mode = BLE_PHY_MODE_1M;
|
||||
|
||||
g_ble_phy_data.rx_pwr_compensation = 0;
|
||||
|
||||
#if !defined(BLE_XCVR_RFCLK)
|
||||
/* BLE wants the HFXO on all the time in this case */
|
||||
ble_phy_rfclk_enable();
|
||||
@@ -1858,6 +1862,12 @@ ble_phy_txpwr_get(void)
|
||||
return g_ble_phy_data.phy_txpwr_dbm;
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_set_rx_pwr_compensation(int8_t compensation)
|
||||
{
|
||||
g_ble_phy_data.rx_pwr_compensation = compensation;
|
||||
}
|
||||
|
||||
/**
|
||||
* ble phy setchan
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user