From 2c3c3bf82c6288dcbacc948a6f877d69a3651f89 Mon Sep 17 00:00:00 2001 From: Szymon Janc Date: Thu, 8 Sep 2022 09:20:34 +0200 Subject: [PATCH] nimble/ll: Add generic interface for controlling FEM antenna This allows to select active antenna if supported by FEM. 0 means default antenna, while any other value is FEM specific. --- .../include/controller/ble_ll_fem.h | 5 ++++ nimble/controller/pkg.yml | 2 ++ nimble/controller/src/ble_ll_hci_vs.c | 27 +++++++++++++++++ nimble/controller/syscfg.yml | 4 +++ .../fem/sky66112/include/sky66112/sky66112.h | 1 - nimble/drivers/fem/sky66112/pkg.yml | 1 + nimble/drivers/fem/sky66112/src/sky66112.c | 29 ++++++++++++++----- nimble/include/nimble/hci_common.h | 5 ++++ 8 files changed, 66 insertions(+), 8 deletions(-) diff --git a/nimble/controller/include/controller/ble_ll_fem.h b/nimble/controller/include/controller/ble_ll_fem.h index 3d645173d..d8c6dbec0 100644 --- a/nimble/controller/include/controller/ble_ll_fem.h +++ b/nimble/controller/include/controller/ble_ll_fem.h @@ -38,6 +38,11 @@ void ble_ll_fem_lna_enable(void); void ble_ll_fem_lna_disable(void); #endif +#if MYNEWT_VAL(BLE_LL_FEM_ANTENNA) +/* 0 sets default antenna, any other value is FEM specific */ +int ble_ll_fem_antenna(uint8_t antenna); +#endif + #ifdef __cplusplus } #endif diff --git a/nimble/controller/pkg.yml b/nimble/controller/pkg.yml index 9115e4528..4462823cf 100644 --- a/nimble/controller/pkg.yml +++ b/nimble/controller/pkg.yml @@ -33,6 +33,8 @@ pkg.req_apis.BLE_LL_FEM_PA: - ble_ll_fem_pa pkg.req_apis.BLE_LL_FEM_LNA: - ble_ll_fem_lna +pkg.req_apis.BLE_LL_FEM_ANTENNA: + - ble_ll_fem_antenna pkg.deps: - "@apache-mynewt-core/kernel/os" diff --git a/nimble/controller/src/ble_ll_hci_vs.c b/nimble/controller/src/ble_ll_hci_vs.c index 9b9cf268d..c6c1e256b 100644 --- a/nimble/controller/src/ble_ll_hci_vs.c +++ b/nimble/controller/src/ble_ll_hci_vs.c @@ -25,6 +25,7 @@ #include "controller/ble_ll_adv.h" #include "controller/ble_ll_scan.h" #include "controller/ble_hw.h" +#include "controller/ble_ll_fem.h" #include "ble_ll_conn_priv.h" #include "ble_ll_priv.h" @@ -351,6 +352,29 @@ ble_ll_hci_vs_set_data_len(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, } #endif +#if MYNEWT_VAL(BLE_LL_FEM_ANTENNA) +static int +ble_ll_hci_vs_set_antenna(uint16_t ocf, const uint8_t *cmdbuf, uint8_t cmdlen, + uint8_t *rspbuf, uint8_t *rsplen) +{ + const struct ble_hci_vs_set_antenna_cp *cmd = (const void *) cmdbuf; + + if (cmdlen != sizeof(*cmd)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + if (ble_ll_hci_vs_is_controller_busy()) { + return BLE_ERR_CMD_DISALLOWED; + } + + if (ble_ll_fem_antenna(cmd->antenna)) { + return BLE_ERR_INV_HCI_CMD_PARMS; + } + + return BLE_ERR_SUCCESS; +} +#endif + static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_RD_STATIC_ADDR, ble_ll_hci_vs_rd_static_addr), @@ -374,6 +398,9 @@ static struct ble_ll_hci_vs_cmd g_ble_ll_hci_vs_cmds[] = { BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_DATA_LEN, ble_ll_hci_vs_set_data_len), #endif +#if MYNEWT_VAL(BLE_LL_FEM_ANTENNA) + BLE_LL_HCI_VS_CMD(BLE_HCI_OCF_VS_SET_ANTENNA, ble_ll_hci_vs_set_antenna), +#endif }; static struct ble_ll_hci_vs_cmd * diff --git a/nimble/controller/syscfg.yml b/nimble/controller/syscfg.yml index 11e582c52..364e9f58e 100644 --- a/nimble/controller/syscfg.yml +++ b/nimble/controller/syscfg.yml @@ -430,6 +430,10 @@ syscfg.defs: description: > Time required for LNA to turn on, in microseconds. value: MYNEWT_VAL(BLE_LL_LNA_TURN_ON_US) + BLE_LL_FEM_ANTENNA: + description: > + Enable support for runtime antenna selection in FEM. + value: 0 BLE_LL_SYSINIT_STAGE: description: > diff --git a/nimble/drivers/fem/sky66112/include/sky66112/sky66112.h b/nimble/drivers/fem/sky66112/include/sky66112/sky66112.h index 2403e7c06..6bdf59f74 100644 --- a/nimble/drivers/fem/sky66112/include/sky66112/sky66112.h +++ b/nimble/drivers/fem/sky66112/include/sky66112/sky66112.h @@ -28,7 +28,6 @@ extern "C" { #endif void sky66112_tx_hp_mode(uint8_t enabled); -void sky66112_antenna_port(uint8_t port); void sky66112_rx_bypass(uint8_t enabled); void sky66112_tx_bypass(uint8_t enabled); #ifdef __cplusplus diff --git a/nimble/drivers/fem/sky66112/pkg.yml b/nimble/drivers/fem/sky66112/pkg.yml index 5dd738a07..532fe212a 100644 --- a/nimble/drivers/fem/sky66112/pkg.yml +++ b/nimble/drivers/fem/sky66112/pkg.yml @@ -24,6 +24,7 @@ pkg.homepage: "https://mynewt.apache.org/" pkg.apis: - ble_ll_fem_pa - ble_ll_fem_lna + - ble_ll_fem_antenna pkg.deps: - nimble/controller diff --git a/nimble/drivers/fem/sky66112/src/sky66112.c b/nimble/drivers/fem/sky66112/src/sky66112.c index 9b74c45c7..9e9ceab69 100644 --- a/nimble/drivers/fem/sky66112/src/sky66112.c +++ b/nimble/drivers/fem/sky66112/src/sky66112.c @@ -94,23 +94,26 @@ sky66112_tx_hp_mode(uint8_t enabled) } } -void -sky66112_antenna_port(uint8_t port) +int +ble_ll_fem_antenna(uint8_t port) { int pin = MYNEWT_VAL(SKY66112_PIN_SEL); if (pin >= 0) { switch (port) { + case 0: case 1: - hal_gpio_init_out(pin, 0); + hal_gpio_write(pin, 0); break; case 2: - hal_gpio_init_out(pin, 1); + hal_gpio_write(pin, 1); break; default: - assert(0); + return -1; } } + + return 0; } void @@ -158,6 +161,18 @@ sky66112_init(void) hal_gpio_init_out(pin, 0); } - sky66112_tx_hp_mode(MYNEWT_VAL(SKY66112_TX_HP_MODE)); - sky66112_antenna_port(MYNEWT_VAL(SKY66112_ANTENNA_PORT)); + /* configure default antenna */ + pin = MYNEWT_VAL(SKY66112_PIN_SEL); + if (pin >= 0) { + switch (MYNEWT_VAL(SKY66112_ANTENNA_PORT)) { + case 1: + hal_gpio_init_out(pin, 0); + break; + case 2: + hal_gpio_init_out(pin, 1); + break; + default: + assert(0); + } + } } diff --git a/nimble/include/nimble/hci_common.h b/nimble/include/nimble/hci_common.h index a3c3dc3f0..7c5ebe9a0 100644 --- a/nimble/include/nimble/hci_common.h +++ b/nimble/include/nimble/hci_common.h @@ -1179,6 +1179,11 @@ struct ble_hci_vs_set_data_len_cp { struct ble_hci_vs_set_data_len_rp { uint16_t conn_handle; } __attribute__((packed)); +#define BLE_HCI_OCF_VS_SET_ANTENNA (MYNEWT_VAL(BLE_HCI_VS_OCF_OFFSET) + (0x0009)) +struct ble_hci_vs_set_antenna_cp { + uint8_t antenna; +} __attribute__((packed)); + /* Command Specific Definitions */