diff --git a/components/esp_phy/include/esp_phy.h b/components/esp_phy/include/esp_phy.h new file mode 100644 index 0000000000..93b3546896 --- /dev/null +++ b/components/esp_phy/include/esp_phy.h @@ -0,0 +1,112 @@ +/* + * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include "esp_err.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file + * PHY API + */ + +/** + * @brief PHY antenna + */ +typedef enum { + ESP_PHY_ANT_ANT0, /*!< PHY antenna 0 */ + ESP_PHY_ANT_ANT1, /*!< PHY antenna 1 */ + ESP_PHY_ANT_MAX, /*!< Invalid PHY antenna */ +} esp_phy_ant_t; + +/** + * @brief PHY antenna mode + */ +typedef enum { + ESP_PHY_ANT_MODE_ANT0, /*!< Enable PHY antenna 0 only */ + ESP_PHY_ANT_MODE_ANT1, /*!< Enable PHY antenna 1 only */ + ESP_PHY_ANT_MODE_AUTO, /*!< Enable PHY antenna 0 and 1, automatically select an antenna, suggest not use this mode */ + ESP_PHY_ANT_MODE_MAX, /*!< Invalid PHY enabled antenna */ +} esp_phy_ant_mode_t; + +/** + * @brief PHY GPIO configuration for antenna selection + */ +typedef struct { + uint8_t gpio_select: 1, /*!< Whether this GPIO is connected to external antenna switch */ + gpio_num: 7; /*!< The GPIO number that connects to external antenna switch */ +} esp_phy_ant_gpio_t; + +/** + * @brief PHY GPIOs configuration for antenna selection + */ +typedef struct { + esp_phy_ant_gpio_t gpio_cfg[4]; /*!< The configurations of GPIOs that connect to external antenna switch */ +} esp_phy_ant_gpio_config_t; + +/** + * @brief PHY antenna configuration + */ +typedef struct { + esp_phy_ant_mode_t rx_ant_mode; /*!< PHY antenna mode for receiving */ + esp_phy_ant_t rx_ant_default; /*!< Default antenna mode for receiving, it's ignored if rx_ant_mode is not ESP_PHY_ANT_MODE_AUTO */ + esp_phy_ant_mode_t tx_ant_mode; /*!< PHY antenna mode for transmission, it can be set to ESP_PHY_ANT_MODE_ANT1 or ESP_PHY_ANT_MODE_ANT0 */ + uint8_t enabled_ant0: 4, /*!< Index (in antenna GPIO configuration) of enabled ESP_PHY_ANT_MODE_ANT0 */ + enabled_ant1: 4; /*!< Index (in antenna GPIO configuration) of enabled ESP_PHY_ANT_MODE_ANT1 */ +} esp_phy_ant_config_t; + +/** + * @brief Set antenna GPIO configuration + * + * @param config : Antenna GPIO configuration. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_phy_set_ant_gpio(esp_phy_ant_gpio_config_t *config); + +/** + * @brief Get current antenna GPIO configuration + * + * @param config : Antenna GPIO configuration. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_phy_get_ant_gpio(esp_phy_ant_gpio_config_t *config); + +/** + * @brief Set antenna configuration + * + * @param config : Antenna configuration. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_phy_set_ant(esp_phy_ant_config_t *config); + +/** + * @brief Get current antenna configuration + * + * @param config : Antenna configuration. + * + * @return + * - ESP_OK : success + * - other : failed + */ +esp_err_t esp_phy_get_ant(esp_phy_ant_config_t *config); + +#ifdef __cplusplus +} +#endif diff --git a/components/esp_phy/include/esp_private/phy.h b/components/esp_phy/include/esp_private/phy.h index bee81286a4..14b3f7c2a8 100644 --- a/components/esp_phy/include/esp_private/phy.h +++ b/components/esp_phy/include/esp_private/phy.h @@ -180,6 +180,25 @@ _lock_t phy_get_lock(void); * */ void phy_track_pll(void); + +/** + * @brief PHY antenna default configuration + * + */ +void ant_dft_cfg(bool default_ant); + +/** + * @brief PHY tx antenna config + * + */ +void ant_tx_cfg(uint8_t ant0); + +/** + * @brief PHY rx antenna config + * + */ +void ant_rx_cfg(bool auto_en, uint8_t ant0, uint8_t ant1); + #ifdef __cplusplus } #endif diff --git a/components/esp_phy/lib b/components/esp_phy/lib index 603b695836..c9c0fb3556 160000 --- a/components/esp_phy/lib +++ b/components/esp_phy/lib @@ -1 +1 @@ -Subproject commit 603b69583635ffcedf2a5e1d0f70da77edf82d10 +Subproject commit c9c0fb3556623ca6e7f0b23fe9a234a177e2bae9 diff --git a/components/esp_phy/src/phy_common.c b/components/esp_phy/src/phy_common.c index 759f3b5de8..6f7cfa016f 100644 --- a/components/esp_phy/src/phy_common.c +++ b/components/esp_phy/src/phy_common.c @@ -4,11 +4,19 @@ * SPDX-License-Identifier: Apache-2.0 */ -#include "esp_log.h" +#include +#include #include "esp_timer.h" +#include "esp_log.h" +#include "esp_private/esp_gpio_reserve.h" +#include "soc/gpio_sig_map.h" +#include "driver/gpio.h" +#include "esp_rom_gpio.h" #include "esp_phy_init.h" #include "esp_private/phy.h" -#include +#include "esp_phy.h" + +static const char* TAG = "phy_comm"; static volatile uint16_t s_phy_modem_flag = 0; @@ -23,6 +31,9 @@ static volatile int64_t s_bt_154_prev_timestamp; #define PHY_TRACK_PLL_PERIOD_IN_US 1000000 static void phy_track_pll_internal(void); +static esp_phy_ant_gpio_config_t s_phy_ant_gpio_config = { 0 }; +static esp_phy_ant_config_t s_phy_ant_config = { 0 }; + #if CONFIG_IEEE802154_ENABLED || CONFIG_BT_ENABLED || CONFIG_ESP_WIFI_ENABLED bool phy_enabled_modem_contains(esp_phy_modem_t modem) { @@ -119,3 +130,152 @@ esp_phy_modem_t phy_get_modem_flag(void) { return s_phy_modem_flag; } + +static void phy_ant_set_gpio_output(uint32_t io_num) +{ + gpio_config_t io_conf = {}; + io_conf.intr_type = GPIO_INTR_DISABLE; + io_conf.mode = GPIO_MODE_OUTPUT; + io_conf.pin_bit_mask = (1ULL << io_num); + io_conf.pull_down_en = 0; + io_conf.pull_up_en = 0; + gpio_config(&io_conf); +} + +esp_err_t esp_phy_set_ant_gpio(esp_phy_ant_gpio_config_t *config) +{ + if (config == NULL) { + ESP_LOGE(TAG, "Invalid configuration"); + return ESP_ERR_INVALID_ARG; + } + + for (int i = 0; i < 4; i++) { + if (config->gpio_cfg[i].gpio_select == 1) { + if(esp_gpio_is_reserved(config->gpio_cfg[i].gpio_num)) { + ESP_LOGE(TAG, "gpio[%d] number: %d is reserved\n", i, config->gpio_cfg[i].gpio_num); + return ESP_ERR_INVALID_ARG; + } + } + } + + for (int i = 0; i < 4; i++) { + if (config->gpio_cfg[i].gpio_select == 1) { + phy_ant_set_gpio_output(config->gpio_cfg[i].gpio_num); + esp_rom_gpio_connect_out_signal(config->gpio_cfg[i].gpio_num, ANT_SEL0_IDX + i, 0, 0); + } + } + + memcpy(&s_phy_ant_gpio_config, config, sizeof(esp_phy_ant_gpio_config_t)); + + return ESP_OK; +} + +esp_err_t esp_phy_get_ant_gpio(esp_phy_ant_gpio_config_t *config) +{ + if (config == NULL) { + ESP_LOGE(TAG, "Invalid configuration"); + return ESP_ERR_INVALID_ARG; + } + + memcpy(config, &s_phy_ant_gpio_config, sizeof(esp_phy_ant_gpio_config_t)); + + return ESP_OK; +} + +static bool phy_ant_config_check(esp_phy_ant_config_t *config) +{ + if ((config->rx_ant_mode >= ESP_PHY_ANT_MODE_MAX) + ||(config->tx_ant_mode >= ESP_PHY_ANT_MODE_MAX) + ||(config->rx_ant_default >= ESP_PHY_ANT_MAX)) { + ESP_LOGE(TAG, "Invalid antenna: rx=%d, tx=%d, default=%d", + config->rx_ant_mode, config->tx_ant_mode, config->rx_ant_default); + return ESP_ERR_INVALID_ARG; + } + + if ((config->tx_ant_mode == ESP_PHY_ANT_MODE_AUTO) && (config->rx_ant_mode != ESP_PHY_ANT_MODE_AUTO)) { + ESP_LOGE(TAG, "If tx ant is AUTO, also need to set rx ant to AUTO"); + return ESP_ERR_INVALID_ARG; + } + + return ESP_OK; +} + +esp_err_t esp_phy_set_ant(esp_phy_ant_config_t *config) +{ + uint8_t ant0; + uint8_t ant1; + uint8_t rx_ant0; + uint8_t rx_ant1; + uint8_t def_ant; + uint8_t tx_ant0; + bool rx_auto; + + if (!config || (phy_ant_config_check(config) != ESP_OK)) { + return ESP_ERR_INVALID_ARG; + } + + if ( phy_get_modem_flag() == 0 ) { + ESP_LOGE(TAG, "PHY not enabled"); + return ESP_ERR_INVALID_STATE; + } + + ant0 = config->enabled_ant0; + ant1 = config->enabled_ant1; + rx_auto = false; + def_ant = 0; + switch (config->rx_ant_mode) { + case ESP_PHY_ANT_MODE_ANT0: + rx_ant0 = ant0; + rx_ant1 = ant0; + break; + case ESP_PHY_ANT_MODE_ANT1: + rx_ant0 = ant1; + rx_ant1 = ant1; + break; + case ESP_PHY_ANT_MODE_AUTO: + rx_ant0 = ant0; + rx_ant1 = ant1; + rx_auto = true; + break; + default: + return ESP_ERR_INVALID_ARG; + } + + switch (config->tx_ant_mode) { + case ESP_PHY_ANT_MODE_ANT0: + tx_ant0 = ant0; + break; + case ESP_PHY_ANT_MODE_ANT1: + tx_ant0 = ant1; + break; + default: + return ESP_ERR_INVALID_ARG; + } + + switch (config->rx_ant_default) { + case ESP_PHY_ANT_ANT0: + def_ant = 0; + break; + case ESP_PHY_ANT_ANT1: + def_ant = 1; + break; + default: + return ESP_ERR_INVALID_ARG; + } + + memcpy(&s_phy_ant_config, config, sizeof(esp_phy_ant_config_t)); + ant_dft_cfg(def_ant); + ant_tx_cfg(tx_ant0); + ant_rx_cfg(rx_auto, rx_ant0, rx_ant1); + return ESP_OK; +} + +esp_err_t esp_phy_get_ant(esp_phy_ant_config_t *config) +{ + if (config == NULL) { + ESP_LOGE(TAG, "Invalid args"); + return ESP_ERR_INVALID_ARG; + } + memcpy(config, &s_phy_ant_config, sizeof(esp_phy_ant_config_t)); + return ESP_OK; +}