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:
Szymon Janc
2019-01-16 22:04:47 +01:00
parent 822e6b8db3
commit f769e422e5
8 changed files with 118 additions and 8 deletions
@@ -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);
+2 -2
View File
@@ -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;
}
+74
View File
@@ -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;
+3 -3
View File
@@ -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
+11 -1
View File
@@ -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
*
+11 -1
View File
@@ -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
*
+11 -1
View File
@@ -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
*