Merge pull request #135 from SuperHouse/feature/phy
PHY management features
This commit is contained in:
commit
3da022c132
8 changed files with 770 additions and 40 deletions
|
@ -24,6 +24,7 @@
|
||||||
#include "os_version.h"
|
#include "os_version.h"
|
||||||
|
|
||||||
#include "espressif/esp_common.h"
|
#include "espressif/esp_common.h"
|
||||||
|
#include "espressif/phy_info.h"
|
||||||
#include "sdk_internal.h"
|
#include "sdk_internal.h"
|
||||||
|
|
||||||
/* This is not declared in any header file (but arguably should be) */
|
/* This is not declared in any header file (but arguably should be) */
|
||||||
|
@ -31,8 +32,6 @@
|
||||||
void user_init(void);
|
void user_init(void);
|
||||||
|
|
||||||
#define BOOT_INFO_SIZE 28
|
#define BOOT_INFO_SIZE 28
|
||||||
//TODO: phy_info should probably be a struct (no idea about its organization, though)
|
|
||||||
#define PHY_INFO_SIZE 128
|
|
||||||
|
|
||||||
// These are the offsets of these values within the RTCMEM regions. It appears
|
// These are the offsets of these values within the RTCMEM regions. It appears
|
||||||
// that the ROM saves them to RTCMEM before calling us, and we pull them out of
|
// that the ROM saves them to RTCMEM before calling us, and we pull them out of
|
||||||
|
@ -45,26 +44,6 @@ void user_init(void);
|
||||||
extern uint32_t _bss_start;
|
extern uint32_t _bss_start;
|
||||||
extern uint32_t _bss_end;
|
extern uint32_t _bss_end;
|
||||||
|
|
||||||
// .Ldata003 -- .irom.text+0x0
|
|
||||||
static const uint8_t IROM default_phy_info[PHY_INFO_SIZE] = {
|
|
||||||
0x05, 0x00, 0x04, 0x02, 0x05, 0x05, 0x05, 0x02,
|
|
||||||
0x05, 0x00, 0x04, 0x05, 0x05, 0x04, 0x05, 0x05,
|
|
||||||
0x04, 0xfe, 0xfd, 0xff, 0xf0, 0xf0, 0xf0, 0xe0,
|
|
||||||
0xe0, 0xe0, 0xe1, 0x0a, 0xff, 0xff, 0xf8, 0x00,
|
|
||||||
0xf8, 0xf8, 0x52, 0x4e, 0x4a, 0x44, 0x40, 0x38,
|
|
||||||
0x00, 0x00, 0x01, 0x01, 0x02, 0x03, 0x04, 0x05,
|
|
||||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0xe1, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x01, 0x93, 0x43, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
};
|
|
||||||
|
|
||||||
// user_init_flag -- .bss+0x0
|
// user_init_flag -- .bss+0x0
|
||||||
uint8_t sdk_user_init_flag;
|
uint8_t sdk_user_init_flag;
|
||||||
|
|
||||||
|
@ -82,7 +61,7 @@ xTaskHandle sdk_xWatchDogTaskHandle;
|
||||||
static void IRAM get_otp_mac_address(uint8_t *buf);
|
static void IRAM get_otp_mac_address(uint8_t *buf);
|
||||||
static void IRAM set_spi0_divisor(uint32_t divisor);
|
static void IRAM set_spi0_divisor(uint32_t divisor);
|
||||||
static void zero_bss(void);
|
static void zero_bss(void);
|
||||||
static void init_networking(uint8_t *phy_info, uint8_t *mac_addr);
|
static void init_networking(sdk_phy_info_t *phy_info, uint8_t *mac_addr);
|
||||||
static void init_g_ic(void);
|
static void init_g_ic(void);
|
||||||
static void dump_excinfo(void);
|
static void dump_excinfo(void);
|
||||||
static void user_start_phase2(void);
|
static void user_start_phase2(void);
|
||||||
|
@ -273,7 +252,7 @@ static void zero_bss(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// .Lfunc006 -- .irom0.text+0x70
|
// .Lfunc006 -- .irom0.text+0x70
|
||||||
static void init_networking(uint8_t *phy_info, uint8_t *mac_addr) {
|
static void init_networking(sdk_phy_info_t *phy_info, uint8_t *mac_addr) {
|
||||||
if (sdk_register_chipv6_phy(phy_info)) {
|
if (sdk_register_chipv6_phy(phy_info)) {
|
||||||
printf("FATAL: sdk_register_chipv6_phy failed");
|
printf("FATAL: sdk_register_chipv6_phy failed");
|
||||||
halt();
|
halt();
|
||||||
|
@ -413,7 +392,7 @@ extern void (*__init_array_end)(void);
|
||||||
// .Lfunc009 -- .irom0.text+0x5b4
|
// .Lfunc009 -- .irom0.text+0x5b4
|
||||||
static __attribute__((noinline)) void user_start_phase2(void) {
|
static __attribute__((noinline)) void user_start_phase2(void) {
|
||||||
uint8_t *buf;
|
uint8_t *buf;
|
||||||
uint8_t *phy_info;
|
sdk_phy_info_t phy_info, default_phy_info;
|
||||||
|
|
||||||
sdk_system_rtc_mem_read(0, &sdk_rst_if, sizeof(sdk_rst_if));
|
sdk_system_rtc_mem_read(0, &sdk_rst_if, sizeof(sdk_rst_if));
|
||||||
if (sdk_rst_if.version > 3) {
|
if (sdk_rst_if.version > 3) {
|
||||||
|
@ -431,8 +410,16 @@ static __attribute__((noinline)) void user_start_phase2(void) {
|
||||||
sdk_info._unknown1 = 0x00ffffff;
|
sdk_info._unknown1 = 0x00ffffff;
|
||||||
sdk_info._unknown2 = 0x0104a8c0;
|
sdk_info._unknown2 = 0x0104a8c0;
|
||||||
init_g_ic();
|
init_g_ic();
|
||||||
phy_info = malloc(PHY_INFO_SIZE);
|
|
||||||
sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)phy_info, PHY_INFO_SIZE);
|
read_saved_phy_info(&phy_info);
|
||||||
|
get_default_phy_info(&default_phy_info);
|
||||||
|
|
||||||
|
if (phy_info.version != default_phy_info.version) {
|
||||||
|
/* Versions don't match, use default for PHY info
|
||||||
|
(may be a blank config sector, or a new default version.)
|
||||||
|
*/
|
||||||
|
memcpy(&phy_info, &default_phy_info, sizeof(sdk_phy_info_t));
|
||||||
|
}
|
||||||
|
|
||||||
// Disable default buffering on stdout
|
// Disable default buffering on stdout
|
||||||
setbuf(stdout, NULL);
|
setbuf(stdout, NULL);
|
||||||
|
@ -440,13 +427,7 @@ static __attribute__((noinline)) void user_start_phase2(void) {
|
||||||
uart_flush_txfifo(0);
|
uart_flush_txfifo(0);
|
||||||
uart_flush_txfifo(1);
|
uart_flush_txfifo(1);
|
||||||
|
|
||||||
if (phy_info[0] != 5) {
|
init_networking(&phy_info, sdk_info.sta_mac_addr);
|
||||||
// Bad version byte. Discard what we read and use default values
|
|
||||||
// instead.
|
|
||||||
memcpy(phy_info, default_phy_info, PHY_INFO_SIZE);
|
|
||||||
}
|
|
||||||
init_networking(phy_info, sdk_info.sta_mac_addr);
|
|
||||||
free(phy_info);
|
|
||||||
|
|
||||||
// Call gcc constructor functions
|
// Call gcc constructor functions
|
||||||
void (**ctor)(void);
|
void (**ctor)(void);
|
||||||
|
@ -487,7 +468,7 @@ static __attribute__((noinline)) void dump_flash_config_sectors(uint32_t start_s
|
||||||
printf("system param error\n");
|
printf("system param error\n");
|
||||||
// Note: original SDK code didn't dump PHY info
|
// Note: original SDK code didn't dump PHY info
|
||||||
printf("phy_info:\n");
|
printf("phy_info:\n");
|
||||||
dump_flash_sector(start_sector, PHY_INFO_SIZE);
|
dump_flash_sector(start_sector, sizeof(sdk_phy_info_t));
|
||||||
printf("\ng_ic saved 0:\n");
|
printf("\ng_ic saved 0:\n");
|
||||||
dump_flash_sector(start_sector + 1, sizeof(struct sdk_g_ic_saved_st));
|
dump_flash_sector(start_sector + 1, sizeof(struct sdk_g_ic_saved_st));
|
||||||
printf("\ng_ic saved 1:\n");
|
printf("\ng_ic saved 1:\n");
|
||||||
|
|
32
core/esp_phy.c
Normal file
32
core/esp_phy.c
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/** esp/phy.h
|
||||||
|
*
|
||||||
|
* PHY hardware management functions.
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2016 ChefSteps, Inc
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#include <esp/phy.h>
|
||||||
|
#include <esp/gpio.h>
|
||||||
|
|
||||||
|
void bt_coexist_configure(bt_coexist_mode_t mode, uint8_t bt_active_pin, uint8_t bt_priority_pin)
|
||||||
|
{
|
||||||
|
/* Disable coexistence entirely before changing pin assignments */
|
||||||
|
GPIO.OUT &= ~(GPIO_OUT_BT_COEXIST_MASK);
|
||||||
|
uint32_t new_mask = 0;
|
||||||
|
|
||||||
|
new_mask = VAL2FIELD_M(GPIO_OUT_BT_ACTIVE_PIN, bt_active_pin) +
|
||||||
|
VAL2FIELD_M(GPIO_OUT_BT_PRIORITY_PIN, bt_priority_pin);
|
||||||
|
|
||||||
|
if(mode == BT_COEXIST_USE_BT_ACTIVE || mode == BT_COEXIST_USE_BT_ACTIVE_PRIORITY) {
|
||||||
|
gpio_enable(bt_active_pin, GPIO_INPUT);
|
||||||
|
new_mask |= GPIO_OUT_BT_ACTIVE_ENABLE;
|
||||||
|
}
|
||||||
|
if(mode == BT_COEXIST_USE_BT_ACTIVE_PRIORITY) {
|
||||||
|
gpio_enable(bt_priority_pin, GPIO_INPUT);
|
||||||
|
new_mask |= GPIO_OUT_BT_PRIORITY_ENABLE;
|
||||||
|
}
|
||||||
|
GPIO.OUT |= new_mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,9 +81,9 @@ static inline void gpio_set_output_on_sleep(const uint8_t gpio_num, bool enabled
|
||||||
static inline void gpio_write(const uint8_t gpio_num, const bool set)
|
static inline void gpio_write(const uint8_t gpio_num, const bool set)
|
||||||
{
|
{
|
||||||
if (set)
|
if (set)
|
||||||
GPIO.OUT_SET = BIT(gpio_num);
|
GPIO.OUT_SET = BIT(gpio_num) & GPIO_OUT_PIN_MASK;
|
||||||
else
|
else
|
||||||
GPIO.OUT_CLEAR = BIT(gpio_num);
|
GPIO.OUT_CLEAR = BIT(gpio_num) & GPIO_OUT_PIN_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Toggle output of a pin
|
/* Toggle output of a pin
|
||||||
|
@ -102,9 +102,9 @@ static inline void gpio_toggle(const uint8_t gpio_num)
|
||||||
task's pins, without needing to disable/enable interrupts.
|
task's pins, without needing to disable/enable interrupts.
|
||||||
*/
|
*/
|
||||||
if(GPIO.OUT & BIT(gpio_num))
|
if(GPIO.OUT & BIT(gpio_num))
|
||||||
GPIO.OUT_CLEAR = BIT(gpio_num);
|
GPIO.OUT_CLEAR = BIT(gpio_num) & GPIO_OUT_PIN_MASK;
|
||||||
else
|
else
|
||||||
GPIO.OUT_SET = BIT(gpio_num);
|
GPIO.OUT_SET = BIT(gpio_num) & GPIO_OUT_PIN_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read input value of a GPIO pin.
|
/* Read input value of a GPIO pin.
|
||||||
|
|
|
@ -61,6 +61,21 @@ struct GPIO_REGS {
|
||||||
|
|
||||||
_Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
|
_Static_assert(sizeof(struct GPIO_REGS) == 0x74, "GPIO_REGS is the wrong size");
|
||||||
|
|
||||||
|
/* Details for additional OUT register fields */
|
||||||
|
|
||||||
|
/* Bottom 16 bits of GPIO.OUT are for GPIOs 0-15, but upper 16 bits
|
||||||
|
are used to configure the input signalling pins for Bluetooth
|
||||||
|
Coexistence config (see esp/phy.h for a wrapper function).
|
||||||
|
*/
|
||||||
|
#define GPIO_OUT_PIN_MASK 0x0000FFFF
|
||||||
|
#define GPIO_OUT_BT_COEXIST_MASK 0x03FF0000
|
||||||
|
#define GPIO_OUT_BT_ACTIVE_ENABLE BIT(24)
|
||||||
|
#define GPIO_OUT_BT_PRIORITY_ENABLE BIT(25)
|
||||||
|
#define GPIO_OUT_BT_ACTIVE_PIN_M 0x0F
|
||||||
|
#define GPIO_OUT_BT_ACTIVE_PIN_S 16
|
||||||
|
#define GPIO_OUT_BT_PRIORITY_PIN_M 0x0F
|
||||||
|
#define GPIO_OUT_BT_PRIORITY_PIN_S 20
|
||||||
|
|
||||||
/* Details for CONF[i] registers */
|
/* Details for CONF[i] registers */
|
||||||
|
|
||||||
/* GPIO.CONF[i] control the pin behavior for the corresponding GPIO in/output.
|
/* GPIO.CONF[i] control the pin behavior for the corresponding GPIO in/output.
|
||||||
|
|
58
core/include/esp/phy.h
Normal file
58
core/include/esp/phy.h
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/** esp/phy.h
|
||||||
|
*
|
||||||
|
* PHY hardware management functions.
|
||||||
|
*
|
||||||
|
* These are not enough to configure the ESP8266 PHY by themselves
|
||||||
|
* (yet), but they provide utilities to modify the configuration set
|
||||||
|
* up via the SDK.
|
||||||
|
*
|
||||||
|
* Functions implemented here deal directly with the hardware, not the
|
||||||
|
* SDK software layers.
|
||||||
|
*
|
||||||
|
* Part of esp-open-rtos
|
||||||
|
* Copyright (C) 2016 ChefSteps, Inc
|
||||||
|
* BSD Licensed as described in the file LICENSE
|
||||||
|
*/
|
||||||
|
#ifndef _ESP_PHY_H
|
||||||
|
#define _ESP_PHY_H
|
||||||
|
|
||||||
|
#include <esp/types.h>
|
||||||
|
#include <common_macros.h>
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
BT_COEXIST_NONE,
|
||||||
|
BT_COEXIST_USE_BT_ACTIVE,
|
||||||
|
BT_COEXIST_USE_BT_ACTIVE_PRIORITY,
|
||||||
|
} bt_coexist_mode_t;
|
||||||
|
|
||||||
|
/** Override the Bluetooth Coexistence BT_ACTIVE pin setting
|
||||||
|
taken from the phy_info structure.
|
||||||
|
|
||||||
|
This enables other pins to be used for Bluetooth Coexistence
|
||||||
|
signals (rather than just the two provided for by phy_info). (Note
|
||||||
|
that not that not all pins are confirmed to work, GPIO 0 is
|
||||||
|
confirmed not usable as the SDK configures it as the WLAN_ACTIVE
|
||||||
|
output - even if you change the pin mode the SDK will change it
|
||||||
|
back.)
|
||||||
|
|
||||||
|
To change pins and have coexistence work successfully the BT
|
||||||
|
coexistence feature must be enabled in the phy_info configuration
|
||||||
|
(get_default_phy_info()). You can then modify the initial
|
||||||
|
configuration by calling this function from your own user_init
|
||||||
|
function.
|
||||||
|
|
||||||
|
(Eventually we should be able to support enough PHY registers
|
||||||
|
to enable coexistence without SDK support at all, but not yet.)
|
||||||
|
|
||||||
|
This function will enable bt_active_pin & bt_priority_as GPIO
|
||||||
|
inputs, according to the mode parameter.
|
||||||
|
|
||||||
|
Remember that the default Bluetooth Coexistence pins will be
|
||||||
|
configured as GPIOs by the SDK already, so you may want to
|
||||||
|
reconfigure/re-iomux them after calling this function.
|
||||||
|
*/
|
||||||
|
void bt_coexist_configure(bt_coexist_mode_t mode, uint8_t bt_active_pin, uint8_t bt_priority_pin);
|
||||||
|
|
||||||
|
#endif
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include "espressif/esp_wifi.h"
|
#include "espressif/esp_wifi.h"
|
||||||
#include "espressif/spi_flash.h"
|
#include "espressif/spi_flash.h"
|
||||||
|
#include "espressif/phy_info.h"
|
||||||
#include "lwip/netif.h"
|
#include "lwip/netif.h"
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -217,7 +218,7 @@ void sdk_phy_enable_agc(void);
|
||||||
void sdk_pm_attach(void);
|
void sdk_pm_attach(void);
|
||||||
void sdk_pp_attach(void);
|
void sdk_pp_attach(void);
|
||||||
void sdk_pp_soft_wdt_init(void);
|
void sdk_pp_soft_wdt_init(void);
|
||||||
int sdk_register_chipv6_phy(uint8_t *);
|
int sdk_register_chipv6_phy(sdk_phy_info_t *);
|
||||||
void sdk_sleep_reset_analog_rtcreg_8266(void);
|
void sdk_sleep_reset_analog_rtcreg_8266(void);
|
||||||
uint32_t sdk_system_get_checksum(uint8_t *, uint32_t);
|
uint32_t sdk_system_get_checksum(uint8_t *, uint32_t);
|
||||||
void sdk_system_restart_in_nmi(void);
|
void sdk_system_restart_in_nmi(void);
|
||||||
|
|
161
core/phy_info.c
Normal file
161
core/phy_info.c
Normal file
|
@ -0,0 +1,161 @@
|
||||||
|
/* Routines to allow custom access to the Internal Espressif
|
||||||
|
SDK PHY datastructures.
|
||||||
|
|
||||||
|
Matches espressif/phy_internal.h
|
||||||
|
|
||||||
|
Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton,
|
||||||
|
BSD Licensed as described in the file LICENSE.
|
||||||
|
*/
|
||||||
|
#include <espressif/phy_info.h>
|
||||||
|
#include <espressif/esp_common.h>
|
||||||
|
#include <common_macros.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static const sdk_phy_info_t IROM default_phy_info = {
|
||||||
|
._reserved00 = { 0x05, 0x00, 0x04, 0x02, 0x05 },
|
||||||
|
.version = 5,
|
||||||
|
._reserved06 = { 0x05, 0x02, 0x05, 0x00, 0x04, 0x05, 0x05, 0x04,
|
||||||
|
0x05, 0x05, 0x04,-0x02,-0x03,-0x01,-0x10,-0x10,
|
||||||
|
-0x10,-0x20,-0x20, -0x20},
|
||||||
|
.spur_freq_primary = 225,
|
||||||
|
.spur_freq_divisor = 10,
|
||||||
|
.spur_freq_en_h = 0xFF,
|
||||||
|
.spur_freq_en_l = 0xFF,
|
||||||
|
|
||||||
|
._reserved1e = { 0xf8, 0, 0xf8, 0xf8 },
|
||||||
|
|
||||||
|
.target_power = { 82, 78, 74, 68, 64, 56 },
|
||||||
|
.target_power_index_mcs = { 0, 0, 1, 1, 2, 3, 4, 5 },
|
||||||
|
|
||||||
|
.crystal_freq = CRYSTAL_FREQ_26M,
|
||||||
|
|
||||||
|
.sdio_config = SDIO_CONFIG_AUTO,
|
||||||
|
|
||||||
|
.bt_coexist_config = BT_COEXIST_CONFIG_NONE,
|
||||||
|
.bt_coexist_protocol = BT_COEXIST_PROTOCOL_WIFI_ONLY,
|
||||||
|
|
||||||
|
.dual_ant_config = DUAL_ANT_CONFIG_NONE,
|
||||||
|
|
||||||
|
._reserved34 = 0x02,
|
||||||
|
|
||||||
|
.crystal_sleep = CRYSTAL_SLEEP_OFF,
|
||||||
|
|
||||||
|
.spur_freq_2_primary = 225,
|
||||||
|
.spur_freq_2_divisor = 10,
|
||||||
|
.spur_freq_2_en_h = 0x00,
|
||||||
|
.spur_freq_2_en_l = 0x00,
|
||||||
|
.spur_freq_cfg_msb = 0x00,
|
||||||
|
.spur_freq_2_cfg_msb = 0x00,
|
||||||
|
.spur_freq_3_cfg = 0x0000,
|
||||||
|
.spur_freq_4_cfg = 0x0000,
|
||||||
|
|
||||||
|
._reserved4a = { 0x01, 0x93, 0x43, 0x00 },
|
||||||
|
|
||||||
|
.low_power_en = false,
|
||||||
|
.lp_atten_stage01 = LP_ATTEN_STAGE01_23DB,
|
||||||
|
.lp_atten_bb = 0,
|
||||||
|
|
||||||
|
.pwr_ind_11b_en = false,
|
||||||
|
.pwr_ind_11b_0 = 0,
|
||||||
|
.pwr_ind_11b_1 = 0,
|
||||||
|
|
||||||
|
/* Nominal 3.3V VCC. NOTE: This value is 0 in the
|
||||||
|
esp-open-rtos SDK default config sector, and may be unused
|
||||||
|
by that version of the SDK?
|
||||||
|
*/
|
||||||
|
.pa_vdd = 33,
|
||||||
|
|
||||||
|
/* Note: untested with the esp-open-rtos SDK default config sector, may be unused? */
|
||||||
|
.freq_correct_mode = FREQ_CORRECT_DISABLE,
|
||||||
|
.force_freq_offset = 0,
|
||||||
|
|
||||||
|
/* Note: is zero with the esp-open-rtos SDK default config sector, may be unused? */
|
||||||
|
.rf_cal_mode = RF_CAL_MODE_SAVED,
|
||||||
|
};
|
||||||
|
|
||||||
|
void get_default_phy_info(sdk_phy_info_t *info) __attribute__((weak, alias("get_sdk_default_phy_info")));
|
||||||
|
|
||||||
|
void get_sdk_default_phy_info(sdk_phy_info_t *info)
|
||||||
|
{
|
||||||
|
memcpy(info, &default_phy_info, sizeof(sdk_phy_info_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void read_saved_phy_info(sdk_phy_info_t *info)
|
||||||
|
{
|
||||||
|
sdk_spi_flash_read(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void write_saved_phy_info(const sdk_phy_info_t *info)
|
||||||
|
{
|
||||||
|
sdk_spi_flash_write(sdk_flashchip.chip_size - sdk_flashchip.sector_size * 4, (uint32_t *)info, sizeof(sdk_phy_info_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_phy_info(const sdk_phy_info_t *info, bool raw)
|
||||||
|
{
|
||||||
|
printf("version=%d\n", info->version);
|
||||||
|
printf("spur_freq = %.3f (%d/%d)\n",
|
||||||
|
(float)info->spur_freq_primary / info->spur_freq_divisor,
|
||||||
|
info->spur_freq_primary,
|
||||||
|
info->spur_freq_divisor);
|
||||||
|
printf("spur_freq_en = 0x%02x 0x%02x\n", info->spur_freq_en_h,
|
||||||
|
info->spur_freq_en_l);
|
||||||
|
printf("target_power\n");
|
||||||
|
for(int i = 0; i < 6; i++) {
|
||||||
|
printf(" %d: %.2fdB (raw 0x%02x)\n", i,
|
||||||
|
info->target_power[i]/4.0,
|
||||||
|
info->target_power[i]);
|
||||||
|
}
|
||||||
|
printf("target_power_index_mcs:");
|
||||||
|
for(int i = 0; i < 8; i++) {
|
||||||
|
printf(" %d%c", info->target_power_index_mcs[i],
|
||||||
|
i == 7 ? '\n' : ',');
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("crystal_freq: %s (raw %d)\n",
|
||||||
|
(info->crystal_freq == CRYSTAL_FREQ_40M ? "40MHz" :
|
||||||
|
(info->crystal_freq == CRYSTAL_FREQ_26M ? "26MHz" :
|
||||||
|
(info->crystal_freq == CRYSTAL_FREQ_24M ? "24MHz" : "???"))),
|
||||||
|
info->crystal_freq);
|
||||||
|
|
||||||
|
printf("sdio_config: %d\n", info->sdio_config);
|
||||||
|
printf("bt_coexist config: %d protocol: 0x%02x\n",
|
||||||
|
info->bt_coexist_config, info->bt_coexist_protocol);
|
||||||
|
printf("dual_ant_config: %d\n", info->dual_ant_config);
|
||||||
|
|
||||||
|
printf("crystal_sleep: %d\n", info->crystal_sleep);
|
||||||
|
|
||||||
|
printf("spur_freq_2 = %.3f (%d/%d)\n",
|
||||||
|
(float)info->spur_freq_2_primary / info->spur_freq_2_divisor,
|
||||||
|
info->spur_freq_2_primary,
|
||||||
|
info->spur_freq_2_divisor);
|
||||||
|
printf("spur_freq_2_en = 0x%02x 0x%02x\n", info->spur_freq_2_en_h,
|
||||||
|
info->spur_freq_2_en_l);
|
||||||
|
|
||||||
|
printf("spur_freq_cfg_msb = 0x%02x\n", info->spur_freq_cfg_msb);
|
||||||
|
printf("spur_freq_2_)cfg_msb = 0x%02x\n", info->spur_freq_2_cfg_msb);
|
||||||
|
printf("spur_freq_3_cfg = 0x%04x\n", info->spur_freq_3_cfg);
|
||||||
|
printf("spur_freq_4_cfg = 0x%04x\n", info->spur_freq_4_cfg);
|
||||||
|
|
||||||
|
printf("low_power_en = %d\n", info->low_power_en);
|
||||||
|
printf("lp_atten_stage01 = 0x%02x\n", info->lp_atten_stage01);
|
||||||
|
printf("lp_atten_bb = %.2f (raw 0x%02x)\n", info->lp_atten_bb / 4.0,
|
||||||
|
info->lp_atten_bb);
|
||||||
|
|
||||||
|
printf("pa_vdd = %d\n", info->pa_vdd);
|
||||||
|
|
||||||
|
printf("freq_correct_mode = 0x%02x\n", info->freq_correct_mode);
|
||||||
|
printf("force_freq_offset = %d\n", info->force_freq_offset);
|
||||||
|
printf("rf_cal_mode = 0x%02x\n", info->rf_cal_mode);
|
||||||
|
|
||||||
|
if(raw) {
|
||||||
|
printf("Raw values:");
|
||||||
|
uint8_t *p = (uint8_t *)info;
|
||||||
|
for(int i = 0; i < sizeof(sdk_phy_info_t); i ++) {
|
||||||
|
if(i % 8 == 0) {
|
||||||
|
printf("\n0x%02x:", i);
|
||||||
|
}
|
||||||
|
printf(" %02x", p[i]);
|
||||||
|
}
|
||||||
|
printf("\n\n");
|
||||||
|
}
|
||||||
|
}
|
482
include/espressif/phy_info.h
Normal file
482
include/espressif/phy_info.h
Normal file
|
@ -0,0 +1,482 @@
|
||||||
|
/** Internal Espressif SDK "PHY info" data structure
|
||||||
|
|
||||||
|
The data structure (sdk_phy_info_t) is used to configure the
|
||||||
|
ESP8266 PHY layer via the SDK. The fields here are not written
|
||||||
|
directly to hardware, the SDK code (mostly in libphy) parses this
|
||||||
|
structure and configures the hardware.
|
||||||
|
|
||||||
|
The structure loaded at reset time from a flash configuration
|
||||||
|
sector (see read_saved_phy_info()) (Espressif's SDK sources this
|
||||||
|
from a file "esp_init_data_default.bin"). If no valid structure is
|
||||||
|
found in the flash config sector then the SDK loads default values
|
||||||
|
(see get_default_phy_info()). It is possible to implement a custom
|
||||||
|
get_default_phy_info() to change the PHY default settings (see the
|
||||||
|
'version' field below).
|
||||||
|
|
||||||
|
@note It is possible that the SDK will quietly write a new
|
||||||
|
configuration sector to flash itself following internal
|
||||||
|
calibration, etc. However this does not seem to happen, you need to
|
||||||
|
flash it explicitly if you want it stored there.
|
||||||
|
|
||||||
|
@note Most of what is below is unconfirmed, except where a @note
|
||||||
|
says that it has been confirmed to work as expected. Please
|
||||||
|
consider submitting notes if you find behaviour here that works or
|
||||||
|
doesn't work as expected.
|
||||||
|
|
||||||
|
Information on the meaning/offset of fields comes from Espressif's
|
||||||
|
flash download tool, which uses an Excel spreadsheet (in the
|
||||||
|
init_data directory of the ZIP file) to configure and a Python
|
||||||
|
script to convert an esp_init_data_custom.bin file to flash:
|
||||||
|
http://bbs.espressif.com/viewtopic.php?f=5&t=433
|
||||||
|
|
||||||
|
Many fields remain undocumented (& disassembly of libphy suggests
|
||||||
|
that some documented fields supported undocumented values.)
|
||||||
|
|
||||||
|
A few additional notes about the phy_info fields can be found
|
||||||
|
in the ESP Arduino ESP8266 phy_init_data structure (however most of
|
||||||
|
that content is verbatim from Espressif's spreadsheet):
|
||||||
|
https://github.com/esp8266/Arduino/blob/master/cores/esp8266/core_esp8266_phy.c#L29
|
||||||
|
|
||||||
|
Part of esp-open-rtos. Copyright (C) 2016 Angus Gratton,
|
||||||
|
BSD Licensed as described in the file LICENSE.
|
||||||
|
*/
|
||||||
|
#ifndef _ESPRESSIF_PHY_INFO_H
|
||||||
|
#define _ESPRESSIF_PHY_INFO_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* CRYSTAL_FREQ_xx values as used by sdk_phy_info_t.crystal_freq */
|
||||||
|
#define CRYSTAL_FREQ_40M 0
|
||||||
|
#define CRYSTAL_FREQ_26M 1
|
||||||
|
#define CRYSTAL_FREQ_24M 2
|
||||||
|
|
||||||
|
/* SDIO_CONFIG_xx values as used by sdk_phy_info_t.sdio_config */
|
||||||
|
#define SDIO_CONFIG_AUTO 0 /* Uses pin strapping to determine */
|
||||||
|
#define SDIO_CONFIG_SDIOV1_1 /* Data output on negative edge */
|
||||||
|
#define SDIO_CONFIG_SDIOV2_0 /* data output on positive edge */
|
||||||
|
|
||||||
|
/* BT_COEXIST_CONFIG_xx values as used by sdk_phy_info_t.bt_coexist */
|
||||||
|
/* No bluetooth */
|
||||||
|
#define BT_COEXIST_CONFIG_NONE 0
|
||||||
|
/* Coexistence configuration A:
|
||||||
|
GPIO 0 - WLAN_ACTIVE
|
||||||
|
GPIO 14 - BT_ACTIVE
|
||||||
|
GPIO 13 - BT_PRIORITY
|
||||||
|
GPIO 3 - ANT_SEL_BT
|
||||||
|
*/
|
||||||
|
#define BT_COEXIST_CONFIG_A 1
|
||||||
|
/* No coexistence, but Bluetooth enabled?
|
||||||
|
Unsure how this works?
|
||||||
|
*/
|
||||||
|
#define BT_COEXIST_CONFIG_PRESENT 2
|
||||||
|
/* Coexistence configuration B:
|
||||||
|
GPIO 0 - WLAN_ACTIVE
|
||||||
|
GPIO 14 - BT_PRIORITY
|
||||||
|
GPIO 13 - BT_ACTIVE
|
||||||
|
GPIO 3 - ANT_SEL_BT
|
||||||
|
*/
|
||||||
|
#define BT_COEXIST_CONFIG_B 3
|
||||||
|
|
||||||
|
/* BT_COEXIST_PROTOCOL_xx values for coexistence protocol,
|
||||||
|
field sdk_phy_info_t.bt_coexist_protocol
|
||||||
|
*/
|
||||||
|
#define BT_COEXIST_PROTOCOL_WIFI_ONLY 0
|
||||||
|
#define BT_COEXIST_PROTOCOL_BT_ONLY 1
|
||||||
|
|
||||||
|
/* Coexistence is enabled, Bluetooth has its own antenna */
|
||||||
|
#define BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT 2
|
||||||
|
/* Coexistence is enabled, Bluetooth shares WiFi antenna */
|
||||||
|
#define BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT 4
|
||||||
|
|
||||||
|
/* Coexistence is enabled, use only BT_ACTIVE signal */
|
||||||
|
#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY 0
|
||||||
|
/* Coexistence is enabled, use both BT_ACTIVE and BT_PRIORITY signals */
|
||||||
|
#define BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_PRIORITY 1
|
||||||
|
|
||||||
|
/* DUAL_ANT_CONFIG_xx values for dual antenna config,
|
||||||
|
field sdk_phy_info_t.dual_ant_config
|
||||||
|
|
||||||
|
(Not really clear how this feature works, if at all.)
|
||||||
|
*/
|
||||||
|
#define DUAL_ANT_CONFIG_NONE 0
|
||||||
|
/* antenna diversity for WiFi, use GPIO0 + U0RXD (?) */
|
||||||
|
#define DUAL_ANT_CONFIG_DUAL 1
|
||||||
|
/* TX/RX switch for external PA & LNA: GPIO 0 high, GPIO 3 low during TX */
|
||||||
|
#define DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW
|
||||||
|
/* TX/RX switch for external PA & LNA: GPIO 0 low, GPIO 3 high during TX */
|
||||||
|
#define DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH
|
||||||
|
|
||||||
|
|
||||||
|
/* CRYSTAL_SLEEP_xx values used for sdk_phy_info_t.crystal_sleep
|
||||||
|
*/
|
||||||
|
#define CRYSTAL_SLEEP_OFF 0
|
||||||
|
#define CRYSTAL_SLEEP_ON 1
|
||||||
|
#define CRYSTAL_SLEEP_GPIO16 2
|
||||||
|
#define CRYSTAL_SLEEP_GPIO2 3
|
||||||
|
|
||||||
|
/* RF Stage 0 & 1 attenuation constants. Use for sdk_phy_info_t.lp_atten_stage01
|
||||||
|
|
||||||
|
@note These values have been tested and are confirmed to work as
|
||||||
|
expected by measuring RSSI w/ rt73 USB adapter in monitor mode
|
||||||
|
(some values also checked on spectrum analyzer) - provided
|
||||||
|
low_power_en is set then the signal is attenuated as per this
|
||||||
|
setting.
|
||||||
|
|
||||||
|
(It may look like LP_ATTEN_STAGE01_11_5DB is out of order, but
|
||||||
|
according to monitor mode captures this is the correct ordering of
|
||||||
|
these constants.)
|
||||||
|
|
||||||
|
Setting the numeric values in between these constants appears to
|
||||||
|
also attenuate the signal, but not necessarily by the amount you'd
|
||||||
|
expect.
|
||||||
|
*/
|
||||||
|
#define LP_ATTEN_STAGE01_0DB 0x0f /* 0dB */
|
||||||
|
#define LP_ATTEN_STAGE01_2_5DB 0x0e /* -2.5dB */
|
||||||
|
#define LP_ATTEN_STAGE01_6DB 0x0d /* -6dB */
|
||||||
|
#define LP_ATTEN_STAGE01_8_5DB 0x09 /* -8.5dB */
|
||||||
|
#define LP_ATTEN_STAGE01_11_5DB 0x0c /* -11.5dB */
|
||||||
|
#define LP_ATTEN_STAGE01_14DB 0x08 /* -14dB */
|
||||||
|
#define LP_ATTEN_STAGE01_17_5DB 0x04 /* -17.5dB */
|
||||||
|
#define LP_ATTEN_STAGE01_23DB 0x00 /* -23dB */
|
||||||
|
|
||||||
|
/* Constant for sdk_phy_info_t.pa_vdd */
|
||||||
|
#define PA_VDD_MEASURE_VCC 0xFF
|
||||||
|
|
||||||
|
/* Bitmask flags for sdk_phy_info_t.freq_correct_mode */
|
||||||
|
|
||||||
|
/* Set this flag to disable frequency offset correction */
|
||||||
|
#define FREQ_CORRECT_DISABLE 0
|
||||||
|
|
||||||
|
/* Set this flag to enable frequency offset correction */
|
||||||
|
#define FREQ_CORRECT_ENABLE BIT(0)
|
||||||
|
|
||||||
|
/* Set = Baseband PLL frequency is 160MHz (can only apply +ve offset)
|
||||||
|
* Unset = Baseband PLL frequency is 168MHz (can apply +ve/-ve offset */
|
||||||
|
#define FREQ_CORRECT_BB_160M BIT(1)
|
||||||
|
|
||||||
|
/* Set = use force_freq_offset field to correct, Unset = automatically
|
||||||
|
measure & correct offset
|
||||||
|
*/
|
||||||
|
#define FREQ_CORRECT_FORCE BIT(2)
|
||||||
|
|
||||||
|
|
||||||
|
/* RF_CAL_MODE_xx fields used for sdk_phy_info_t.rf_cal_mode
|
||||||
|
*/
|
||||||
|
/* Use saved RF CAL data from flash, only. RF init takes 2ms. */
|
||||||
|
#define RF_CAL_MODE_SAVED 0
|
||||||
|
/* Calibrate TX power control only, use saved RF CAL data for others.
|
||||||
|
RF init takes 20ms. */
|
||||||
|
#define RF_CAL_MODE_TXPOWER_ONLY 1
|
||||||
|
/* Unclear if/how this mode is different to 2? */
|
||||||
|
#define RF_CAL_MODE_SAVED_2 2
|
||||||
|
/* Run full RF CAL routine. RF init takes approx 200ms. */
|
||||||
|
#define RF_CAL_MODE_FULL 3
|
||||||
|
|
||||||
|
/* Data structure that maps to the phy_info configuration block */
|
||||||
|
typedef struct __attribute__((packed)) {
|
||||||
|
uint8_t _reserved00[0x05]; /* 0x00 - 0x04 */
|
||||||
|
|
||||||
|
/* This "version" field was set to 5 in the SDK phy_info,
|
||||||
|
and the original SDK startup code checks it is 5 and then loads
|
||||||
|
default PHY configuration otherwise.
|
||||||
|
|
||||||
|
esp-open-rtos will load phy_info from get_default_phy_info() if
|
||||||
|
the value stored in flash has a different value to the value
|
||||||
|
returned in get_default_phy_info(). This means you can
|
||||||
|
increment the version return by get_default_phy_info() (to any
|
||||||
|
value but 0xFF), and know that the new defaults will replace
|
||||||
|
any older stored values.
|
||||||
|
|
||||||
|
@notes It's not clear whether this is actually a version field
|
||||||
|
(the other 24 bytes here have equally arbitrary numbers in
|
||||||
|
them.) Changing the "version" to other values does not seem to
|
||||||
|
effect WiFi performance at all, neither does zeroing out the
|
||||||
|
first 5 reserved bytes in _reserved00. However zeroing bytes in
|
||||||
|
the _reserved06 region will break WiFi entirely.
|
||||||
|
*/
|
||||||
|
uint8_t version; /* 0x05 */
|
||||||
|
int8_t _reserved06[0x14]; /* 0x06 - 0x19 */
|
||||||
|
|
||||||
|
/* spur_freq = spur_freq_primary / spur_freq_divisor */
|
||||||
|
uint8_t spur_freq_primary; /* 0x1a */
|
||||||
|
uint8_t spur_freq_divisor; /* 0x1b */
|
||||||
|
|
||||||
|
/* Bitmask to enable spur_freq for each channel
|
||||||
|
Appears to be a big endian short word?
|
||||||
|
*/
|
||||||
|
uint8_t spur_freq_en_h; /* 0x1c */
|
||||||
|
uint8_t spur_freq_en_l; /* 0x1d */
|
||||||
|
|
||||||
|
uint8_t _reserved1e[4]; /* 0x1e - 0x21 */
|
||||||
|
|
||||||
|
/* Each value is a target power level.
|
||||||
|
Units are 1/4 dBm ie value 64 = 16dBm.
|
||||||
|
|
||||||
|
SDK defaults to using these transmit powers:
|
||||||
|
20.5dBm, 19.5dBm, 18.5dBm, 17dBm, 16dBm, 14dBm
|
||||||
|
|
||||||
|
@note Adjusting these values is confirmed to reduce
|
||||||
|
transmit power accordingly.
|
||||||
|
*/
|
||||||
|
uint8_t target_power[6]; /* 0x22 - 0x27 */
|
||||||
|
|
||||||
|
/* Maps 8 MCS (modulation & coding schemes) types for 802.11b, g &
|
||||||
|
* n to a target_power level index (0-5), set above.
|
||||||
|
|
||||||
|
This mapping of MCS slot to MCS type is derived from the
|
||||||
|
spreadsheet and also a table sent by Espressif, but is untested
|
||||||
|
and may be SDK version dependendent (especially any 802.11n
|
||||||
|
rates). However the general relationship is confirmed to hold
|
||||||
|
(higher MCS index = higher bit rate).
|
||||||
|
|
||||||
|
MCS 0: 1Mbps/2Mbps/5.5Mbps/11Mbps (802.11b) / 6Mbps/9Mbps (802.11g)
|
||||||
|
default target_power 0 (default 20.5dBm)
|
||||||
|
(see also pwr_ind_11b_en)
|
||||||
|
|
||||||
|
MCS 1: 12Mbps (802.11g)
|
||||||
|
default target_power 0 (default 20.5dBm)
|
||||||
|
|
||||||
|
MCS 2: 18Mbps (802.11g)
|
||||||
|
default target_power 1 (19.5dBm)
|
||||||
|
|
||||||
|
MCS 3: 24Mbps (802.11g)
|
||||||
|
default target_power 1 (19.5dBm)
|
||||||
|
|
||||||
|
MCS 4: 36Mbps (802.11g)
|
||||||
|
default target_power 2 (18.5dBm)
|
||||||
|
|
||||||
|
MCS 5: 48Mbps (802.11g)
|
||||||
|
default target_power 3 (17dBm)
|
||||||
|
|
||||||
|
MCS 6: 54Mbps (802.11g)
|
||||||
|
default target_power 4 (16dBm)
|
||||||
|
|
||||||
|
MCS 7: 65Mbps (802.11n) - unclear if ever used?
|
||||||
|
default target_power 5 (14dBm)
|
||||||
|
*/
|
||||||
|
uint8_t target_power_index_mcs[8]; /* 0x28 - 0x2f */
|
||||||
|
|
||||||
|
/* One of CRYSTAL_FREQ_40M / CRYSTAL_FREQ_26M / CRYSTAL_FREQ_24M
|
||||||
|
|
||||||
|
The crystal configured here is the input to the PLL setting
|
||||||
|
calculations which are used to derive the CPU & APB peripheral
|
||||||
|
clock frequency, and probably the WiFi PLLs (unconfirmed.)
|
||||||
|
*/
|
||||||
|
uint8_t crystal_freq; /* 0x30 */
|
||||||
|
|
||||||
|
uint8_t _unused31; /* 0x31: Possibly high byte of crystal freq? */
|
||||||
|
|
||||||
|
/* One of SDIO_CONFIG_AUTO, SDIO_CONFIG_SDIOV1_1, SDIO_CONFIG_SDIOV2_0 */
|
||||||
|
uint8_t sdio_config; /* 0x32 */
|
||||||
|
|
||||||
|
/* BT coexistence pin configuration.
|
||||||
|
|
||||||
|
One of BT_COEXIST_CONFIG_NONE, BT_COEXIST_CONFIG_A,
|
||||||
|
BT_COEXIST_CONFIG_PRESENT, BT_COEXIST_CONFIG_B
|
||||||
|
*/
|
||||||
|
uint8_t bt_coexist_config; /* 0x33 */
|
||||||
|
|
||||||
|
/* BT coexistence pin protocol.
|
||||||
|
|
||||||
|
If no coexistence:
|
||||||
|
Either BT_COEXIST_PROTOCOL_WIFI_ONLY, or
|
||||||
|
BT_COEXIST_PROTOCOL_BT_ONLY.
|
||||||
|
|
||||||
|
If coexistence:
|
||||||
|
Combine one of
|
||||||
|
BT_COEXIST_PROTOCOL_FLAG_SEPARATE_ANT or
|
||||||
|
BT_COEXIST_PROTOCOL_FLAG_SHARE_ANT
|
||||||
|
with one of
|
||||||
|
BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_ONLY or
|
||||||
|
BT_COEXIST_PROTOCOL_FLAG_BT_ACTIVE_BT_PRIORITY
|
||||||
|
*/
|
||||||
|
uint8_t bt_coexist_protocol; /* 0x34 */
|
||||||
|
|
||||||
|
/* Dual antenna configuration
|
||||||
|
|
||||||
|
One of DUAL_ANT_CONFIG_NONE, DUAL_ANT_CONFIG_DUAL,
|
||||||
|
DUAL_ANT_CONFIG_TX_GPIO0_HIGH_GPIO3_LOW,
|
||||||
|
DUAL_ANT_CONFIG_TX_GPIO0_LOW_GPIO3_HIGH
|
||||||
|
*/
|
||||||
|
uint8_t dual_ant_config; /* 0x35 */
|
||||||
|
|
||||||
|
uint8_t _reserved34; /* 0x36 */
|
||||||
|
|
||||||
|
/* For sharing crystal clock with other devices:
|
||||||
|
one of CRYSTAL_SLEEP_OFF, CRYSTAL_SLEEP_ON,
|
||||||
|
CRYSTAL_SLEEP_GPIO16, CRYSTAL_SLEEP_GPIO2
|
||||||
|
*/
|
||||||
|
uint8_t crystal_sleep; /* 0x37 */
|
||||||
|
|
||||||
|
uint8_t _unused38[8];
|
||||||
|
|
||||||
|
/* spur_freq_2 = spur_freq_2_primary / spur_freq_2_divisor */
|
||||||
|
uint8_t spur_freq_2_primary; /* 0x40 */
|
||||||
|
uint8_t spur_freq_2_divisor; /* 0x41 */
|
||||||
|
|
||||||
|
/* Bitmask to enable spur_freq_2 for each channel?
|
||||||
|
Appears to be a big endian short word?
|
||||||
|
*/
|
||||||
|
uint8_t spur_freq_2_en_h; /* 0x42 */
|
||||||
|
uint8_t spur_freq_2_en_l; /* 0x43 */
|
||||||
|
|
||||||
|
/* Not really clear what these do */
|
||||||
|
uint8_t spur_freq_cfg_msb; /* 0x44 */
|
||||||
|
uint8_t spur_freq_2_cfg_msb; /* 0x45 */
|
||||||
|
uint16_t spur_freq_3_cfg; /* 0x46 - 0x47 */
|
||||||
|
uint16_t spur_freq_4_cfg; /* 0x48 - 0x49 */
|
||||||
|
|
||||||
|
uint8_t _reserved4a[4]; /* 0x4a - 0x4d */
|
||||||
|
|
||||||
|
uint8_t _unused78[15]; /* 0x4e - 0x5c */
|
||||||
|
|
||||||
|
/* Flag to enable low power mode */
|
||||||
|
uint8_t low_power_en; /* 0x5d */
|
||||||
|
|
||||||
|
/* Low Power attenuation of RF gain stages 0 & 1
|
||||||
|
|
||||||
|
Attenuates transmit power if/when low_power_en is set.
|
||||||
|
|
||||||
|
Use one of the constants LP_ATTEN_STAGE01_0DB,
|
||||||
|
LP_ATTEN_STAGE01_2_5DB, LP_ATTEN_STAGE01_6DB,
|
||||||
|
LP_ATTEN_STAGE01_8_5DB, LP_ATTEN_STAGE01_11_5DB,
|
||||||
|
LP_ATTEN_STAGE01_14DB, LP_ATTEN_STAGE01_17_5DB,
|
||||||
|
LP_ATTEN_STAGE01_23DB.
|
||||||
|
*/
|
||||||
|
uint8_t lp_atten_stage01; /* 0x5e */
|
||||||
|
|
||||||
|
/* Low Power(?) attenuation of baseband gain
|
||||||
|
|
||||||
|
Units are minus 1/4 dB, ie value 4 == -1dB.
|
||||||
|
|
||||||
|
Maximum value is 24 (0x18) == -6dB
|
||||||
|
*/
|
||||||
|
uint8_t lp_atten_bb; /* 0x5f */
|
||||||
|
|
||||||
|
/* I believe this means, when pwr_ind_11b_en == 0 then the 802.11g
|
||||||
|
MCS 0 level from target_power_index_mcs are used to
|
||||||
|
determine 802.11b transmit power level.
|
||||||
|
|
||||||
|
However, when pwr_ind_11b_en == 1 then the index values in
|
||||||
|
pwr_ind_11b_0 & pwr_ind_11b_1 are used for 802.11b instead.
|
||||||
|
|
||||||
|
This is all unconfirmed, if you can confirm then please update
|
||||||
|
this comment.
|
||||||
|
*/
|
||||||
|
uint8_t pwr_ind_11b_en; /* 0x60 */
|
||||||
|
|
||||||
|
/* 802.11b low data rate power index (0~5).
|
||||||
|
Sets the power level index for operation at 1 & 2Mbps
|
||||||
|
*/
|
||||||
|
uint8_t pwr_ind_11b_0; /* 0x61 */
|
||||||
|
|
||||||
|
/* 802.11b high data rate power index (0~5)
|
||||||
|
Sets the power level index for operation at 5.5 & 11Mbps
|
||||||
|
*/
|
||||||
|
uint8_t pwr_ind_11b_1; /* 0x62 */
|
||||||
|
|
||||||
|
uint8_t _unused63[8]; /* 0x63 - 0x6a */
|
||||||
|
|
||||||
|
/* Set the voltage of PA_VDD, which appears to be an internal analog
|
||||||
|
reference voltage(?)
|
||||||
|
|
||||||
|
This field is called vdd33_const in the Arduino phy fields,
|
||||||
|
and relates to usage of the TOUT pin (ADC pin).
|
||||||
|
|
||||||
|
Set to PA_VDD_MEASURE_VCC (0xFF) and leave TOUT (ADC) pin
|
||||||
|
floating in order to use the ADC to measure the 3.3V input
|
||||||
|
voltage.
|
||||||
|
|
||||||
|
Set to value in the range 18-36 (1.8V to 3.6V) to set a
|
||||||
|
reference voltage(?) when using TOUT pin as an ADC input. I
|
||||||
|
think this is the reference voltage used to scale the 0-1V
|
||||||
|
which is allowed on the pin, in order to get an accurate
|
||||||
|
reading. So it should be set to a value that matches system
|
||||||
|
VCC... I think!
|
||||||
|
*/
|
||||||
|
uint8_t pa_vdd; /* 0x6b */
|
||||||
|
|
||||||
|
/* Disable RF calibration cycle for this many times */
|
||||||
|
uint8_t disable_rfcal_count; /* 0x6c */
|
||||||
|
|
||||||
|
uint8_t _unused6d[3];
|
||||||
|
|
||||||
|
/* Flags for frequency correction
|
||||||
|
|
||||||
|
A bitmask combination of any of: FREQ_CORRECT_DISABLE,
|
||||||
|
FREQ_CORRECT_ENABLE, FREQ_CORRECT_BB_160M, FREQ_CORRECT_FORCE
|
||||||
|
*/
|
||||||
|
uint8_t freq_correct_mode; /* 0x70 */
|
||||||
|
|
||||||
|
/* Force frequency offset adjustment (instead of auto measuring)
|
||||||
|
units are 1 = 8kHz, full range +/- 1016kHz.
|
||||||
|
|
||||||
|
Only used if FREQ_CORRECT_ENABLE and FREQ_CORRECT_FORCE are
|
||||||
|
set in freq_correct_mode.
|
||||||
|
|
||||||
|
Unclear whether setting FREQ_CORRECT_BB_160M (which allows only positive offsets) changes the usable range.
|
||||||
|
*/
|
||||||
|
int8_t force_freq_offset; /* 0x71 */
|
||||||
|
|
||||||
|
/* Use stored data in flash for RF calibration.
|
||||||
|
|
||||||
|
This field was previously called rf_cal_use_flash.
|
||||||
|
|
||||||
|
Acceptable values one of RF_CAL_MODE_SAVED, RF_CAL_MODE_TXPOWER_ONLY, RF_CAL_MODE_SAVED_2, RF_CAL_MODE_FULL.
|
||||||
|
*/
|
||||||
|
uint8_t rf_cal_mode; /* 0x72 */
|
||||||
|
|
||||||
|
uint8_t _unused73[13];
|
||||||
|
} sdk_phy_info_t;
|
||||||
|
|
||||||
|
/* Some sanity check static assertions. These can probably be
|
||||||
|
removed after this structure has been better tested.
|
||||||
|
*/
|
||||||
|
_Static_assert(sizeof(sdk_phy_info_t) == 128, "sdk_phy_info_t is wrong size!");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, version) == 5, "version at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, target_power) == 34, "target_power_qdb at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, bt_coexist_protocol) == 52, "bt_coexist_protocol at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, spur_freq_2_primary) == 64, "spur_freq_2_primary at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, lp_atten_stage01) == 94, "lp_atten_stage01 at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, pa_vdd) == 107, "pa_vdd aka vdd33_const at wrong offset");
|
||||||
|
_Static_assert(offsetof(sdk_phy_info_t, rf_cal_mode) == 114, "rf_cal_use_flash at wrong offset!");
|
||||||
|
|
||||||
|
/* Read the default PHY info into the supplied structure.
|
||||||
|
|
||||||
|
This function is weak-aliased to get_sdk_default_phy_info() so you
|
||||||
|
can replace it with your own if you want to vary the default values
|
||||||
|
- suggested way to do this is to call get_sdk_default_phy_info()
|
||||||
|
and then only update the fields you care about.
|
||||||
|
|
||||||
|
The default PHY info is used at startup whenever the version field
|
||||||
|
in the default sdk_phy_info_t does not match the version field
|
||||||
|
stored in flash. So you can increment the version field to force a
|
||||||
|
reset to defaults, regardless of what values are in flash.
|
||||||
|
*/
|
||||||
|
void get_default_phy_info(sdk_phy_info_t *info);
|
||||||
|
|
||||||
|
/* Read the "SDK default" PHY info as used by the Espressif SDK */
|
||||||
|
void get_sdk_default_phy_info(sdk_phy_info_t *info);
|
||||||
|
|
||||||
|
/* Read the PHY info currently stored in the SPI flash SDK configuration sector.
|
||||||
|
|
||||||
|
This PHY info is updated by the SDK following RF calibration, etc.
|
||||||
|
|
||||||
|
Note that the saved data may be corrupt - read the 'version' field to verify.
|
||||||
|
*/
|
||||||
|
void read_saved_phy_info(sdk_phy_info_t *info);
|
||||||
|
|
||||||
|
/* Update the saved PHY info in the SPI flash. A reset is necessary to use these values.
|
||||||
|
|
||||||
|
Note that the SDK may clobber these values, so it's recommended you reset ASAP after updating them.
|
||||||
|
*/
|
||||||
|
void write_saved_phy_info(const sdk_phy_info_t *info);
|
||||||
|
|
||||||
|
/* Dump known fields in the phy info structure to stdout,
|
||||||
|
if 'raw' flag is set then the raw hex values are also dumped.
|
||||||
|
*/
|
||||||
|
void dump_phy_info(const sdk_phy_info_t *info, bool raw);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue