Bluetooth: controller: ll_sw: nordic: Add DF antenna configuration handling

Add support for Direction Finding antenna configuration in
Nordic hal of Bluetooth controller.
Add handling of response for HCI_LE_Read_Antenna_Information
HCI command in controller (upper and lower link layer).
Handling of response to the command requires antenna matrix
configuration.

Signed-off-by: Piotr Pryga <piotr.pryga@nordicsemi.no>
This commit is contained in:
Piotr Pryga 2020-11-18 23:08:57 -08:00 committed by Carles Cufí
commit f3e04898eb
9 changed files with 254 additions and 15 deletions

View file

@ -8,10 +8,18 @@ config BT_CTLR_DF_SUPPORT
select BT_CTLR_DF_CTE_TX_SUPPORT
select BT_CTLR_DF_ANT_SWITCH_2US_SUPPORT
select BT_CTLR_DF_ANT_SWITCH_1US_SUPPORT
select BT_CTLR_DF_CTE_RX_SUPPORT
select BT_CTLR_DF_CTE_RX_SAMPLE_1US_SUPPORT
config BT_CTLR_DF_CTE_TX_SUPPORT
bool
config BT_CTLR_DF_CTE_RX_SUPPORT
bool
config BT_CTLR_DF_CTE_RX_SAMPLE_1US_SUPPORT
bool
config BT_CTLR_DF_ANT_SWITCH_2US_SUPPORT
bool
@ -37,6 +45,16 @@ config BT_CTLR_DF_CTE_TX
Enable support for transmission of Constant Tone Extension in
controller.
config BT_CTLR_DF_CTE_RX_SAMPLE_1US
bool "Enable reception of CTE with 1us sampling slots"
depends on BT_CTLR_DF_CTE_RX_SAMPLE_1US_SUPPORT
default y
help
Enable reception of Constant Tone Extension. Process IQ sampling
during CTE reception with 1us sampling slots.
This sampling mode is optional for Direction Finding according to
Bluetooth v5.1.
config BT_CTLR_DF_ANT_SWITCH_1US
bool "Enable support for 1us antenna switch slots"
depends on BT_CTLR_DF_ANT_SWITCH_1US_SUPPORT
@ -56,6 +74,21 @@ config BT_CTLR_DF_ANT_SWITCH_TX
Enable support for antenna switching during CTE transmission.
Also known as Angle of Departure mode.
config BT_CTLR_DF_ANT_SWITCH_RX
bool "Enable antenna switching during CTE reception (AoA) feature"
depends on BT_CTLR_DF_ANT_SWITCH_2US_SUPPORT
default y
help
Enable support for antenna switching during CTE reception.
Also known as Angle of Arrival mode.
config BT_CTLR_DF_CTE_RX
bool "Enable reception of Constant Tone Extension feature"
depends on BT_CTLR_DF_CTE_RX_SUPPORT
default y
help
Enable support for reception of Constant Tone Extension in controller.
config BT_CTLR_DF_CONN_CTE_RSP
bool "Enable Connection CTE Response feature"
depends on BT_CTLR_DF_CTE_TX && BT_CONN
@ -80,9 +113,10 @@ config BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN
range 2 75 if !SOC_COMPATIBLE_NRF
default 12
help
Defines maximum number of antenna switch patterns that controller
will store. For nRF5x-based controllers, the hardware imposes
the value is within range 3 to 40. For general use cases Bluetoot
Core 5.1 spec. requires the value to be within range 2 up to 75.
Defines maximum length of antenna switch pattern that controller
is able to store. For nRF5x-based controllers, the hardware imposes
the value is within range 3 to 40, where last value is maximum.
For general use cases Bluetooth Core 5.1 spec. required the value
to be within range 2 up to 75.
endif # BT_CTLR_DF

View file

@ -0,0 +1,9 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#if defined(CONFIG_BT_CTLR_DF)
#include "hal/radio_df_vendor_hal.h"
#endif /* CONFIG_BT_CTLR_DF */

View file

@ -18,3 +18,9 @@ struct lll_df_adv_cfg {
/* @brief Min supported length of antenna switching pattern */
#define LLL_DF_MIN_ANT_PATTERN_LEN 3
/* @brief Max supported CTE length in 8us units */
#define LLL_DF_MAX_CTE_LEN 20
/* Provides number of available antennas for Direction Finding */
uint8_t lll_df_ant_num_get(void);

View file

@ -0,0 +1,136 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <errno.h>
#include <devicetree.h>
#include <sys/util_macro.h>
#include <nrfx/hal/nrf_radio.h>
#include "radio_df.h"
/* @brief Minimum antennas number required if antenna switching is enabled */
#define DF_ANT_NUM_MIN 2
/* @brief Value to set antenna GPIO pin as not connected */
#define DF_GPIO_PIN_NOT_SET 0xFF
/* @brief Number of PSEL_DFEGPIO registers in Radio peripheral */
#define DF_PSEL_GPIO_NUM 8
/* @brief Direction Finding antenna matrix configuration */
struct df_ant_cfg {
uint8_t ant_num;
/* Selection of GPIOs to be used to switch antennas by Radio */
uint8_t dfe_gpio[DF_PSEL_GPIO_NUM];
};
#define RADIO DT_NODELABEL(radio)
#define DFE_GPIO_PIN(idx) \
COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
(NRF_DT_GPIOS_TO_PSEL(RADIO, dfegpio##idx##_gpios)), \
(DF_GPIO_PIN_NOT_SET))
#define DFE_GPIO_PIN_DISCONNECT (RADIO_PSEL_DFEGPIO_CONNECT_Disconnected << \
RADIO_PSEL_DFEGPIO_CONNECT_Pos)
#define COUNT_GPIO(idx, _) + DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios)
#define DFE_GPIO_NUM (UTIL_LISTIFY(DF_PSEL_GPIO_NUM, COUNT_GPIO, _))
/* DFE_GPIO_NUM_IS_ZERO is required to correctly compile COND_CODE_1 in
* DFE_GPIO_ALLOWED_ANT_NUM macro. DFE_GPIO_NUM does not expand to literal 1
* So it is not possible to use it as a conditional in COND_CODE_1 argument.
*/
#if (DFE_GPIO_NUM > 0)
#define DFE_GPIO_NUM_IS_ZERO 1
#else
#define DFE_GPIO_NUM_IS_ZERO EMPTY
#endif
#define DFE_GPIO_ALLOWED_ANT_NUM COND_CODE_1(DFE_GPIO_NUM_IS_ZERO, \
(BIT(DFE_GPIO_NUM)), (0))
#if IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) || \
IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
/* Check if there is enough pins configured to represent each pattern
* for given antennas number.
*/
BUILD_ASSERT((DT_PROP(RADIO, dfe_ant_num) <= DFE_GPIO_ALLOWED_ANT_NUM), "Insufficient "
"number of GPIO pins configured.");
BUILD_ASSERT((DT_PROP(RADIO, dfe_ant_num) >= DF_ANT_NUM_MIN), "Insufficient "
"number of antennas provided.");
/* Check if dfegpio#-gios property has flag cell set to zero */
#define DFE_GPIO_PIN_FLAGS(idx) (DT_GPIO_FLAGS(RADIO, dfegpio##idx##_gpios))
#define DFE_GPIO_PIN_IS_FLAG_ZERO(idx) \
COND_CODE_1(DT_NODE_HAS_PROP(RADIO, dfegpio##idx##_gpios), \
(BUILD_ASSERT((DFE_GPIO_PIN_FLAGS(idx) == 0), \
"Flags value of GPIO pin property must be" \
"zero.")), \
(EMPTY))
#define DFE_GPIO_PIN_LIST(idx, _) idx,
FOR_EACH(DFE_GPIO_PIN_IS_FLAG_ZERO, (;),
UTIL_LISTIFY(DF_PSEL_GPIO_NUM, DFE_GPIO_PIN_LIST))
#if DT_NODE_HAS_STATUS(RADIO, okay)
const static struct df_ant_cfg ant_cfg = {
.ant_num = DT_PROP(RADIO, dfe_ant_num),
.dfe_gpio = {
DFE_GPIO_PIN(0),
DFE_GPIO_PIN(1),
DFE_GPIO_PIN(2),
DFE_GPIO_PIN(3),
DFE_GPIO_PIN(4),
DFE_GPIO_PIN(5),
DFE_GPIO_PIN(6),
DFE_GPIO_PIN(7),
}
};
#else
#error "DF antenna switching feature requires dfe_ant to be enabled in DTS"
#endif
#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX || CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */
/* @brief Function performs steps related with DF antennas configuration.
*
* Sets up DF related PSEL.DFEGPIO registers to give possibility to Radio
* to drivee antennas switches.
*/
void radio_df_ant_configure(void)
{
#if IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) || \
IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
for (uint8_t idx = 0; idx < DF_PSEL_GPIO_NUM; ++idx) {
if (ant_cfg.dfe_gpio[idx] != DF_GPIO_PIN_NOT_SET) {
nrf_radio_dfe_pattern_pin_set(NRF_RADIO,
ant_cfg.dfe_gpio[idx],
idx);
} else {
nrf_radio_dfe_pattern_pin_set(NRF_RADIO,
DFE_GPIO_PIN_DISCONNECT,
idx);
}
}
#endif /* CONFIG_BT_CTLR_DF_ANT_SWITCH_TX || CONFIG_BT_CTLR_DF_ANT_SWITCH_RX */
}
/* @brief Function provides number of available antennas for Direction Finding.
*
* The number of antennas is hardware defined. It is provided via devicetree.
*
* @return Number of available antennas.
*/
uint8_t radio_df_ant_num_get(void)
{
#if IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) || \
IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX)
return ant_cfg.ant_num;
#else
return 0;
#endif
}

View file

@ -0,0 +1,10 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/* Performs steps related with DF antennae configuration. */
void radio_df_ant_configure(void);
/* Provides number of available antennae for Direction Finding */
uint8_t radio_df_ant_num_get(void);

View file

@ -0,0 +1,7 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/nrf5/radio/radio_df.h"

View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include "hal/radio_df.h"
#include "lll_df.h"
/* @brief Function provides number of available antennas.
*
* The number of antenna is hardware defined and it is provided via devicetree.
*
* @return Number of available antennas.
*/
uint8_t lll_df_ant_num_get(void)
{
return radio_df_ant_num_get();
}

View file

@ -52,6 +52,11 @@ if(CONFIG_BT_LL_SW_SPLIT)
CONFIG_BT_CTLR_PROFILE_ISR
ll_sw/nordic/lll/lll_prof.c
)
zephyr_library_sources_ifdef(
CONFIG_BT_CTLR_DF
ll_sw/nordic/lll/lll_df.c
ll_sw/nordic/hal/nrf5/radio/radio_df.c
)
zephyr_library_include_directories(
ll_sw/nordic/lll
)

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
* Copyright (c) 2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -237,14 +237,14 @@ uint8_t ll_df_set_conn_cte_tx_params(uint16_t handle, uint8_t cte_types,
}
/* @brief Function provides information about Direction Finding
* antennae switching and sampling related settings.
* antennas switching and sampling related settings.
*
* @param[out]switch_sample_rates Pointer to store available antennae
* @param[out]switch_sample_rates Pointer to store available antennas
* switch-sampling configurations.
* @param[out]num_ant Pointer to store number of available
* antennae.
* antennas.
* @param[out]max_switch_pattern_len Pointer to store maximum number of
* antennae switch patterns.
* antennas ids in switch pattern.
* @param[out]max_cte_len Pointer to store maximum length of CTE
* in [8us] units.
*/
@ -253,13 +253,25 @@ void ll_df_read_ant_inf(uint8_t *switch_sample_rates,
uint8_t *max_switch_pattern_len,
uint8_t *max_cte_len)
{
/* Currently filled with data that inform about
* lack of antenna support for Direction Finding
*/
*switch_sample_rates = 0;
*num_ant = 0;
*max_switch_pattern_len = 0;
*max_cte_len = 0;
if (IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_TX) &&
IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_1US)) {
*switch_sample_rates |= DF_AOD_1US_TX;
}
if (IS_ENABLED(CONFIG_BT_CTLR_DF_CTE_RX) &&
IS_ENABLED(CONFIG_BT_CTLR_DF_CTE_RX_SAMPLE_1US)) {
*switch_sample_rates |= DF_AOD_1US_RX;
}
if (IS_ENABLED(CONFIG_BT_CTLR_DF_ANT_SWITCH_RX) &&
IS_ENABLED(CONFIG_BT_CTLR_DF_CTE_RX_SAMPLE_1US)) {
*switch_sample_rates |= DF_AOA_1US;
}
*max_switch_pattern_len = CONFIG_BT_CTLR_DF_MAX_ANT_SW_PATTERN_LEN;
*num_ant = lll_df_ant_num_get();
*max_cte_len = LLL_DF_MAX_CTE_LEN;
}
static struct lll_df_adv_cfg *ull_df_adv_cfg_acquire(void)