diff --git a/df_datalink_ge/src/Xilinx.spec b/df_datalink_ge/src/Xilinx.spec deleted file mode 100644 index 8eea377..0000000 --- a/df_datalink_ge/src/Xilinx.spec +++ /dev/null @@ -1,2 +0,0 @@ -*startfile: -crti%O%s crtbegin%O%s diff --git a/df_datalink_ge/src/config/app_config.h b/df_datalink_ge/src/config/app_config.h index c7b80d6..834a5c0 100644 --- a/df_datalink_ge/src/config/app_config.h +++ b/df_datalink_ge/src/config/app_config.h @@ -10,24 +10,30 @@ * History: * [2021-04-28]: Initial edition. * - * Copyright(c) 2021 Beijing Institute of Technology. + * Copyright(c) 2024 Beijing Institute of Technology. * Lab of Communication and Networking * ******************************************************************************/ -#ifndef CONFIG_H_ -#define CONFIG_H_ - -#define XILINX_PLATFORM +#ifndef __APP_CONFIG_H_ +#define __APP_CONFIG_H_ #include "xparameters.h" -/******** Software Version ********/ -#define _APP_VER 0x00010008 +#ifdef PLATFORM_ZYNQMP // Zynq MPSoC (Zynq UltraScale+) +#define HSJL_GE +#elif defined(PLATFORM_ZYNQ) +#define HSJL_NODE +#else +#error Unsupported hardware... +#endif -#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24) -#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16) -#define _APP_VER_PATCH (_APP_VER & 0x0000FFFF) +/******** Software Version ********/ +#define _APP_VER 0x00010008 + +#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24) +#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16) +#define _APP_VER_PATCH (_APP_VER & 0x0000FFFF) /*********** Debug Info Level ************/ // #define _DEBUG_LEVEL 1 @@ -36,35 +42,41 @@ // 1 - print only errors // other - print nothing -#define APP_EMULATE_DATA #define DATALINK_ENABLE_AUTORECONNECT #define DATALINK_ENABLE_AUTOTIMESYNC -//#define DATALINK_ENABLE_BERTEST - +// #define DATALINK_ENABLE_BERTEST /************ Hardware Configs ************/ -#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ -#define GLOBAL_TIMER_CLK_HZ (CPU_CLK_HZ/2) -#define SCU_TIMER_CLK_HZ (CPU_CLK_HZ/2) -#define FCLK_CLK0_HZ 100000000 - +#ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+) +#define CPU_CLK_HZ XPAR_CPU_CORTEXA53_0_CPU_CLK_FREQ_HZ +#define FCLK_CLK0_HZ 100000000 +#define APP_TIMER_CLK_HZ FCLK_CLK0_HZ +#else // Zynq-7000 +#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ +#define APP_TIMER_CLK_HZ (CPU_CLK_HZ / 2) +#define FCLK_CLK0_HZ 100000000 +#endif /********* Zynq Platform Configs **********/ -// SCU Timer (for logging) -#define SCUTIMER_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID -#define SCUTIMER_INTR_ID XPAR_SCUTIMER_INTR - +// APP Timer (for logging) +#ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+) +#define APPTIMER_DEVICE_ID XPAR_AXI_TIMER_DEVICE_ID +#define APPTIMER_INTR_ID XPAR_FABRIC_AXI_TIMER_INTERRUPT_INTR +#else +#define APPTIMER_DEVICE_ID XPAR_PS7_SCUTIMER_0_DEVICE_ID +#define APPTIMER_INTR_ID XPAR_SCUTIMER_INTR +#endif // Physical Layer Configs -#define PHY_DEVICE_ID 0 -#define PHY_BASEADDR XPAR_PHYC_BASEADDR -#define PHY_BEAM_SET_PRESET +#define PHY_DEVICE_ID (0x01 | 0x00) +#define PHY_BASEADDR XPAR_PHYC_BASEADDR #define PHY_BEAM_FORMING_ENABLE // -- Antenna Bram Configs -#define PHY_ANTCONFIG_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_INFO_BRAM_CTRL_DEVICE_ID +#define PHY_ANTCONFIG_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_CONFIG_BRAM_CTRL_DEVICE_ID +#define PHY_ANTINFO_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_ANT_BEAM_BRAM_CTRL_DEVICE_ID // -- Buffers #define PHY_TXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_TX_FRAME_BRAM_CTRL_DEVICE_ID #define PHY_RXBUFF_BRAM_DEVICE_ID XPAR_PHY_DATA_INTERFACE_RX_FRAME_BRAM_CTRL_DEVICE_ID // -- Xadc -#define PHY_HW_XADC_DEVICE_ID XPAR_PS7_XADC_0_DEVICE_ID +#define PHY_HW_SYSMON_DEVICE_ID XPAR_SYSTEM_MANAGEMENT_DEVICE_ID // -- Interrupt id #define PHY_INTR_ID XPAR_FABRIC_PHY_IRQ_INTR #define PERIODIC_5MS_INTR_ID XPAR_FABRIC_PHY_5MS_DELAY_2MS_INTR @@ -73,19 +85,202 @@ #define TIME_CONTROLLER_BASEADDR XPAR_TMC_BASEADDR // System Bus Configs -#define MPC_BRAM_ID XPAR_MPC_BRAM_INTERFACE_MPC_BRAM_CTRL_DEVICE_ID -#define MPC_GPIO_ID XPAR_MPC_GPIO_DEVICE_ID -#define MPC_TX_INTR_ID XPAR_FABRIC_MPC_TX_IRQ_INTR -#define MPC_RX_INTR_ID XPAR_FABRIC_MPC_RX_IRQ_INTR - -// Global Timer config -#define GLOBAL_TIMER_DEVICE_ID XPAR_GLOBAL_TMR_DEVICE_ID -#define GLOBAL_TIMER_BASEADDR XPAR_GLOBAL_TMR_BASEADDR -#define GLOBAL_TIMER_INTR_ID XPAR_GLOBAL_TMR_INTR +#define SYSBUS_BASE_ADDR XPAR_SYSTEMBUS_BASEADDR +#define SYSBUS_TX_INTR_ID XPAR_FABRIC_SYSTEMBUS_TX_DONE_INTR +#define SYSBUS_RX_INTR_ID XPAR_FABRIC_SYSTEMBUS_RX_DONE_INTR // INTC configis #define INTC_DEVICE_ID XPAR_SCUGIC_0_DEVICE_ID +/********* Hardware Configurations **********/ +#ifdef HSJL_GE // Zynq MPSoC (Zynq UltraScale+) +#define RFSOC +#define LMK04828 +//#define LMX2594_ADC +//#define LMX2594_DAC +#define RFDC_DEVICE_ID XPAR_XRFDC_0_DEVICE_ID +#else +#define AD9361_REG +//#define AD9361_API +#define AD9528 +//#define AD9653 +//#define AD9694 +#endif + +// AD9361 Configuration +#define SPI_INTERFACE_SPI_ENGINE +#define HAVE_SPLIT_GAIN_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define HAVE_TDD_SYNTH_TABLE 1 /* only set to 0 in case split_gain_table_mode_enable = 0*/ +#define AD9361_DEVICE 1 /* set it 1 if AD9361 device is used, 0 otherwise */ +#define AD9364_DEVICE 0 /* set it 1 if AD9364 device is used, 0 otherwise */ +#define AD9363A_DEVICE 0 /* set it 1 if AD9363A device is used, 0 otherwise */ +#define HAVE_VERBOSE_MESSAGES /* Recommended during development prints errors and warnings */ +// #define HAVE_DEBUG_MESSAGES /* For Debug purposes only */ +// AD9361 GPIO Configurations +#define AD9361_GPIO_DEVICE_ID 0 +#define AD9361_GPIO_OFFSET 54 +#define AD9361_GPIO_INPUT 0 +#define AD9361_GPIO_OUTPUT 1 +#define AD9361_GPIO_DISABLE 0 +#define AD9361_GPIO_ENABLE 1 +// -- AD9361-1 SPI Engine Configuration +#define AD9361_SPI_DEVICE_ID 0 +#define AD9361_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9361_SPI_ENGINE_MAX_SPEED 5000000 +#define AD9361_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define AD9361_SPI_ENGINE_DATA_WIDTH 8 +#define AD9361_SPI_ENGINE_CS_DELAY 3 +#define AD9361_TIMEOUT_TH 2000 +#define AD9361_1_SPI_CS 0x01 +#define AD9361_2_SPI_CS 0x02 +#define AD9361_2_TIMEOUT_TH 2000 +// -- AD9361-1 GPIO +#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 6) +#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 7) +#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 8) +#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 9) +#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 10) +#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 11) +#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 12) +#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 13) +#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 14) +#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 15) +#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 16) +#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 17) +#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 18) +#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 19) +#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 20) +#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 21) +// -- AD9361-2 GPIO +#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 22) +#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 23) +#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 24) +#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 25) +#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 26) +#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 27) +#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 28) +#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 29) +#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 30) +#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 31) +#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 32) +#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 33) +#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 34) +#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 35) +#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 36) +#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 37) +// AD9361-Status Code +#define AD9361_SYNC (AD9361_GPIO_OFFSET + 38) +#define AD9361_RX_FIFO_RST (AD9361_GPIO_OFFSET + 39) +#define AD9361_1_CAL_START (AD9361_GPIO_OFFSET + 40) +#define AD9361_2_CAL_START (AD9361_GPIO_OFFSET + 41) +#define AD9361_RECAL (AD9361_GPIO_OFFSET + 42) +#define AD9361_TX_SWITCH (AD9361_GPIO_OFFSET + 43) +#define AD9361_1_CAL_DONE (AD9361_GPIO_OFFSET + 44) +#define AD9361_2_CAL_DONE (AD9361_GPIO_OFFSET + 45) +#define AD9361_CAL_RESULT (AD9361_GPIO_OFFSET + 46) + +typedef enum +{ + TX_FREQ_125, + TX_FREQ_126, + TX_FREQ_4125 +} ad9361TxFreq; + +// HMC7044 Configurations +#define HMC7044_GPIO_DEVICE_ID 0 +#define HMC7044_GPIO_OFFSET 54 +#define HMC7044_RESET (HMC7044_GPIO_OFFSET + 0) +#define HMC7044_SYNC (HMC7044_GPIO_OFFSET + 1) +#define HMC7044_GPIO_0 (HMC7044_GPIO_OFFSET + 2) +#define HMC7044_GPIO_1 (HMC7044_GPIO_OFFSET + 3) +#define HMC7044_GPIO_2 (HMC7044_GPIO_OFFSET + 4) +#define HMC7044_GPIO_3 (HMC7044_GPIO_OFFSET + 5) +// -- HMC7044 SPI Engine Configuration +#define HMC7044_SPI_DEVICE_ID 0 +#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define HMC7044_SPI_ENGINE_MAX_SPEED 5000000 +#define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define HMC7044_SPI_ENGINE_DATA_WIDTH 8 +#define HMC7044_SPI_ENGINE_CS_DELAY 3 +#define HMC7044_SPI_CS_HMC7044 0x00 + +// AD9528 Configurations +#define AD9528_GPIO_DEVICE_ID 0 +#define AD9528_GPIO_OFFSET 54 +#define AD9528_RESETB (AD9528_GPIO_OFFSET+0) +#define AD9528_SYSREF_REQ (AD9528_GPIO_OFFSET+1) +#define AD9528_STATUS_0 (AD9528_GPIO_OFFSET+2) +#define AD9528_STATUS_1 (AD9528_GPIO_OFFSET+3) +// -- AD9528 SPI Engine Configuration +#define AD9528_SPI_DEVICE_ID 0 +#define AD9528_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9528_SPI_ENGINE_MAX_SPEED 5000000 +#define AD9528_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define AD9528_SPI_ENGINE_DATA_WIDTH 8 +#define AD9528_SPI_ENGINE_CS_DELAY 3 +#define AD9528_SPI_CS 0x00 + +// LMK04828 Configurations +#define LMK04828_GPIO_DEVICE_ID 0 +#define LMK04828_GPIO_OFFSET 54 +// -- LMK04828 SPI Engine Configuration +#define LMK04828_SPI_DEVICE_ID 0 +#define LMK04828_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMK04828_SPI_ENGINE_MAX_SPEED 5000000 +#define LMK04828_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define LMK04828_SPI_ENGINE_DATA_WIDTH 8 +#define LMK04828_SPI_ENGINE_CS_DELAY 3 +#define LMK04828_SPI_CS 0x00 + +// LMX2594_ADC Configurations +#define LMX2594_ADC_GPIO_DEVICE_ID 0 +#define LMX2594_ADC_GPIO_OFFSET 54 +// -- LMX2594_ADC SPI Engine Configuration +#define LMX2594_ADC_SPI_DEVICE_ID 0 +#define LMX2594_ADC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMX2594_ADC_SPI_ENGINE_MAX_SPEED 5000000 +#define LMX2594_ADC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define LMX2594_ADC_SPI_ENGINE_DATA_WIDTH 8 +#define LMX2594_ADC_SPI_ENGINE_CS_DELAY 3 +#define LMX2594_ADC_SPI_CS 0x01 + +// LMX2594_DAC Configurations +#define LMX2594_DAC_GPIO_DEVICE_ID 0 +#define LMX2594_DAC_GPIO_OFFSET 54 +// -- LMX2594_DAC SPI Engine Configuration +#define LMX2594_DAC_SPI_DEVICE_ID 0 +#define LMX2594_DAC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define LMX2594_DAC_SPI_ENGINE_MAX_SPEED 5000000 +#define LMX2594_DAC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define LMX2594_DAC_SPI_ENGINE_DATA_WIDTH 8 +#define LMX2594_DAC_SPI_ENGINE_CS_DELAY 3 +#define LMX2594_DAC_SPI_CS 0x02 + +// AD9653 Configurations +#define AD9653_GPIO_DEVICE_ID 0 +#define AD9653_GPIO_OFFSET 54 +#define AD9653_POWR_DOWN (AD9653_GPIO_OFFSET+0) +// -- AD9653 SPI Engine Configuration +#define AD9653_SPI_DEVICE_ID 0 +#define AD9653_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9653_SPI_ENGINE_MAX_SPEED 5000000 +#define AD9653_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define AD9653_SPI_ENGINE_DATA_WIDTH 8 +#define AD9653_SPI_ENGINE_CS_DELAY 3 +#define AD9653_SPI_CS 0x03 + +// AD9694 Configurations +#define AD9694_GPIO_DEVICE_ID 0 +#define AD9694_GPIO_OFFSET 54 +// -- AD9694 SPI Engine Configuration +#define AD9694_SPI_DEVICE_ID 0 +#define AD9694_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ +#define AD9694_SPI_ENGINE_MAX_SPEED 5000000 +#define AD9694_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR +#define AD9694_SPI_ENGINE_DATA_WIDTH 8 +#define AD9694_SPI_ENGINE_CS_DELAY 3 +#define AD9694_SPI_CS 0x03 + // Configuration Check #if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE) #define PHY_BEAM_FORMING_ENABLE @@ -94,8 +289,8 @@ #if defined(DATALINK_ENABLE_BERTEST) #if !defined(DATALINK_ENABLE_AUTOTIMESYNC) - #warning To enbale bit error rate test, auto time-sync should be enabled... +#warning To enbale bit error rate test, auto time-sync should be enabled... #endif #endif -#endif +#endif //__APP_CONFIG_H_ diff --git a/df_datalink_ge/src/config/platform.c b/df_datalink_ge/src/config/platform.c deleted file mode 100644 index 364f8ce..0000000 --- a/df_datalink_ge/src/config/platform.c +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2010 - 2015 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ - -#include "xparameters.h" -#include "xil_cache.h" -#include "platform_config.h" - -/* - * Uncomment one of the following two lines, depending on the target, - * if ps7/psu init source files are added in the source directory for - * compiling example outside of SDK. - */ -/*#include "ps7_init.h"*/ -/*#include "psu_init.h"*/ - -#ifdef STDOUT_IS_16550 - #include "xuartns550_l.h" - - #define UART_BAUD 9600 -#endif - -void -enable_caches() -{ -#ifdef __PPC__ - Xil_ICacheEnableRegion(CACHEABLE_REGION_MASK); - Xil_DCacheEnableRegion(CACHEABLE_REGION_MASK); -#elif __MICROBLAZE__ -#ifdef XPAR_MICROBLAZE_USE_ICACHE - Xil_ICacheEnable(); -#endif -#ifdef XPAR_MICROBLAZE_USE_DCACHE - Xil_DCacheEnable(); -#endif -#endif -} - -void -disable_caches() -{ -#ifdef __MICROBLAZE__ -#ifdef XPAR_MICROBLAZE_USE_DCACHE - Xil_DCacheDisable(); -#endif -#ifdef XPAR_MICROBLAZE_USE_ICACHE - Xil_ICacheDisable(); -#endif -#endif -} - -void -init_uart() -{ -#ifdef STDOUT_IS_16550 - XUartNs550_SetBaud(STDOUT_BASEADDR, XPAR_XUARTNS550_CLOCK_HZ, UART_BAUD); - XUartNs550_SetLineControlReg(STDOUT_BASEADDR, XUN_LCR_8_DATA_BITS); -#endif - /* Bootrom/BSP configures PS7/PSU UART to 115200 bps */ -} - -void -init_platform() -{ - /* - * If you want to run this example outside of SDK, - * uncomment one of the following two lines and also #include "ps7_init.h" - * or #include "ps7_init.h" at the top, depending on the target. - * Make sure that the ps7/psu_init.c and ps7/psu_init.h files are included - * along with this example source files for compilation. - */ - /* ps7_init();*/ - /* psu_init();*/ - enable_caches(); - init_uart(); -} - -void -cleanup_platform() -{ - disable_caches(); -} diff --git a/df_datalink_ge/src/config/platform.h b/df_datalink_ge/src/config/platform.h deleted file mode 100644 index e273e37..0000000 --- a/df_datalink_ge/src/config/platform.h +++ /dev/null @@ -1,41 +0,0 @@ -/****************************************************************************** -* -* Copyright (C) 2008 - 2014 Xilinx, Inc. All rights reserved. -* -* Permission is hereby granted, free of charge, to any person obtaining a copy -* of this software and associated documentation files (the "Software"), to deal -* in the Software without restriction, including without limitation the rights -* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -* copies of the Software, and to permit persons to whom the Software is -* furnished to do so, subject to the following conditions: -* -* The above copyright notice and this permission notice shall be included in -* all copies or substantial portions of the Software. -* -* Use of the Software is limited solely to applications: -* (a) running on a Xilinx device, or -* (b) that interact with a Xilinx device through a bus or interconnect. -* -* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF -* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -* SOFTWARE. -* -* Except as contained in this notice, the name of the Xilinx shall not be used -* in advertising or otherwise to promote the sale, use or other dealings in -* this Software without prior written authorization from Xilinx. -* -******************************************************************************/ - -#ifndef __PLATFORM_H_ -#define __PLATFORM_H_ - -#include "platform_config.h" - -void init_platform(); -void cleanup_platform(); - -#endif diff --git a/df_datalink_ge/src/config/platform_config.h b/df_datalink_ge/src/config/platform_config.h deleted file mode 100644 index e2fd813..0000000 --- a/df_datalink_ge/src/config/platform_config.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef __PLATFORM_CONFIG_H_ -#define __PLATFORM_CONFIG_H_ - -#define STDOUT_IS_PS7_UART -#define UART_DEVICE_ID 0 - -#endif diff --git a/df_datalink_ge/src/dev_profile/ad9361_1_reg_profile.c b/df_datalink_ge/src/dev_profile/ad9361_1_reg_profile.c new file mode 100644 index 0000000..c5268cf --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9361_1_reg_profile.c @@ -0,0 +1,1233 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +#define TIMEOUT_TH AD9361_TIMEOUT_TH + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +// ad9361-1 +static struct spi_init_param ad9361_1_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_1_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_1_reg_gpio_resetb_init = { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +struct ad9361_reg_init_param ad9361_1_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_1_reg_spi_init, + .gpio_resetb = &ad9361_1_reg_gpio_resetb_init +}; + +uint32_t ad9361_1_reg_config(struct ad9361_reg_dev *dev){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + + //************************************************************ + // AD9361 R2 Auto Generated Initialization Script: This script was + // generated using the AD9361 Customer software Version 2.1.3 + //************************************************************ + // Profile: Custom + // REFCLK_IN: 40.000 MHz + + + status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation + status = ad9361_reg_write(dev, 0x02A6, 0x0E); // Enable Master Bias + status = ad9361_reg_write(dev, 0x02A8, 0x0E); // Set Bandgap Trim + status = ad9361_reg_write(dev, 0x02AB, 0x07); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x02AC, 0xFF); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0009, 0x17); // Enable Clocks + mdelay(20) ;// waits 20 ms + + //************************************************************ + // Set BBPLL Frequency: 1152.000000 + //************************************************************ + status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0046, 0x02); // Set BBPLL Loop Filter Charge Pump current + status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1 + status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1 + status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2 + status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy + status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy + status = ad9361_reg_write(dev, 0x0043, 0x00); // BBPLL Freq Word (Fractional[7:0]) + status = ad9361_reg_write(dev, 0x0042, 0xC0); // BBPLL Freq Word (Fractional[15:8]) + status = ad9361_reg_write(dev, 0x0041, 0x0C); // BBPLL Freq Word (Fractional[23:16]) + status = ad9361_reg_write(dev, 0x0044, 0x0E); // BBPLL Freq Word (Integer[7:0]) + status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration + status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit + status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin + + // Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 172.800 us (Done when 0x05E[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x005E, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + + status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0003, 0xE4); // Setup Rx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate + + //************************************************************ + // Setup the Parallel Port (Digital Data Interface) + //************************************************************ + status = ad9361_reg_write(dev, 0x0010, 0x08); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK + status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data + status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits + status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data) + status = ad9361_reg_write(dev, 0x0007, 0x0F); // PPORT TX Delay (adjusts setup/hold FBCLK->Data) + + //************************************************************ + // Setup AuxDAC + //************************************************************ + status = ad9361_reg_write(dev, 0x0018, 0x00); // AuxDAC1 Word[9:2] + status = ad9361_reg_write(dev, 0x0019, 0x00); // AuxDAC2 Word[9:2] + status = ad9361_reg_write(dev, 0x001A, 0x00); // AuxDAC1 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x001B, 0x00); // AuxDAC2 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x0023, 0xFF); // AuxDAC Manaul/Auto Control + status = ad9361_reg_write(dev, 0x0026, 0x00); // AuxDAC Manual Select Bit/GPO Manual Select + status = ad9361_reg_write(dev, 0x0030, 0x00); // AuxDAC1 Rx Delay + status = ad9361_reg_write(dev, 0x0031, 0x00); // AuxDAC1 Tx Delay + status = ad9361_reg_write(dev, 0x0032, 0x00); // AuxDAC2 Rx Delay + status = ad9361_reg_write(dev, 0x0033, 0x00); // AuxDAC2 Tx Delay + + //************************************************************ + // Setup AuxADC + //************************************************************ + status = ad9361_reg_write(dev, 0x000B, 0x00); // Temp Sensor Setup (Offset) + status = ad9361_reg_write(dev, 0x000C, 0x00); // Temp Sensor Setup (Temp Window) + status = ad9361_reg_write(dev, 0x000D, 0x03); // Temp Sensor Setup (Periodic Measure) + status = ad9361_reg_write(dev, 0x000F, 0x04); // Temp Sensor Setup (Decimation) + status = ad9361_reg_write(dev, 0x001C, 0x00); // AuxADC Setup (Clock Div) + status = ad9361_reg_write(dev, 0x001D, 0x01); // AuxADC Setup (Decimation/Enable) + + //************************************************************ + // Setup Control Outs + //************************************************************ + status = ad9361_reg_write(dev, 0x0035, 0x00); // Ctrl Out index + status = ad9361_reg_write(dev, 0x0036, 0xFF); // Ctrl Out [7:0] output enable + + //************************************************************ + // Setup GPO + //************************************************************ + status = ad9361_reg_write(dev, 0x003A, 0x27); // Set number of REFCLK cycles for 1us delay timer + status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX + status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT + status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay + status = ad9361_reg_write(dev, 0x0029, 0x00); // GPO_1 RX Delay + status = ad9361_reg_write(dev, 0x002A, 0x00); // GPO_2 RX Delay + status = ad9361_reg_write(dev, 0x002B, 0x00); // GPO_3 RX Delay + status = ad9361_reg_write(dev, 0x002C, 0x00); // GPO_0 TX Delay + status = ad9361_reg_write(dev, 0x002D, 0x00); // GPO_1 TX Delay + status = ad9361_reg_write(dev, 0x002E, 0x00); // GPO_2 TX Delay + status = ad9361_reg_write(dev, 0x002F, 0x00); // GPO_3 TX Delay + + //************************************************************ + // Setup RF PLL non-frequency-dependent registers + //************************************************************ + status = ad9361_reg_write(dev, 0x0261, 0x00); // Set Rx LO Power mode + status = ad9361_reg_write(dev, 0x02A1, 0x00); // Set Tx LO Power mode + status = ad9361_reg_write(dev, 0x0248, 0x0B); // Enable Rx VCO LDO + status = ad9361_reg_write(dev, 0x0288, 0x0B); // Enable Tx VCO LDO + status = ad9361_reg_write(dev, 0x0246, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0286, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0249, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x0289, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x023B, 0x80); // Enable Rx VCO cal + status = ad9361_reg_write(dev, 0x027B, 0x80); // Enable Tx VCO cal + status = ad9361_reg_write(dev, 0x0243, 0x0D); // Set Rx prescaler bias + status = ad9361_reg_write(dev, 0x0283, 0x0D); // Set Tx prescaler bias + status = ad9361_reg_write(dev, 0x023D, 0x00); // Clear Half VCO cal clock setting + status = ad9361_reg_write(dev, 0x027D, 0x00); // Clear Half VCO cal clock setting + + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth mode bit + status = ad9361_reg_write(dev, 0x0014, 0x1D); // Set Force ALERT State bit + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD mode + mdelay(1); // waits 1 ms + + status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal + + // Wait for CP cal to complete, Max RXCP Cal time: 460.800 (us)(Done when 0x244[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0244, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal + + // Wait for CP cal to complete, Max TXCP Cal time: 460.800 (us)(Done when 0x284[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0284, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + //************************************************************ + // FDD RX,TX Synth Frequency: 1500.000000,1500.000000 MHz + //************************************************************ + //************************************************************ + // Setup Rx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0239, 0xC3); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0242, 0x1F); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0238, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0251, 0x0C); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x023B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x023E, 0xD4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0240, 0x09); // Set Synth Loop Filter R3 + + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC3); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x1F); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0C); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xD4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x09); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Rx and Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0233, 0x00); // Write Rx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0234, 0x00); // Write Rx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0235, 0x00); // Write Rx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0231, 0x4B); // Write Rx Synth Integer Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0005, 0x11); // Set LO divider setting + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0x4B); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x11); // Set LO divider setting + + //************************************************************ + // Program Mixer GM Sub-table + //************************************************************ + status = ad9361_reg_write(dev, 0x013F, 0x02); // Start Clock + status = ad9361_reg_write(dev, 0x0138, 0x0F); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x78); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x00); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0E); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x74); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x0D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0D); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x70); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x15); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0C); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x6C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x1B); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0B); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x68); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x21); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0A); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x64); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x25); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x09); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x60); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x29); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x08); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x5C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2C); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x07); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x58); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2F); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x06); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x54); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x31); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x05); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x50); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x33); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x04); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x4C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x34); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x03); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x48); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x35); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x02); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x30); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3A); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x01); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x18); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x00); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x00); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3E); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x02); // Clear Write Bit + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x00); // Stop Clock + + //************************************************************ + // Program Rx Gain Tables with GainTable800MHz.csv + //************************************************************ + + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Start Gain Table Clock + status = ad9361_reg_write(dev, 0x0130, 0x00); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x01); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x02); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x03); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x01); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x04); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x02); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x05); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x06); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x07); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x08); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x09); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x06); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x07); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x08); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x10); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x11); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x12); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x13); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x14); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x15); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x16); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x17); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x18); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x19); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x10); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x20); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x21); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x22); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x23); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x24); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x25); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x26); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x22); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x27); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x23); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x28); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x24); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x29); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x25); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x26); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x27); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x30); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x31); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x32); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x33); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x34); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x35); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x36); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x37); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x38); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x39); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x33); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x34); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x35); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x36); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x40); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x37); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x41); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x42); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x65); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x43); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x66); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x44); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x67); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x45); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x68); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x46); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x69); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x47); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6A); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x48); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6B); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x49); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6C); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6D); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6E); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6F); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x50); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x51); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x52); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x53); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x54); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x55); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x56); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x57); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x58); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x59); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x5A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Clear Write Bit + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x00); // Stop Gain Table Clock + //************************************************************ + // Setup Rx Manual Gain Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x00FA, 0xE0); // Gain Control Mode Select + status = ad9361_reg_write(dev, 0x00FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + status = ad9361_reg_write(dev, 0x00FC, 0x23); // Incr Step Size, ADC Overrange Size + status = ad9361_reg_write(dev, 0x00FD, 0x4C); // Max Full/LMT Gain Table Index + status = ad9361_reg_write(dev, 0x00FE, 0x44); // Decr Step Size, Peak Overload Time + status = ad9361_reg_write(dev, 0x0100, 0x6F); // Max Digital Gain + status = ad9361_reg_write(dev, 0x0104, 0x2F); // ADC Small Overload Threshold + status = ad9361_reg_write(dev, 0x0105, 0x3A); // ADC Large Overload Threshold + status = ad9361_reg_write(dev, 0x0107, 0x2B); // Small LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0108, 0x31); // Large LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0109, 0x00); // Rx1 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010A, 0x58); // Rx1 LPF Gain Index + status = ad9361_reg_write(dev, 0x010B, 0x00); // Rx1 Digital Gain Index + status = ad9361_reg_write(dev, 0x010C, 0x00); // Rx2 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010D, 0x18); // Rx2 LPF Gain Index + status = ad9361_reg_write(dev, 0x010E, 0x00); // Rx2 Digital Gain Index + status = ad9361_reg_write(dev, 0x0114, 0x30); // Low Power Threshold + status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit + status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control + //************************************************************ + // RX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter + // Corner @ 28.000000 MHz) + //************************************************************ + status = ad9361_reg_write(dev, 0x01FB, 0x14); // RX Freq Corner (MHz) + status = ad9361_reg_write(dev, 0x01FC, 0x00); // RX Freq Corner (Khz) + status = ad9361_reg_write(dev, 0x01F8, 0x05); // Rx BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM + status = ad9361_reg_write(dev, 0x01C0, 0x03); // Set GM common mode + status = ad9361_reg_write(dev, 0x01E2, 0x02); // Enable Rx1 Filter Tuner + status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune + + // Wait for RX filter to tune, Max Cal Time: 2.648 us (Done when 0x016[7]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1) + status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2) + //************************************************************ + // TX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter + // Corner @ 32.000000 MHz) + //************************************************************ + status = ad9361_reg_write(dev, 0x00D6, 0x04); // TX BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune + + // Wait for TX filter to tune, Max Cal Time: 1.233 us (Done when 0x016[6]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x40) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels) + //************************************************************ + // RX TIA Setup: Setup values scale based on RxBBF calibration + // results. See information in Calibration Guide. + //************************************************************ + status = ad9361_reg_write(dev, 0x01DB, 0x20); // Set TIA selcc[2:0] + status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DC, 0x47); // Set RX TIA1 C LSB[5:0] + status = ad9361_reg_write(dev, 0x01DE, 0x47); // Set RX TIA2 C LSB[5:0] + + //************************************************************ + // TX Secondary Filter Calibration Setup: Real Bandwidth + // 20.000000MHz, 3dB Corner @ 100.000000MHz + //************************************************************ + status = ad9361_reg_write(dev, 0x00D2, 0x04); // TX Secondary Filter PDF Cap cal[5:0] + status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0] + status = ad9361_reg_write(dev, 0x00D0, 0x57); // Pdampbias + + //************************************************************ + // ADC Setup: Tune ADC Performance based on RX analog filter tune + // corner. Real Bandwidth: 18.155158 MHz, ADC Clock Frequency: + // 288.000000 MHz. The values in registers 0x200 - 0x227 need to be + // calculated using the equations in the Calibration Guide. + //************************************************************ + + status = ad9361_reg_write(dev, 0x0200, 0x00); + status = ad9361_reg_write(dev, 0x0201, 0x00); + status = ad9361_reg_write(dev, 0x0202, 0x00); + status = ad9361_reg_write(dev, 0x0203, 0x24); + status = ad9361_reg_write(dev, 0x0204, 0x24); + status = ad9361_reg_write(dev, 0x0205, 0x00); + status = ad9361_reg_write(dev, 0x0206, 0x00); + status = ad9361_reg_write(dev, 0x0207, 0x67); + status = ad9361_reg_write(dev, 0x0208, 0x55); + status = ad9361_reg_write(dev, 0x0209, 0x31); + status = ad9361_reg_write(dev, 0x020A, 0x3E); + status = ad9361_reg_write(dev, 0x020B, 0x35); + status = ad9361_reg_write(dev, 0x020C, 0x41); + status = ad9361_reg_write(dev, 0x020D, 0x34); + status = ad9361_reg_write(dev, 0x020E, 0x00); + status = ad9361_reg_write(dev, 0x020F, 0x6A); + status = ad9361_reg_write(dev, 0x0210, 0x6A); + status = ad9361_reg_write(dev, 0x0211, 0x6A); + status = ad9361_reg_write(dev, 0x0212, 0x3C); + status = ad9361_reg_write(dev, 0x0213, 0x3C); + status = ad9361_reg_write(dev, 0x0214, 0x3C); + status = ad9361_reg_write(dev, 0x0215, 0x3F); + status = ad9361_reg_write(dev, 0x0216, 0x3F); + status = ad9361_reg_write(dev, 0x0217, 0x3F); + status = ad9361_reg_write(dev, 0x0218, 0x2E); + status = ad9361_reg_write(dev, 0x0219, 0x9C); + status = ad9361_reg_write(dev, 0x021A, 0x1F); + status = ad9361_reg_write(dev, 0x021B, 0x15); + status = ad9361_reg_write(dev, 0x021C, 0x9C); + status = ad9361_reg_write(dev, 0x021D, 0x1F); + status = ad9361_reg_write(dev, 0x021E, 0x15); + status = ad9361_reg_write(dev, 0x021F, 0x9C); + status = ad9361_reg_write(dev, 0x0220, 0x1F); + status = ad9361_reg_write(dev, 0x0221, 0x2A); + status = ad9361_reg_write(dev, 0x0222, 0x2A); + status = ad9361_reg_write(dev, 0x0223, 0x40); + status = ad9361_reg_write(dev, 0x0224, 0x40); + status = ad9361_reg_write(dev, 0x0225, 0x2C); + status = ad9361_reg_write(dev, 0x0226, 0x00); + status = ad9361_reg_write(dev, 0x0227, 0x00); + //************************************************************ + // Setup and Run BB DC and RF DC Offset Calibrations + //************************************************************ + status = ad9361_reg_write(dev, 0x0193, 0x3F); + status = ad9361_reg_write(dev, 0x0190, 0x0F); // Set BBDC tracking shift M value, only applies when BB DC tracking enabled + status = ad9361_reg_write(dev, 0x0194, 0x01); // BBDC Cal setting + status = ad9361_reg_write(dev, 0x0016, 0x01); // Start BBDC offset cal + + // BBDC Max Cal Time: 8416.667 us. Cal done when 0x016[0]==0 + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count + status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0] + status = ad9361_reg_write(dev, 0x0187, 0x24); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x018B, 0x83); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0188, 0x05); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0189, 0x30); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0016, 0x02); // Start RFDC offset cal + + // RFDC Max Cal Time: 114511.250 us + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x5F); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0x80); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase + status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit + status = ad9361_reg_write(dev, 0x0169, 0xCF); // Enable Rx Quadrature Calibration Tracking + status = ad9361_reg_write(dev, 0x018B, 0xAD); // Enable BB and RF DC Tracking Calibrations + status = ad9361_reg_write(dev, 0x0012, 0x02); // Cals done, Set PPORT Config + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD/TDD bit + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth Mode, FDD External Control bits properly + + //************************************************************ + // Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB + //************************************************************ + status = ad9361_reg_write(dev, 0x0073, 0x00); + status = ad9361_reg_write(dev, 0x0074, 0x00); + status = ad9361_reg_write(dev, 0x0075, 0x00); + status = ad9361_reg_write(dev, 0x0076, 0x00); + //************************************************************ + // Setup RSSI and Power Measurement Duration Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x0150, 0x0E); // RSSI Measurement Duration 0, 1 + status = ad9361_reg_write(dev, 0x0151, 0x00); // RSSI Measurement Duration 2, 3 + status = ad9361_reg_write(dev, 0x0152, 0xFF); // RSSI Weighted Multiplier 0 + status = ad9361_reg_write(dev, 0x0153, 0x00); // RSSI Weighted Multiplier 1 + status = ad9361_reg_write(dev, 0x0154, 0x00); // RSSI Weighted Multiplier 2 + status = ad9361_reg_write(dev, 0x0155, 0x00); // RSSI Weighted Multiplier 3 + status = ad9361_reg_write(dev, 0x0156, 0x00); // RSSI Delay + status = ad9361_reg_write(dev, 0x0157, 0x00); // RSSI Wait + status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select + status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration + + return status; + } diff --git a/df_datalink_ge/src/dev_profile/ad9361_2_reg_profile.c b/df_datalink_ge/src/dev_profile/ad9361_2_reg_profile.c new file mode 100644 index 0000000..ffc02ec --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9361_2_reg_profile.c @@ -0,0 +1,1233 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +#define TIMEOUT_TH AD9361_TIMEOUT_TH + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +// ad9361-2 +static struct spi_init_param ad9361_2_reg_spi_init = { + .device_id = AD9361_SPI_DEVICE_ID, + .max_speed_hz = AD9361_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_1, + .chip_select = AD9361_2_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9361_2_reg_gpio_resetb_init = { + .number = AD9361_2_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +struct ad9361_reg_init_param ad9361_2_reg_default_init_param = { + /* SPI */ + .spi_init = &ad9361_2_reg_spi_init, + .gpio_resetb = &ad9361_2_reg_gpio_resetb_init +}; + +uint32_t ad9361_2_reg_config(struct ad9361_reg_dev *dev){ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + + //************************************************************ + // AD9361 R2 Auto Generated Initialization Script: This script was + // generated using the AD9361 Customer software Version 2.1.3 + //************************************************************ + // Profile: Custom + // REFCLK_IN: 40.000 MHz + + + status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation + status = ad9361_reg_write(dev, 0x02A6, 0x0E); // Enable Master Bias + status = ad9361_reg_write(dev, 0x02A8, 0x0E); // Set Bandgap Trim + status = ad9361_reg_write(dev, 0x02AB, 0x07); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x02AC, 0xFF); // Set RF PLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0009, 0x17); // Enable Clocks + mdelay(20) ;// waits 20 ms + + //************************************************************ + // Set BBPLL Frequency: 1152.000000 + //************************************************************ + status = ad9361_reg_write(dev, 0x0045, 0x03); // Set BBPLL reflclk scale to REFCLK * 2 + status = ad9361_reg_write(dev, 0x0046, 0x02); // Set BBPLL Loop Filter Charge Pump current + status = ad9361_reg_write(dev, 0x0048, 0xE8); // Set BBPLL Loop Filter C1, R1 + status = ad9361_reg_write(dev, 0x0049, 0x5B); // Set BBPLL Loop Filter R2, C2, C1 + status = ad9361_reg_write(dev, 0x004A, 0x35); // Set BBPLL Loop Filter C3,R2 + status = ad9361_reg_write(dev, 0x004B, 0xE0); // Allow calibration to occur and set cal count to 1024 for max accuracy + status = ad9361_reg_write(dev, 0x004E, 0x10); // Set calibration clock to REFCLK/4 for more accuracy + status = ad9361_reg_write(dev, 0x0043, 0x00); // BBPLL Freq Word (Fractional[7:0]) + status = ad9361_reg_write(dev, 0x0042, 0xC0); // BBPLL Freq Word (Fractional[15:8]) + status = ad9361_reg_write(dev, 0x0041, 0x0C); // BBPLL Freq Word (Fractional[23:16]) + status = ad9361_reg_write(dev, 0x0044, 0x0E); // BBPLL Freq Word (Integer[7:0]) + status = ad9361_reg_write(dev, 0x003F, 0x05); // Start BBPLL Calibration + status = ad9361_reg_write(dev, 0x003F, 0x01); // Clear BBPLL start calibration bit + status = ad9361_reg_write(dev, 0x004C, 0x86); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x01); // Increase BBPLL KV and phase margin + status = ad9361_reg_write(dev, 0x004D, 0x05); // Increase BBPLL KV and phase margin + + // Wait for BBPLL to lock, Timeout 2sec, Max BBPLL VCO Cal Time: 172.800 us (Done when 0x05E[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x005E, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + + status = ad9361_reg_write(dev, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0003, 0xE4); // Setup Rx Digital Filters/ Channels + status = ad9361_reg_write(dev, 0x0004, 0x03); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) + status = ad9361_reg_write(dev, 0x000A, 0x12); // Set BBPLL post divide rate + + //************************************************************ + // Setup the Parallel Port (Digital Data Interface) + //************************************************************ + status = ad9361_reg_write(dev, 0x0010, 0x08); // I/O Config. Tx Swap IQ; Rx Swap IQ; Tx CH Swap, Rx CH Swap; Rx Frame Mode; 2R2T bit; Invert data bus; Invert DATA_CLK + status = ad9361_reg_write(dev, 0x0011, 0x00); // I/O Config. Alt Word Order; -Rx1; -Rx2; -Tx1; -Tx2; Invert Rx Frame; Delay Rx Data + status = ad9361_reg_write(dev, 0x0012, 0x02); // I/O Config. Rx=2*Tx; Swap Ports; SDR; LVDS; Half Duplex; Single Port; Full Port; Swap Bits + status = ad9361_reg_write(dev, 0x0006, 0x00); // PPORT Rx Delay (adjusts Tco Dataclk->Data) + status = ad9361_reg_write(dev, 0x0007, 0x0F); // PPORT TX Delay (adjusts setup/hold FBCLK->Data) + + //************************************************************ + // Setup AuxDAC + //************************************************************ + status = ad9361_reg_write(dev, 0x0018, 0x00); // AuxDAC1 Word[9:2] + status = ad9361_reg_write(dev, 0x0019, 0x00); // AuxDAC2 Word[9:2] + status = ad9361_reg_write(dev, 0x001A, 0x00); // AuxDAC1 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x001B, 0x00); // AuxDAC2 Config and Word[1:0] + status = ad9361_reg_write(dev, 0x0023, 0xFF); // AuxDAC Manaul/Auto Control + status = ad9361_reg_write(dev, 0x0026, 0x00); // AuxDAC Manual Select Bit/GPO Manual Select + status = ad9361_reg_write(dev, 0x0030, 0x00); // AuxDAC1 Rx Delay + status = ad9361_reg_write(dev, 0x0031, 0x00); // AuxDAC1 Tx Delay + status = ad9361_reg_write(dev, 0x0032, 0x00); // AuxDAC2 Rx Delay + status = ad9361_reg_write(dev, 0x0033, 0x00); // AuxDAC2 Tx Delay + + //************************************************************ + // Setup AuxADC + //************************************************************ + status = ad9361_reg_write(dev, 0x000B, 0x00); // Temp Sensor Setup (Offset) + status = ad9361_reg_write(dev, 0x000C, 0x00); // Temp Sensor Setup (Temp Window) + status = ad9361_reg_write(dev, 0x000D, 0x03); // Temp Sensor Setup (Periodic Measure) + status = ad9361_reg_write(dev, 0x000F, 0x04); // Temp Sensor Setup (Decimation) + status = ad9361_reg_write(dev, 0x001C, 0x00); // AuxADC Setup (Clock Div) + status = ad9361_reg_write(dev, 0x001D, 0x01); // AuxADC Setup (Decimation/Enable) + + //************************************************************ + // Setup Control Outs + //************************************************************ + status = ad9361_reg_write(dev, 0x0035, 0x00); // Ctrl Out index + status = ad9361_reg_write(dev, 0x0036, 0xFF); // Ctrl Out [7:0] output enable + + //************************************************************ + // Setup GPO + //************************************************************ + status = ad9361_reg_write(dev, 0x003A, 0x27); // Set number of REFCLK cycles for 1us delay timer + status = ad9361_reg_write(dev, 0x0020, 0x00); // GPO Auto Enable Setup in RX and TX + status = ad9361_reg_write(dev, 0x0027, 0x00); // GPO Manual and GPO auto value in ALERT + status = ad9361_reg_write(dev, 0x0028, 0x00); // GPO_0 RX Delay + status = ad9361_reg_write(dev, 0x0029, 0x00); // GPO_1 RX Delay + status = ad9361_reg_write(dev, 0x002A, 0x00); // GPO_2 RX Delay + status = ad9361_reg_write(dev, 0x002B, 0x00); // GPO_3 RX Delay + status = ad9361_reg_write(dev, 0x002C, 0x00); // GPO_0 TX Delay + status = ad9361_reg_write(dev, 0x002D, 0x00); // GPO_1 TX Delay + status = ad9361_reg_write(dev, 0x002E, 0x00); // GPO_2 TX Delay + status = ad9361_reg_write(dev, 0x002F, 0x00); // GPO_3 TX Delay + + //************************************************************ + // Setup RF PLL non-frequency-dependent registers + //************************************************************ + status = ad9361_reg_write(dev, 0x0261, 0x00); // Set Rx LO Power mode + status = ad9361_reg_write(dev, 0x02A1, 0x00); // Set Tx LO Power mode + status = ad9361_reg_write(dev, 0x0248, 0x0B); // Enable Rx VCO LDO + status = ad9361_reg_write(dev, 0x0288, 0x0B); // Enable Tx VCO LDO + status = ad9361_reg_write(dev, 0x0246, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0286, 0x02); // Set VCO Power down TCF bits + status = ad9361_reg_write(dev, 0x0249, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x0289, 0x8E); // Set VCO cal length + status = ad9361_reg_write(dev, 0x023B, 0x80); // Enable Rx VCO cal + status = ad9361_reg_write(dev, 0x027B, 0x80); // Enable Tx VCO cal + status = ad9361_reg_write(dev, 0x0243, 0x0D); // Set Rx prescaler bias + status = ad9361_reg_write(dev, 0x0283, 0x0D); // Set Tx prescaler bias + status = ad9361_reg_write(dev, 0x023D, 0x00); // Clear Half VCO cal clock setting + status = ad9361_reg_write(dev, 0x027D, 0x00); // Clear Half VCO cal clock setting + + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth mode bit + status = ad9361_reg_write(dev, 0x0014, 0x1D); // Set Force ALERT State bit + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD mode + mdelay(1); // waits 1 ms + + status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal + + // Wait for CP cal to complete, Max RXCP Cal time: 460.800 (us)(Done when 0x244[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0244, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x027D, 0x04); // Start TX CP cal + + // Wait for CP cal to complete, Max TXCP Cal time: 460.800 (us)(Done when 0x284[7]==1) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0284, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x80 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x023D, 0x00); // Disable RX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + status = ad9361_reg_write(dev, 0x027D, 0x00); // Disable TX CP Calibration since the CP Cal start bit is not self-clearing. Only important if the script is run again without restting the DUT + //************************************************************ + // FDD RX,TX Synth Frequency: 1500.000000,1500.000000 MHz + //************************************************************ + //************************************************************ + // Setup Rx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x023A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0239, 0xC3); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0242, 0x1F); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0238, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0245, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0251, 0x0C); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0250, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x023B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x023E, 0xD4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x023F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0240, 0x09); // Set Synth Loop Filter R3 + + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC3); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x1F); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0C); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xD4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x09); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Rx and Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0233, 0x00); // Write Rx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0234, 0x00); // Write Rx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0235, 0x00); // Write Rx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0232, 0x00); // Write Rx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0231, 0x4B); // Write Rx Synth Integer Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0005, 0x11); // Set LO divider setting + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0x4B); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x11); // Set LO divider setting + + //************************************************************ + // Program Mixer GM Sub-table + //************************************************************ + status = ad9361_reg_write(dev, 0x013F, 0x02); // Start Clock + status = ad9361_reg_write(dev, 0x0138, 0x0F); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x78); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x00); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0E); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x74); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x0D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0D); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x70); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x15); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0C); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x6C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x1B); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0B); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x68); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x21); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x0A); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x64); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x25); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x09); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x60); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x29); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x08); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x5C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2C); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x07); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x58); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x2F); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x06); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x54); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x31); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x05); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x50); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x33); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x04); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x4C); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x34); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x03); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x48); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x35); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x02); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x30); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3A); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x01); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x18); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3D); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x0138, 0x00); // Addr Table Index + status = ad9361_reg_write(dev, 0x0139, 0x00); // Gain + status = ad9361_reg_write(dev, 0x013A, 0x00); // Bias + status = ad9361_reg_write(dev, 0x013B, 0x3E); // GM + status = ad9361_reg_write(dev, 0x013F, 0x06); // Write Words + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x02); // Clear Write Bit + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay for 3 ADCCLK/16 clock cycles (Dummy Write) + status = ad9361_reg_write(dev, 0x013C, 0x00); // Delay ~1us (Dummy Write) + status = ad9361_reg_write(dev, 0x013F, 0x00); // Stop Clock + + //************************************************************ + // Program Rx Gain Tables with GainTable800MHz.csv + //************************************************************ + + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Start Gain Table Clock + status = ad9361_reg_write(dev, 0x0130, 0x00); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x01); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x02); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x03); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x01); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x04); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x02); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x05); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x06); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x07); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x08); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x03); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x09); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x04); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x05); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x06); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x07); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x08); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x0F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x10); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x11); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x12); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x13); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x01); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x14); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x09); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x15); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x16); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x17); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x18); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x19); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x0F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x10); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x02); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x1F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x20); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x21); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x04); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x22); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x23); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x24); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x24); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x20); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x25); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x21); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x26); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x22); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x27); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x23); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x28); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x24); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x29); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x25); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x26); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x27); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x28); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x29); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2A); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x2F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2B); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x30); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2C); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x31); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2D); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x32); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x33); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x34); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x35); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x36); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x44); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x37); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2E); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x38); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x2F); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x39); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x30); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x31); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x32); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x33); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x34); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x35); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x3F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x36); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x40); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x37); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x41); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x64); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x42); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x65); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x43); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x66); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x44); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x67); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x45); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x68); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x46); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x69); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x47); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6A); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x48); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6B); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x49); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6C); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6D); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4B); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6E); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4C); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x6F); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x38); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x20); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4D); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4E); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x4F); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x50); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x51); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x52); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x53); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x54); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x55); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x56); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x57); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x58); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x59); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0130, 0x5A); // Gain Table Index + status = ad9361_reg_write(dev, 0x0131, 0x00); // Ext LNA, Int LNA, & Mixer Gain Word + status = ad9361_reg_write(dev, 0x0132, 0x00); // TIA & LPF Word + status = ad9361_reg_write(dev, 0x0133, 0x00); // DC Cal bit & Dig Gain Word + status = ad9361_reg_write(dev, 0x0137, 0x1E); // Write Words + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay 3 ADCCLK/16 cycles + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x1A); // Clear Write Bit + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0134, 0x00); // Dummy Write to delay ~1us + status = ad9361_reg_write(dev, 0x0137, 0x00); // Stop Gain Table Clock + //************************************************************ + // Setup Rx Manual Gain Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x00FA, 0xE0); // Gain Control Mode Select + status = ad9361_reg_write(dev, 0x00FB, 0x08); // Table, Digital Gain, Man Gain Ctrl + status = ad9361_reg_write(dev, 0x00FC, 0x23); // Incr Step Size, ADC Overrange Size + status = ad9361_reg_write(dev, 0x00FD, 0x4C); // Max Full/LMT Gain Table Index + status = ad9361_reg_write(dev, 0x00FE, 0x44); // Decr Step Size, Peak Overload Time + status = ad9361_reg_write(dev, 0x0100, 0x6F); // Max Digital Gain + status = ad9361_reg_write(dev, 0x0104, 0x2F); // ADC Small Overload Threshold + status = ad9361_reg_write(dev, 0x0105, 0x3A); // ADC Large Overload Threshold + status = ad9361_reg_write(dev, 0x0107, 0x2B); // Small LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0108, 0x31); // Large LMT Overload Threshold + status = ad9361_reg_write(dev, 0x0109, 0x00); // Rx1 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010A, 0x58); // Rx1 LPF Gain Index + status = ad9361_reg_write(dev, 0x010B, 0x00); // Rx1 Digital Gain Index + status = ad9361_reg_write(dev, 0x010C, 0x00); // Rx2 Full/LMT Gain Index + status = ad9361_reg_write(dev, 0x010D, 0x18); // Rx2 LPF Gain Index + status = ad9361_reg_write(dev, 0x010E, 0x00); // Rx2 Digital Gain Index + status = ad9361_reg_write(dev, 0x0114, 0x30); // Low Power Threshold + status = ad9361_reg_write(dev, 0x011A, 0x27); // Initial LMT Gain Limit + status = ad9361_reg_write(dev, 0x0081, 0x00); // Tx Symbol Gain Control + //************************************************************ + // RX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter + // Corner @ 28.000000 MHz) + //************************************************************ + status = ad9361_reg_write(dev, 0x01FB, 0x14); // RX Freq Corner (MHz) + status = ad9361_reg_write(dev, 0x01FC, 0x00); // RX Freq Corner (Khz) + status = ad9361_reg_write(dev, 0x01F8, 0x05); // Rx BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x01F9, 0x1E); // RX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x01D5, 0x3F); // Set Rx Mix LO CM + status = ad9361_reg_write(dev, 0x01C0, 0x03); // Set GM common mode + status = ad9361_reg_write(dev, 0x01E2, 0x02); // Enable Rx1 Filter Tuner + status = ad9361_reg_write(dev, 0x01E3, 0x02); // Enable Rx2 Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x80); // Start RX Filter Tune + + // Wait for RX filter to tune, Max Cal Time: 2.648 us (Done when 0x016[7]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x80) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x01E2, 0x03); // Disable Rx Filter Tuner (Rx1) + status = ad9361_reg_write(dev, 0x01E3, 0x03); // Disable Rx Filter Tuner (Rx2) + //************************************************************ + // TX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter + // Corner @ 32.000000 MHz) + //************************************************************ + status = ad9361_reg_write(dev, 0x00D6, 0x04); // TX BBF Tune Divider[7:0] + status = ad9361_reg_write(dev, 0x00D7, 0x1E); // TX BBF Tune Divider[8] + + status = ad9361_reg_write(dev, 0x00CA, 0x22); // Enable Tx Filter Tuner + status = ad9361_reg_write(dev, 0x0016, 0x40); // Start Tx Filter Tune + + // Wait for TX filter to tune, Max Cal Time: 1.233 us (Done when 0x016[6]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x40) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x00CA, 0x26); // Disable Tx Filter Tuner (Both Channels) + //************************************************************ + // RX TIA Setup: Setup values scale based on RxBBF calibration + // results. See information in Calibration Guide. + //************************************************************ + status = ad9361_reg_write(dev, 0x01DB, 0x20); // Set TIA selcc[2:0] + status = ad9361_reg_write(dev, 0x01DD, 0x00); // Set RX TIA1 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DF, 0x00); // Set RX TIA2 C MSB[6:0] + status = ad9361_reg_write(dev, 0x01DC, 0x47); // Set RX TIA1 C LSB[5:0] + status = ad9361_reg_write(dev, 0x01DE, 0x47); // Set RX TIA2 C LSB[5:0] + + //************************************************************ + // TX Secondary Filter Calibration Setup: Real Bandwidth + // 20.000000MHz, 3dB Corner @ 100.000000MHz + //************************************************************ + status = ad9361_reg_write(dev, 0x00D2, 0x04); // TX Secondary Filter PDF Cap cal[5:0] + status = ad9361_reg_write(dev, 0x00D1, 0x0C); // TX Secondary Filter PDF Res cal[3:0] + status = ad9361_reg_write(dev, 0x00D0, 0x57); // Pdampbias + + //************************************************************ + // ADC Setup: Tune ADC Performance based on RX analog filter tune + // corner. Real Bandwidth: 18.155158 MHz, ADC Clock Frequency: + // 288.000000 MHz. The values in registers 0x200 - 0x227 need to be + // calculated using the equations in the Calibration Guide. + //************************************************************ + + status = ad9361_reg_write(dev, 0x0200, 0x00); + status = ad9361_reg_write(dev, 0x0201, 0x00); + status = ad9361_reg_write(dev, 0x0202, 0x00); + status = ad9361_reg_write(dev, 0x0203, 0x24); + status = ad9361_reg_write(dev, 0x0204, 0x24); + status = ad9361_reg_write(dev, 0x0205, 0x00); + status = ad9361_reg_write(dev, 0x0206, 0x00); + status = ad9361_reg_write(dev, 0x0207, 0x67); + status = ad9361_reg_write(dev, 0x0208, 0x55); + status = ad9361_reg_write(dev, 0x0209, 0x31); + status = ad9361_reg_write(dev, 0x020A, 0x3E); + status = ad9361_reg_write(dev, 0x020B, 0x35); + status = ad9361_reg_write(dev, 0x020C, 0x41); + status = ad9361_reg_write(dev, 0x020D, 0x34); + status = ad9361_reg_write(dev, 0x020E, 0x00); + status = ad9361_reg_write(dev, 0x020F, 0x6A); + status = ad9361_reg_write(dev, 0x0210, 0x6A); + status = ad9361_reg_write(dev, 0x0211, 0x6A); + status = ad9361_reg_write(dev, 0x0212, 0x3C); + status = ad9361_reg_write(dev, 0x0213, 0x3C); + status = ad9361_reg_write(dev, 0x0214, 0x3C); + status = ad9361_reg_write(dev, 0x0215, 0x3F); + status = ad9361_reg_write(dev, 0x0216, 0x3F); + status = ad9361_reg_write(dev, 0x0217, 0x3F); + status = ad9361_reg_write(dev, 0x0218, 0x2E); + status = ad9361_reg_write(dev, 0x0219, 0x9C); + status = ad9361_reg_write(dev, 0x021A, 0x1F); + status = ad9361_reg_write(dev, 0x021B, 0x15); + status = ad9361_reg_write(dev, 0x021C, 0x9C); + status = ad9361_reg_write(dev, 0x021D, 0x1F); + status = ad9361_reg_write(dev, 0x021E, 0x15); + status = ad9361_reg_write(dev, 0x021F, 0x9C); + status = ad9361_reg_write(dev, 0x0220, 0x1F); + status = ad9361_reg_write(dev, 0x0221, 0x2A); + status = ad9361_reg_write(dev, 0x0222, 0x2A); + status = ad9361_reg_write(dev, 0x0223, 0x40); + status = ad9361_reg_write(dev, 0x0224, 0x40); + status = ad9361_reg_write(dev, 0x0225, 0x2C); + status = ad9361_reg_write(dev, 0x0226, 0x00); + status = ad9361_reg_write(dev, 0x0227, 0x00); + //************************************************************ + // Setup and Run BB DC and RF DC Offset Calibrations + //************************************************************ + status = ad9361_reg_write(dev, 0x0193, 0x3F); + status = ad9361_reg_write(dev, 0x0190, 0x0F); // Set BBDC tracking shift M value, only applies when BB DC tracking enabled + status = ad9361_reg_write(dev, 0x0194, 0x01); // BBDC Cal setting + status = ad9361_reg_write(dev, 0x0016, 0x01); // Start BBDC offset cal + + // BBDC Max Cal Time: 8416.667 us. Cal done when 0x016[0]==0 + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x0185, 0x20); // Set RF DC offset Wait Count + status = ad9361_reg_write(dev, 0x0186, 0x32); // Set RF DC Offset Count[7:0] + status = ad9361_reg_write(dev, 0x0187, 0x24); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x018B, 0x83); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0188, 0x05); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0189, 0x30); // Settings for RF DC cal + status = ad9361_reg_write(dev, 0x0016, 0x02); // Start RFDC offset cal + + // RFDC Max Cal Time: 114511.250 us + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x5F); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0x80); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do{ + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1);// Wait 1ms + time_out_cnt++; + } while((value & 0x10) != 0x00 && time_out_cnt <= TIMEOUT_TH); + + status = ad9361_reg_write(dev, 0x016A, 0x75); // Set Kexp Phase + status = ad9361_reg_write(dev, 0x016B, 0x95); // Set Kexp Amplitude & Prevent Positive Gain Bit + status = ad9361_reg_write(dev, 0x0169, 0xCF); // Enable Rx Quadrature Calibration Tracking + status = ad9361_reg_write(dev, 0x018B, 0xAD); // Enable BB and RF DC Tracking Calibrations + status = ad9361_reg_write(dev, 0x0012, 0x02); // Cals done, Set PPORT Config + status = ad9361_reg_write(dev, 0x0013, 0x01); // Set ENSM FDD/TDD bit + status = ad9361_reg_write(dev, 0x0015, 0x0C); // Set Dual Synth Mode, FDD External Control bits properly + + //************************************************************ + // Set Tx Attenuation: Tx1: 0.00 dB, Tx2: 0.00 dB + //************************************************************ + status = ad9361_reg_write(dev, 0x0073, 0x00); + status = ad9361_reg_write(dev, 0x0074, 0x00); + status = ad9361_reg_write(dev, 0x0075, 0x00); + status = ad9361_reg_write(dev, 0x0076, 0x00); + //************************************************************ + // Setup RSSI and Power Measurement Duration Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x0150, 0x0E); // RSSI Measurement Duration 0, 1 + status = ad9361_reg_write(dev, 0x0151, 0x00); // RSSI Measurement Duration 2, 3 + status = ad9361_reg_write(dev, 0x0152, 0xFF); // RSSI Weighted Multiplier 0 + status = ad9361_reg_write(dev, 0x0153, 0x00); // RSSI Weighted Multiplier 1 + status = ad9361_reg_write(dev, 0x0154, 0x00); // RSSI Weighted Multiplier 2 + status = ad9361_reg_write(dev, 0x0155, 0x00); // RSSI Weighted Multiplier 3 + status = ad9361_reg_write(dev, 0x0156, 0x00); // RSSI Delay + status = ad9361_reg_write(dev, 0x0157, 0x00); // RSSI Wait + status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select + status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration + + return status; + } diff --git a/df_datalink_ge/src/dev_profile/ad9361_profile.c b/df_datalink_ge/src/dev_profile/ad9361_profile.c new file mode 100644 index 0000000..bbc889e --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9361_profile.c @@ -0,0 +1,340 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9361_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9361_SPI_ENGINE_BASEADDR, + .cs_delay = AD9361_SPI_ENGINE_CS_DELAY, + .data_width = AD9361_SPI_ENGINE_DATA_WIDTH +}; + +struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9361_GPIO_DEVICE_ID +}; + +AD9361_InitParam ad9361_default_init_param = { + /* Device selection */ + ID_AD9361, // dev_sel + /* Reference Clock */ + 48000000UL, //reference_clk_rate + /* Base Configuration */ + 1, //two_rx_two_tx_mode_enable *** adi,2rx-2tx-mode-enable + 1, //one_rx_one_tx_mode_use_rx_num *** adi,1rx-1tx-mode-use-rx-num + 1, //one_rx_one_tx_mode_use_tx_num *** adi,1rx-1tx-mode-use-tx-num + 1, //frequency_division_duplex_mode_enable *** adi,frequency-division-duplex-mode-enable + 0, //frequency_division_duplex_independent_mode_enable *** adi,frequency-division-duplex-independent-mode-enable + 0, //tdd_use_dual_synth_mode_enable *** adi,tdd-use-dual-synth-mode-enable + 0, //tdd_skip_vco_cal_enable *** adi,tdd-skip-vco-cal-enable + 0, //tx_fastlock_delay_ns *** adi,tx-fastlock-delay-ns + 0, //rx_fastlock_delay_ns *** adi,rx-fastlock-delay-ns + 0, //rx_fastlock_pincontrol_enable *** adi,rx-fastlock-pincontrol-enable + 0, //tx_fastlock_pincontrol_enable *** adi,tx-fastlock-pincontrol-enable + 0, //external_rx_lo_enable *** adi,external-rx-lo-enable + 0, //external_tx_lo_enable *** adi,external-tx-lo-enable + 5, //dc_offset_tracking_update_event_mask *** adi,dc-offset-tracking-update-event-mask + 6, //dc_offset_attenuation_high_range *** adi,dc-offset-attenuation-high-range + 5, //dc_offset_attenuation_low_range *** adi,dc-offset-attenuation-low-range + 0x28, //dc_offset_count_high_range *** adi,dc-offset-count-high-range + 0x32, //dc_offset_count_low_range *** adi,dc-offset-count-low-range + 0, //split_gain_table_mode_enable *** adi,split-gain-table-mode-enable + MAX_SYNTH_FREF, //trx_synthesizer_target_fref_overwrite_hz *** adi,trx-synthesizer-target-fref-overwrite-hz + 0, // qec_tracking_slow_mode_enable *** adi,qec-tracking-slow-mode-enable + /* ENSM Control */ + 0, //ensm_enable_pin_pulse_mode_enable *** adi,ensm-enable-pin-pulse-mode-enable + 0, //ensm_enable_txnrx_control_enable *** adi,ensm-enable-txnrx-control-enable + /* LO Control */ + 4125000000UL, //rx_synthesizer_frequency_hz *** adi,rx-synthesizer-frequency-hz + 4126000000UL, //tx_synthesizer_frequency_hz *** adi,tx-synthesizer-frequency-hz + 1, //tx_lo_powerdown_managed_enable *** adi,tx-lo-powerdown-managed-enable + /* Rate & BW Control */ + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// rx_path_clock_frequencies[6] *** adi,rx-path-clock-frequencies + {768000000, 192000000, 96000000, 48000000, 24000000, 24000000},// tx_path_clock_frequencies[6] *** adi,tx-path-clock-frequencies + 18000000,//rf_rx_bandwidth_hz *** adi,rf-rx-bandwidth-hz + 18000000,//rf_tx_bandwidth_hz *** adi,rf-tx-bandwidth-hz + /* RF Port Control */ + 0, //rx_rf_port_input_select *** adi,rx-rf-port-input-select + 0, //tx_rf_port_input_select *** adi,tx-rf-port-input-select + /* TX Attenuation Control */ + 10000, //tx_attenuation_mdB *** adi,tx-attenuation-mdB + 0, //update_tx_gain_in_alert_enable *** adi,update-tx-gain-in-alert-enable + /* Reference Clock Control */ + 0, //xo_disable_use_ext_refclk_enable *** adi,xo-disable-use-ext-refclk-enable + {8, 5920}, //dcxo_coarse_and_fine_tune[2] *** adi,dcxo-coarse-and-fine-tune + CLKOUT_DISABLE, //clk_output_mode_select *** adi,clk-output-mode-select + /* Gain Control */ + 2, //gc_rx1_mode *** adi,gc-rx1-mode + 2, //gc_rx2_mode *** adi,gc-rx2-mode + 58, //gc_adc_large_overload_thresh *** adi,gc-adc-large-overload-thresh + 4, //gc_adc_ovr_sample_size *** adi,gc-adc-ovr-sample-size + 47, //gc_adc_small_overload_thresh *** adi,gc-adc-small-overload-thresh + 8192, //gc_dec_pow_measurement_duration *** adi,gc-dec-pow-measurement-duration + 0, //gc_dig_gain_enable *** adi,gc-dig-gain-enable + 800, //gc_lmt_overload_high_thresh *** adi,gc-lmt-overload-high-thresh + 704, //gc_lmt_overload_low_thresh *** adi,gc-lmt-overload-low-thresh + 24, //gc_low_power_thresh *** adi,gc-low-power-thresh + 15, //gc_max_dig_gain *** adi,gc-max-dig-gain + 0, //gc_use_rx_fir_out_for_dec_pwr_meas_enable *** adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable + /* Gain MGC Control */ + 2, //mgc_dec_gain_step *** adi,mgc-dec-gain-step + 2, //mgc_inc_gain_step *** adi,mgc-inc-gain-step + 0, //mgc_rx1_ctrl_inp_enable *** adi,mgc-rx1-ctrl-inp-enable + 0, //mgc_rx2_ctrl_inp_enable *** adi,mgc-rx2-ctrl-inp-enable + 0, //mgc_split_table_ctrl_inp_gain_mode *** adi,mgc-split-table-ctrl-inp-gain-mode + /* Gain AGC Control */ + 10, //agc_adc_large_overload_exceed_counter *** adi,agc-adc-large-overload-exceed-counter + 2, //agc_adc_large_overload_inc_steps *** adi,agc-adc-large-overload-inc-steps + 0, //agc_adc_lmt_small_overload_prevent_gain_inc_enable *** adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable + 10, //agc_adc_small_overload_exceed_counter *** adi,agc-adc-small-overload-exceed-counter + 4, //agc_dig_gain_step_size *** adi,agc-dig-gain-step-size + 3, //agc_dig_saturation_exceed_counter *** adi,agc-dig-saturation-exceed-counter + 1000, // agc_gain_update_interval_us *** adi,agc-gain-update-interval-us + 0, //agc_immed_gain_change_if_large_adc_overload_enable *** adi,agc-immed-gain-change-if-large-adc-overload-enable + 0, //agc_immed_gain_change_if_large_lmt_overload_enable *** adi,agc-immed-gain-change-if-large-lmt-overload-enable + 10, //agc_inner_thresh_high *** adi,agc-inner-thresh-high + 1, //agc_inner_thresh_high_dec_steps *** adi,agc-inner-thresh-high-dec-steps + 12, //agc_inner_thresh_low *** adi,agc-inner-thresh-low + 1, //agc_inner_thresh_low_inc_steps *** adi,agc-inner-thresh-low-inc-steps + 10, //agc_lmt_overload_large_exceed_counter *** adi,agc-lmt-overload-large-exceed-counter + 2, //agc_lmt_overload_large_inc_steps *** adi,agc-lmt-overload-large-inc-steps + 10, //agc_lmt_overload_small_exceed_counter *** adi,agc-lmt-overload-small-exceed-counter + 5, //agc_outer_thresh_high *** adi,agc-outer-thresh-high + 2, //agc_outer_thresh_high_dec_steps *** adi,agc-outer-thresh-high-dec-steps + 18, //agc_outer_thresh_low *** adi,agc-outer-thresh-low + 2, //agc_outer_thresh_low_inc_steps *** adi,agc-outer-thresh-low-inc-steps + 1, //agc_attack_delay_extra_margin_us; *** adi,agc-attack-delay-extra-margin-us + 0, //agc_sync_for_gain_counter_enable *** adi,agc-sync-for-gain-counter-enable + /* Fast AGC */ + 64, //fagc_dec_pow_measuremnt_duration *** adi,fagc-dec-pow-measurement-duration + 260, //fagc_state_wait_time_ns *** adi,fagc-state-wait-time-ns + /* Fast AGC - Low Power */ + 0, //fagc_allow_agc_gain_increase *** adi,fagc-allow-agc-gain-increase-enable + 5, //fagc_lp_thresh_increment_time *** adi,fagc-lp-thresh-increment-time + 1, //fagc_lp_thresh_increment_steps *** adi,fagc-lp-thresh-increment-steps + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + 1, //fagc_lock_level_lmt_gain_increase_en *** adi,fagc-lock-level-lmt-gain-increase-enable + 5, //fagc_lock_level_gain_increase_upper_limit *** adi,fagc-lock-level-gain-increase-upper-limit + /* Fast AGC - Peak Detectors and Final Settling */ + 1, //fagc_lpf_final_settling_steps *** adi,fagc-lpf-final-settling-steps + 1, //fagc_lmt_final_settling_steps *** adi,fagc-lmt-final-settling-steps + 3, //fagc_final_overrange_count *** adi,fagc-final-overrange-count + /* Fast AGC - Final Power Test */ + 0, //fagc_gain_increase_after_gain_lock_en *** adi,fagc-gain-increase-after-gain-lock-enable + /* Fast AGC - Unlocking the Gain */ + 0, //fagc_gain_index_type_after_exit_rx_mode *** adi,fagc-gain-index-type-after-exit-rx-mode + 1, //fagc_use_last_lock_level_for_set_gain_en *** adi,fagc-use-last-lock-level-for-set-gain-enable + 1, //fagc_rst_gla_stronger_sig_thresh_exceeded_en *** adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable + 5, //fagc_optimized_gain_offset *** adi,fagc-optimized-gain-offset + 10, //fagc_rst_gla_stronger_sig_thresh_above_ll *** adi,fagc-rst-gla-stronger-sig-thresh-above-ll + 1, //fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en *** adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable + 1, //fagc_rst_gla_engergy_lost_goto_optim_gain_en *** adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable + 10, //fagc_rst_gla_engergy_lost_sig_thresh_below_ll *** adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll + 8, //fagc_energy_lost_stronger_sig_gain_lock_exit_cnt *** adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt + 1, //fagc_rst_gla_large_adc_overload_en *** adi,fagc-rst-gla-large-adc-overload-enable + 1, //fagc_rst_gla_large_lmt_overload_en *** adi,fagc-rst-gla-large-lmt-overload-enable + 0, //fagc_rst_gla_en_agc_pulled_high_en *** adi,fagc-rst-gla-en-agc-pulled-high-enable + 0, //fagc_rst_gla_if_en_agc_pulled_high_mode *** adi,fagc-rst-gla-if-en-agc-pulled-high-mode + 64, //fagc_power_measurement_duration_in_state5 *** adi,fagc-power-measurement-duration-in-state5 + 2, //fagc_large_overload_inc_steps *** adi,fagc-adc-large-overload-inc-steps + /* RSSI Control */ + 1, //rssi_delay *** adi,rssi-delay + 1000, //rssi_duration *** adi,rssi-duration + 3, //rssi_restart_mode *** adi,rssi-restart-mode + 0, //rssi_unit_is_rx_samples_enable *** adi,rssi-unit-is-rx-samples-enable + 1, //rssi_wait *** adi,rssi-wait + /* Aux ADC Control */ + 256, //aux_adc_decimation *** adi,aux-adc-decimation + 48000000UL, //aux_adc_rate *** adi,aux-adc-rate + /* AuxDAC Control */ + 1, //aux_dac_manual_mode_enable *** adi,aux-dac-manual-mode-enable + 0, //aux_dac1_default_value_mV *** adi,aux-dac1-default-value-mV + 0, //aux_dac1_active_in_rx_enable *** adi,aux-dac1-active-in-rx-enable + 0, //aux_dac1_active_in_tx_enable *** adi,aux-dac1-active-in-tx-enable + 0, //aux_dac1_active_in_alert_enable *** adi,aux-dac1-active-in-alert-enable + 0, //aux_dac1_rx_delay_us *** adi,aux-dac1-rx-delay-us + 0, //aux_dac1_tx_delay_us *** adi,aux-dac1-tx-delay-us + 0, //aux_dac2_default_value_mV *** adi,aux-dac2-default-value-mV + 0, //aux_dac2_active_in_rx_enable *** adi,aux-dac2-active-in-rx-enable + 0, //aux_dac2_active_in_tx_enable *** adi,aux-dac2-active-in-tx-enable + 0, //aux_dac2_active_in_alert_enable *** adi,aux-dac2-active-in-alert-enable + 0, //aux_dac2_rx_delay_us *** adi,aux-dac2-rx-delay-us + 0, //aux_dac2_tx_delay_us *** adi,aux-dac2-tx-delay-us + /* Temperature Sensor Control */ + 256, //temp_sense_decimation *** adi,temp-sense-decimation + 1000, //temp_sense_measurement_interval_ms *** adi,temp-sense-measurement-interval-ms + 0xCE, //temp_sense_offset_signed *** adi,temp-sense-offset-signed + 1, //temp_sense_periodic_measurement_enable *** adi,temp-sense-periodic-measurement-enable + /* Control Out Setup */ + 0xFF, //ctrl_outs_enable_mask *** adi,ctrl-outs-enable-mask + 0, //ctrl_outs_index *** adi,ctrl-outs-index + /* External LNA Control */ + 0, //elna_settling_delay_ns *** adi,elna-settling-delay-ns + 0, //elna_gain_mdB *** adi,elna-gain-mdB + 0, //elna_bypass_loss_mdB *** adi,elna-bypass-loss-mdB + 0, //elna_rx1_gpo0_control_enable *** adi,elna-rx1-gpo0-control-enable + 0, //elna_rx2_gpo1_control_enable *** adi,elna-rx2-gpo1-control-enable + 0, //elna_gaintable_all_index_enable *** adi,elna-gaintable-all-index-enable + /* Digital Interface Control */ + 0, //digital_interface_tune_skip_mode *** adi,digital-interface-tune-skip-mode + 0, //digital_interface_tune_fir_disable *** adi,digital-interface-tune-fir-disable + 1, //pp_tx_swap_enable *** adi,pp-tx-swap-enable + 1, //pp_rx_swap_enable *** adi,pp-rx-swap-enable + 0, //tx_channel_swap_enable *** adi,tx-channel-swap-enable + 0, //rx_channel_swap_enable *** adi,rx-channel-swap-enable + 1, //rx_frame_pulse_mode_enable *** adi,rx-frame-pulse-mode-enable + 0, //two_t_two_r_timing_enable *** adi,2t2r-timing-enable + 0, //invert_data_bus_enable *** adi,invert-data-bus-enable + 0, //invert_data_clk_enable *** adi,invert-data-clk-enable + 0, //fdd_alt_word_order_enable *** adi,fdd-alt-word-order-enable + 0, //invert_rx_frame_enable *** adi,invert-rx-frame-enable + 0, //fdd_rx_rate_2tx_enable *** adi,fdd-rx-rate-2tx-enable + 0, //swap_ports_enable *** adi,swap-ports-enable + 0, //single_data_rate_enable *** adi,single-data-rate-enable + 1, //lvds_mode_enable *** adi,lvds-mode-enable + 0, //half_duplex_mode_enable *** adi,half-duplex-mode-enable + 0, //single_port_mode_enable *** adi,single-port-mode-enable + 0, //full_port_enable *** adi,full-port-enable + 0, //full_duplex_swap_bits_enable *** adi,full-duplex-swap-bits-enable + 0, //delay_rx_data *** adi,delay-rx-data + 0, //rx_data_clock_delay *** adi,rx-data-clock-delay + 4, //rx_data_delay *** adi,rx-data-delay + 7, //tx_fb_clock_delay *** adi,tx-fb-clock-delay + 0, //tx_data_delay *** adi,tx-data-delay + 150, //lvds_bias_mV *** adi,lvds-bias-mV + 1, //lvds_rx_onchip_termination_enable *** adi,lvds-rx-onchip-termination-enable + 0, //rx1rx2_phase_inversion_en *** adi,rx1-rx2-phase-inversion-enable + 0xFF, //lvds_invert1_control *** adi,lvds-invert1-control + 0x0F, //lvds_invert2_control *** adi,lvds-invert2-control + /* GPO Control */ + 0, //gpo_manual_mode_enable *** adi,gpo-manual-mode-enable + 0, //gpo_manual_mode_enable_mask *** adi,gpo-manual-mode-enable-mask + 0, //gpo0_inactive_state_high_enable *** adi,gpo0-inactive-state-high-enable + 0, //gpo1_inactive_state_high_enable *** adi,gpo1-inactive-state-high-enable + 0, //gpo2_inactive_state_high_enable *** adi,gpo2-inactive-state-high-enable + 0, //gpo3_inactive_state_high_enable *** adi,gpo3-inactive-state-high-enable + 0, //gpo0_slave_rx_enable *** adi,gpo0-slave-rx-enable + 0, //gpo0_slave_tx_enable *** adi,gpo0-slave-tx-enable + 0, //gpo1_slave_rx_enable *** adi,gpo1-slave-rx-enable + 0, //gpo1_slave_tx_enable *** adi,gpo1-slave-tx-enable + 0, //gpo2_slave_rx_enable *** adi,gpo2-slave-rx-enable + 0, //gpo2_slave_tx_enable *** adi,gpo2-slave-tx-enable + 0, //gpo3_slave_rx_enable *** adi,gpo3-slave-rx-enable + 0, //gpo3_slave_tx_enable *** adi,gpo3-slave-tx-enable + 0, //gpo0_rx_delay_us *** adi,gpo0-rx-delay-us + 0, //gpo0_tx_delay_us *** adi,gpo0-tx-delay-us + 0, //gpo1_rx_delay_us *** adi,gpo1-rx-delay-us + 0, //gpo1_tx_delay_us *** adi,gpo1-tx-delay-us + 0, //gpo2_rx_delay_us *** adi,gpo2-rx-delay-us + 0, //gpo2_tx_delay_us *** adi,gpo2-tx-delay-us + 0, //gpo3_rx_delay_us *** adi,gpo3-rx-delay-us + 0, //gpo3_tx_delay_us *** adi,gpo3-tx-delay-us + /* Tx Monitor Control */ + 37000, //low_high_gain_threshold_mdB *** adi,txmon-low-high-thresh + 0, //low_gain_dB *** adi,txmon-low-gain + 24, //high_gain_dB *** adi,txmon-high-gain + 0, //tx_mon_track_en *** adi,txmon-dc-tracking-enable + 0, //one_shot_mode_en *** adi,txmon-one-shot-mode-enable + 511, //tx_mon_delay *** adi,txmon-delay + 8192, //tx_mon_duration *** adi,txmon-duration + 2, //tx1_mon_front_end_gain *** adi,txmon-1-front-end-gain + 2, //tx2_mon_front_end_gain *** adi,txmon-2-front-end-gain + 48, //tx1_mon_lo_cm *** adi,txmon-1-lo-cm + 48, //tx2_mon_lo_cm *** adi,txmon-2-lo-cm + /* GPIO definitions */ + /* Reset_b */ + { + .number = AD9361_1_RESET_B, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_resetb *** reset-gpios + /* MCS Sync */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_sync *** sync-gpios + /* Cal-SW1 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw1 *** cal-sw1-gpios + /* Cal-SW2 */ + { + .number = -1, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param + }, //gpio_cal_sw2 *** cal-sw2-gpios + + { + .device_id = AD9361_SPI_DEVICE_ID, + .mode = SPI_MODE_1, + .chip_select = AD9361_1_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param + }, + + /* External LO clocks */ + NULL, //(*ad9361_rfpll_ext_recalc_rate)() + NULL, //(*ad9361_rfpll_ext_round_rate)() + NULL, //(*ad9361_rfpll_ext_set_rate)() +}; + +AD9361_RXFIRConfig rx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // rx + 0, // rx_gain + 1, // rx_dec + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // rx_coef[128] + 64, // rx_coef_size + {0, 0, 0, 0, 0, 0}, //rx_path_clks[6] + 0 // rx_bandwidth +}; + +AD9361_TXFIRConfig tx_fir_config = { // BPF PASSBAND 3/20 fs to 1/4 fs + 3, // tx + -6, // tx_gain + 1, // tx_int + { + -4, -6, -37, 35, 186, 86, -284, -315, + 107, 219, -4, 271, 558, -307, -1182, -356, + 658, 157, 207, 1648, 790, -2525, -2553, 748, + 865, -476, 3737, 6560, -3583, -14731, -5278, 14819, + 14819, -5278, -14731, -3583, 6560, 3737, -476, 865, + 748, -2553, -2525, 790, 1648, 207, 157, 658, + -356, -1182, -307, 558, 271, -4, 219, 107, + -315, -284, 86, 186, 35, -37, -6, -4, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 + }, // tx_coef[128] + 64, // tx_coef_size + {0, 0, 0, 0, 0, 0}, // tx_path_clks[6] + 0 // tx_bandwidth +}; + diff --git a/df_datalink_ge/src/dev_profile/ad9528_profile.c b/df_datalink_ge/src/dev_profile/ad9528_profile.c new file mode 100644 index 0000000..adf8693 --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9528_profile.c @@ -0,0 +1,134 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_gpio.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/frequency/ad9528/ad9528.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9528_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9528_SPI_ENGINE_BASEADDR, + .cs_delay = AD9528_SPI_ENGINE_CS_DELAY, + .data_width = AD9528_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9528_GPIO_DEVICE_ID +}; + +static struct spi_init_param ad9528_spi_init = { + .device_id = AD9528_SPI_DEVICE_ID, + .max_speed_hz = AD9528_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = AD9528_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9528_gpio_resetb_init = { + .number = AD9528_RESETB, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static struct gpio_init_param ad9528_gpio_sysref_req_init = { + .number = AD9528_SYSREF_REQ, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +static ad9528pll1Settings_t clockPll1Settings = { + .refA_Frequency_Hz = 50000000, + .refA_Divider = 1, + .refA_bufferCtrl = SINGLE_ENDED, + .refB_Frequency_Hz = 0, + .refB_Divider = 1, + .refB_bufferCtrl = DISABLED, + .vcxo_Frequency_Hz = 50000000, + .vcxoBufferCtrl = SINGLE_ENDED, + .nDivider = 1 +}; + +static ad9528pll2Settings_t clockPll2Settings = { + .rfDivider = 4, + .n2Divider = 20, + .totalNdiv = 80 +}; + +/******************************************************************* + * Output Distribution Settings + * 9369CE02A uses the following clock outputs + * OUT 1: FPGA REFCLK + * OUT 3: FPGA SYSREF + * OUT 12: DUT SYSREF + * OUT 13: DUT REFCLK + ******************************************************************* + */ +static ad9528outputSettings_t clockOutputSettings = { + .outPowerDown = 0xE001, + .outSource = { + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, + AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV, AD9528_CHANNEL_DIV + }, + .outBufferCtrl = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outAnalogDelay = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outDigitalDelay = { + 0,0,0,0,0, + 0,0,0,0,0, + 0,0,0,0 + }, + .outChannelDiv = { + 5,25,25,5,5, + 5,5,5,5,5, + 5,5,10,5 + }, + .outFrequency_Hz = { + 200e6, 40e6, 40e6, 200e6, 200e6, + 200e6, 200e6, 200e6, 200e6, 200e6, + 200e6, 200e6, 100e6, 200e6 + } +}; + +static ad9528sysrefSettings_t clockSysrefSettings = { + .sysrefRequestMethod = PIN, + .sysrefSource = INTERNAL, + .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, + .sysrefPinBufferMode = DISABLED, + .sysrefPatternMode = CONTINUOUS, + .sysrefNshotMode = FOUR_PULSES, + .sysrefDivide = 256 +}; + +static ad9528spiSettings_t clockSpiSettings = { + .chipSelectIndex = AD9528_SPI_CS, //chip select Index, not used + .writeBitPolarity = 0, //Write bit polarity + .longInstructionWord = 1, //16bit instruction word + .MSBFirst = 1, //MSB first + .CPHA = 0, //Clock phase + .CPOL = 0, //Clock polarity + .enSpiStreaming = 0, //uint8_t enSpiStreaming; + .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; + .fourWireMode = 1 //uint8_t fourWireMode; +}; + +ad9528Init_t ad9528_default_init_param = { + /* SPI */ + .spi_init = &ad9528_spi_init, + .gpio_init_resetb = &ad9528_gpio_resetb_init, + .gpio_init_sysref_req = &ad9528_gpio_sysref_req_init, + .spiSettings = &clockSpiSettings, + .pll1Settings = &clockPll1Settings, + .pll2Settings = &clockPll2Settings, + .outputSettings = &clockOutputSettings, + .sysrefSettings = &clockSysrefSettings +}; diff --git a/df_datalink_ge/src/dev_profile/ad9653_profile.c b/df_datalink_ge/src/dev_profile/ad9653_profile.c new file mode 100644 index 0000000..8f6ba89 --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9653_profile.c @@ -0,0 +1,46 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/adc/ad9653/ad9653.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR, + .cs_delay = AD9653_SPI_ENGINE_CS_DELAY, + .data_width = AD9653_SPI_ENGINE_DATA_WIDTH +}; + +static struct xil_gpio_init_param xil_gpio_param = { + .type = GPIO_PS, + .device_id = AD9653_GPIO_DEVICE_ID +}; + +static struct spi_init_param ad9653_spi_init = { + .device_id = AD9653_SPI_DEVICE_ID, + .max_speed_hz = AD9653_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = AD9653_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct gpio_init_param ad9653_gpio_resetb_init = { + .number = AD9653_POWR_DOWN, + .platform_ops = &xil_gpio_ops, + .extra = &xil_gpio_param +}; + +struct ad9653_init_param ad9653_default_init_param = { + /* SPI */ + .spi_init = &ad9653_spi_init, + .gpio_pdwn = &ad9653_gpio_resetb_init +}; + +const uint32_t ad9653_default_config_len = 36; +const struct ad9653_config ad9653_default_config[] = { + // configuration + +}; diff --git a/df_datalink_ge/src/dev_profile/ad9694_profile.c b/df_datalink_ge/src/dev_profile/ad9694_profile.c new file mode 100644 index 0000000..cf08bfa --- /dev/null +++ b/df_datalink_ge/src/dev_profile/ad9694_profile.c @@ -0,0 +1,72 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/adc/ad9694/ad9694.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9694_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9694_SPI_ENGINE_BASEADDR, + .cs_delay = AD9694_SPI_ENGINE_CS_DELAY, + .data_width = AD9694_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9694_GPIO_DEVICE_ID +//}; + +static struct spi_init_param ad9694_spi_init = { + .device_id = AD9694_SPI_DEVICE_ID, + .max_speed_hz = AD9694_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = AD9694_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct ad9694_init_param ad9694_default_init_param = { + /* SPI */ + .spi_init = &ad9694_spi_init +}; + +const uint32_t ad9694_default_config_len = 36; +const struct ad9694_config ad9694_default_config[] = { + // reset + {0x0000, 0x81}, + {0x1228, 0x4F}, // JESD204B start-up circuit reset + {0x1228, 0x0F}, // JESD204B start-up normal operation + {0x1222, 0x04}, // PLL calibration + {0x1222, 0x00}, // PLL normal operation + {0x1262, 0x08}, // PLL loss of lock control - Clear loss of lock + {0x1262, 0x00}, // PLL loss of lock control - Normal operation + + // system clock + {0x0108, 0x00}, // Clock divider = 1 -> device clock = 368.64MHz + {0x0201, 0x00}, // Chip decimation ration = 1 -> full sample rate + + // channel configuration + {0x0009, 0x03}, // ADC Pair AB & CD receive all spi command + {0x0571, 0x15}, // JESD204B map JTX Link Control 1 + {0x056E, 0x00}, // JESD204B map PLL control, lane rate 6.75~13.5Gbps, actual = 7.3728Gbps + {0x0570, 0x49}, // JESD204B map JTX quick config: L=2 M=2 F=2 + {0x058B, 0x01}, // JESD204B map JTX SCR L config: scrambler disabled, L=2 + {0x0590, 0x2F}, // JESD204B map JTX Subclass & NP config: subclass 1, N' = 16 + {0x058D, 0x1F}, // JESD204B map JTX K config: K = 32 + {0x058F, 0x2D}, // JESD204B map JTX N config: CS = 0, N = 14 + {0x0571, 0x14}, // JESD204B map JTX Link Control 1 + {0x05B0, 0x00}, // SERDOUTx0, SERDOUTx1 power on + {0x0120, 0x0A}, // SYSREF COntrol: continuous mode, captured on falling edge + + // fast detect control + {0x0040, 0x00}, // FD_B/FD_D, FD_A/FD_C function as Fast Detect B/D, A/C output + {0x0245, 0x01}, // Fine fast detect enabled + {0x0247, 0xFE}, // Channel map fast detect upper threshold LSB + {0x0248, 0x1F}, // Channel map fast detect upper threshold MSB, -> 8190 + {0x0249, 0xA4}, // Channel map fast detect lower threshold LSB + {0x024A, 0x1F}, // Channel map fast detect lower threshold MSB, -> 8100 + {0x024B, 0x80}, // Channel map fast detect dwell time LSB + {0x024C, 0x00} // Channel map fast detect dwell time MSB, -> 128 +}; diff --git a/df_datalink_ge/src/dev_profile/dev_profile.h b/df_datalink_ge/src/dev_profile/dev_profile.h index fbe5d11..777cf06 100644 --- a/df_datalink_ge/src/dev_profile/dev_profile.h +++ b/df_datalink_ge/src/dev_profile/dev_profile.h @@ -3,11 +3,55 @@ #include "irq.h" #include "error.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" +#include "../drivers/frequency/ad9528/ad9528.h" +#include "../drivers/frequency/lmk04828/lmk04828.h" +#include "../drivers/frequency/lmx2594/lmx2594.h" +#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "../drivers/rf-transceiver/ad9361/ad9361_api.h" +#include "../drivers/adc/ad9694/ad9694.h" +#include "../drivers/adc/ad9653/ad9653.h" #include "../config/app_config.h" // device parameters extern struct irq_init_param intc_init_param; -extern struct timer_init_param scutimer_init_param; -extern struct global_timer_init_param globaltimer_init_param; +extern struct timer_init_param apptimer_init_param; + +// HMC7044 +extern struct hmc7044_init_param hmc7044_default_init_param; + +// AD9528 +extern ad9528Init_t ad9528_default_init_param; + +// LMK04828 +extern struct lmk04828_init_param lmk04828_default_init_param; +extern const struct lmk04828_config lmk04828_default_config[]; +extern const uint32_t lmk04828_default_config_len; + +// LMX2594 +extern struct lmx2594_init_param lmx2594_adc_init_param; +extern struct lmx2594_init_param lmx2594_dac_init_param; +extern const struct lmx2594_config lmx2594_default_config[]; +extern const uint32_t lmx2594_default_config_len; + +// AD9361 +extern AD9361_InitParam ad9361_default_init_param; +extern AD9361_RXFIRConfig rx_fir_config; +extern AD9361_TXFIRConfig tx_fir_config; +extern struct ad9361_reg_init_param ad9361_1_reg_default_init_param; +extern struct ad9361_reg_init_param ad9361_2_reg_default_init_param; +uint32_t ad9361_1_reg_config(struct ad9361_reg_dev *dev); +uint32_t ad9361_2_reg_config(struct ad9361_reg_dev *dev); + +// AD9653 +extern struct ad9653_init_param ad9653_default_init_param; +extern const struct ad9653_config ad9653_default_config[]; +extern const uint32_t ad9653_default_config_len; + +// AD9694 +extern struct ad9694_init_param ad9694_default_init_param; +extern const struct ad9694_config ad9694_default_config[]; +extern const uint32_t ad9694_default_config_len; + #endif /* SRC_DEV_PROFILE_H_ */ diff --git a/df_datalink_ge/src/dev_profile/global_timer_profile.c b/df_datalink_ge/src/dev_profile/global_timer_profile.c deleted file mode 100644 index 78fab27..0000000 --- a/df_datalink_ge/src/dev_profile/global_timer_profile.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "dev_profile.h" -#include "global_timer.h" -#include "../config/app_config.h" - -struct global_timer_init_param globaltimer_init_param = { - .base_addr = GLOBAL_TIMER_BASEADDR, - .id = GLOBAL_TIMER_DEVICE_ID, - .freq_hz = GLOBAL_TIMER_CLK_HZ, - .load_value = 0x0000000000000000 -}; - diff --git a/df_datalink_ge/src/dev_profile/hmc7044_profile.c b/df_datalink_ge/src/dev_profile/hmc7044_profile.c new file mode 100644 index 0000000..980d646 --- /dev/null +++ b/df_datalink_ge/src/dev_profile/hmc7044_profile.c @@ -0,0 +1,132 @@ +#include "dev_profile.h" +#include "../config/app_config.h" +#include "../drivers/platform/xilinx_gpio.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/frequency/hmc7044/hmc7044.h" + + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = HMC7044_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = HMC7044_SPI_ENGINE_BASEADDR, + .cs_delay = HMC7044_SPI_ENGINE_CS_DELAY, + .data_width = HMC7044_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9361_GPIO_DEVICE_ID +//}; + +// hmc7044 spi settings +static struct spi_init_param hmc7044_spi_init_param = { + .device_id = HMC7044_SPI_DEVICE_ID, + .max_speed_hz = HMC7044_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_4, + .chip_select = HMC7044_SPI_CS_HMC7044, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +// hmc7044 channel specifications +struct hmc7044_chan_spec hmc7044_chan_spec[4] = { + /* AD9361_XTAL */ + { + .disable = 0, + .num = 3, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* FPGA_DAC_LOGIC_CLK */ + { + .disable = 0, + .num = 4, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = true, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* B_AD9361_XTAL */ + { + .disable = 0, + .num = 12, + .divider = 100, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, + /* AD9361_RX_EXT_LO */ + { + .disable = 0, + .num = 13, + .divider = 10, + .coarse_delay = 0, + .fine_delay = 0, + .high_performance_mode_dis = false, + .start_up_mode_dynamic_enable = false, + .dynamic_driver_enable = false, + .output_control0_rb4_enable = true, + .force_mute_enable = false, + .driver_mode = CML, + .driver_impedance = INTERNAL_100OHM_PER_PIN, + .out_mux_mode = CHANNEL_DIV + }, +}; + +// hmc7044 default configurations +struct hmc7044_init_param hmc7044_default_init_param = { + .spi_init = &hmc7044_spi_init_param, + .clkin_freq = {0, 100000000, 0, 0}, + .vcxo_freq = 100000000, + .pll2_freq = 2500000000, + .pll1_loop_bw = 200, + .sysref_timer_div = 1536, + .in_buf_mode = { + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE, + BUFFER_DISABLE, + BUFFER_DISABLE, + ENABLE_AC_COUPLE | ENABLE_INTERNAL_TERM | BUFFER_ENABLE + }, + .gpi_ctrl = { + GPI_DISABLE, + GPI_DISABLE, + CHIP_SLEEP_MODE, + PULSE_GEN_REQUSET + }, + .gpo_ctrl = { + PLL1_LOCK_DETECT | GPO_CMOS_MODE, + PLL2_LOCK_DETECT | GPO_CMOS_MODE, + GPO_DISABLE, + GPO_DISABLE + }, + .num_channels = 4, + .pll1_ref_prio_ctrl = 0xE4, + .sync_pin_mode = SYNC_MULTICHIP, + .high_performance_mode_clock_dist_en = false, + .pulse_gen_mode = PULSE_ONE, + .channels = hmc7044_chan_spec +}; diff --git a/df_datalink_ge/src/dev_profile/intc_profile.c b/df_datalink_ge/src/dev_profile/intc_profile.c index 47dc70a..ae8990e 100644 --- a/df_datalink_ge/src/dev_profile/intc_profile.c +++ b/df_datalink_ge/src/dev_profile/intc_profile.c @@ -2,6 +2,7 @@ #include "irq.h" #include "../config/app_config.h" #include "../drivers/platform/xilinx_irq.h" + struct xil_irq_init_param xil_intc_init_param = { .type = IRQ_PS }; diff --git a/df_datalink_ge/src/dev_profile/lmk04828_profile.c b/df_datalink_ge/src/dev_profile/lmk04828_profile.c new file mode 100644 index 0000000..24c06e7 --- /dev/null +++ b/df_datalink_ge/src/dev_profile/lmk04828_profile.c @@ -0,0 +1,182 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/frequency/lmk04828/lmk04828.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = LMK04828_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = LMK04828_SPI_ENGINE_BASEADDR, + .cs_delay = LMK04828_SPI_ENGINE_CS_DELAY, + .data_width = LMK04828_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = LMK04828_GPIO_DEVICE_ID +//}; + +static struct spi_init_param lmk04828_spi_init = { + .device_id = LMK04828_SPI_DEVICE_ID, + .max_speed_hz = LMK04828_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMK04828_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct lmk04828_init_param lmk04828_default_init_param = { + /* SPI */ + .spi_init = &lmk04828_spi_init +}; + +const uint32_t lmk04828_default_config_len = 137; +const struct lmk04828_config lmk04828_default_config[] = { + // 192MHz + {0x0000, 0x90}, // [7] reset; [4] 3-wire mode disabled + {0x0000, 0x10}, // [7] normal operation; [4] 3-wire mode disabled + {0x0002, 0x00}, // [0] normal operation + {0x0003, 0x06}, // [7-0] product device type, read only, default: 6 + {0x0004, 0xD0}, // [7-0] msb of product identifier, read only, default: 208 + {0x0005, 0x5B}, // [7-0] lsb of product identifier, read only, default: 91 + {0x0006, 0x00}, // [7-0] ic version identifier, read only, default: 32 + {0x000C, 0x51}, // [7-0] msb of vendor identifier, read only, default: 81 + {0x000D, 0x04}, // [7-0] lsb of vendor identifier, read only, default: 4 + // device clock 0 + {0x0100, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0101, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0102, 0x55}, + {0x0103, 0x01}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0104, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0105, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0106, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0107, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 2 + {0x0108, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0109, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x010A, 0x55}, + {0x010B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x010C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x010D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x010E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x010F, 0x10}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 4 + {0x0110, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0111, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0112, 0x55}, + {0x0113, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0114, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0115, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0116, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0117, 0x11}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 6 + {0x0118, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0119, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x011A, 0x55}, + {0x011B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x011C, 0x02}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x011D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x011E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x011F, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 8 + {0x0120, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0121, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0122, 0x55}, + {0x0123, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0124, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0125, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0126, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0127, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 10 + {0x0128, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0129, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x012A, 0x55}, + {0x012B, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x012C, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x012D, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x012E, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x012F, 0x51}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // device clock 12 + {0x0130, 0x10}, // [6] output drive level (ODL); [5] input drive level (IDL); [4-0] device clock (DCLK) output divider + {0x0131, 0x55}, // DCLK: [7-4] output digital delay (DDLY) high count; [3-0] DDLY low count + {0x0132, 0x55}, + {0x0133, 0x00}, // DCLK: [7-3] analog delay (ADLY) value, 25 ps per lsb; [2] ADLY input mux; [1-0] DCLK input mux + {0x0134, 0x22}, // [6] DCLK half step value; [5] SDCLK output MUX; [4-1] SDCLK DDLY; [0] SYSREF half step value + {0x0135, 0x00}, // SYSREF: [4] ADLY enable; [3:0] ADLY value, 600 ps + 150 ps per lsb + {0x0136, 0xF0}, // [7] DCLK DDLY enable; [6] DCLK glitchless half step enable; [5] DCLK glitchless ADLY enable; [4] DCLK ADLY enable; [3]: clock group enable; [2-1] SYSREF disable mode; [0]: SYSREF disable + {0x0137, 0x55}, // [7] SDCLK output polarity; [6-4] SDCLK output format; [3] DCLK output polarity; [2:0] DCLK output format + // clock distribution source + {0x0138, 0x20}, // [6-5] VCO mux; [4] OSCout mux; [3:0] OSCout format + {0x0139, 0x03}, // [2] SYSREF output mux; [1-0] SYSREF source + {0x013A, 0x0C}, // [4-0] SYSREF divider [12:8] + {0x013B, 0x00}, // [7-0] SYSREF divider [7:0] + {0x013C, 0x00}, // [4-0] SYSREF DDLY [12:8] + {0x013D, 0x08}, // [7-0] SYSREF DDLY [7:0] + {0x013E, 0x03}, // [1-0] SYSREF pulse count + {0x013F, 0x00}, // [4] pll2 mux; [3] pll1 mux; [2-1] feedback mux; [0] feedback mux enable + {0x0140, 0x0B}, // power-down control: [7] pll1; [6] vco_ldo; [5] vco; [4] OSCin; [3] individual SYSREF; [2] SYSREF; [1] SYSREF DDLY; [0] SYSREF pluse generator + {0x0141, 0x00}, // dynamic DDLY control + {0x0142, 0x00}, // dynamic DDLY step control + {0x0143, 0x10}, + {0x0144, 0xFF}, + {0x0145, 0x7F}, + {0x0146, 0x12}, + {0x0147, 0x1A}, + {0x0148, 0x03}, + {0x0149, 0x05}, + {0x014A, 0x1B}, + {0x014B, 0x16}, + {0x014C, 0x00}, + {0x014D, 0x00}, + {0x014E, 0xC0}, + {0x014F, 0x7F}, + {0x0150, 0x03}, + {0x0151, 0x02}, + {0x0152, 0x00}, + {0x0153, 0x00}, + {0x0154, 0x78}, + {0x0155, 0x00}, + {0x0156, 0x7D}, + {0x0157, 0x00}, + {0x0158, 0x96}, + {0x0159, 0x06}, + {0x015A, 0x00}, + {0x015B, 0xD4}, + {0x015C, 0x20}, + {0x015D, 0x00}, + {0x015E, 0x00}, + {0x015F, 0x3B}, + {0x0160, 0x00}, + {0x0161, 0x02}, + {0x0162, 0x44}, + {0x0163, 0x00}, + {0x0164, 0x00}, + {0x0165, 0x0C}, + {0x0171, 0xAA}, + {0x0172, 0x02}, + {0x017C, 0x15}, + {0x017D, 0x33}, + {0x0166, 0x00}, + {0x0167, 0x00}, + {0x0168, 0x19}, + {0x0169, 0x59}, + {0x016A, 0x20}, + {0x016B, 0x00}, + {0x016C, 0x00}, + {0x016D, 0x00}, + {0x016E, 0x1B}, + {0x0173, 0x00}, + {0x0182, 0x00}, + {0x0183, 0x00}, + {0x0184, 0x00}, + {0x0185, 0x00}, + {0x0188, 0x00}, + {0x0189, 0x00}, + {0x018A, 0x00}, + {0x018B, 0x00}, + {0x1FFD, 0x00}, + {0x1FFE, 0x00}, + {0x1FFF, 0x53} +}; diff --git a/df_datalink_ge/src/dev_profile/lmx2594_profile.c b/df_datalink_ge/src/dev_profile/lmx2594_profile.c new file mode 100644 index 0000000..6238ebb --- /dev/null +++ b/df_datalink_ge/src/dev_profile/lmx2594_profile.c @@ -0,0 +1,181 @@ +#include "dev_profile.h" +#include "spi.h" +#include "../config/app_config.h" +#include "../drivers/frequency/lmx2594/lmx2594.h" +#include "../drivers/axi_core/spi_engine/spi_engine.h" +#include "../drivers/platform/xilinx_gpio.h" + +static struct spi_engine_init_param spi_engine_param = { + .ref_clk_hz = AD9653_SPI_ENGINE_REF_CLK, + .type = SPI_ENGINE, + .spi_engine_baseaddr = AD9653_SPI_ENGINE_BASEADDR, + .cs_delay = AD9653_SPI_ENGINE_CS_DELAY, + .data_width = AD9653_SPI_ENGINE_DATA_WIDTH +}; + +//static struct xil_gpio_init_param xil_gpio_param = { +// .type = GPIO_PS, +// .device_id = AD9653_GPIO_DEVICE_ID +//}; + +static struct spi_init_param lmx2594_adc_spi_init = { + .device_id = LMX2594_ADC_SPI_DEVICE_ID, + .max_speed_hz = LMX2594_ADC_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMX2594_ADC_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +static struct spi_init_param lmx2594_dac_spi_init = { + .device_id = LMX2594_DAC_SPI_DEVICE_ID, + .max_speed_hz = LMX2594_DAC_SPI_ENGINE_MAX_SPEED, + .mode = SPI_MODE_0, + .chip_select = LMX2594_DAC_SPI_CS, + .platform_ops = &spi_eng_platform_ops, + .extra = &spi_engine_param +}; + +struct lmx2594_init_param lmx2594_adc_init_param = { + /* SPI */ + .spi_init = &lmx2594_adc_spi_init +}; + +struct lmx2594_init_param lmx2594_dac_init_param = { + /* SPI */ + .spi_init = &lmx2594_dac_spi_init +}; + +const uint32_t lmx2594_default_config_len = 110; +const struct lmx2594_config lmx2594_default_config[] = { + // 0 ~ 78: General configuration + // 79 ~ 106: Ramping configuration + // 107 ~ 112: Readback registers + + // Recommended Initial Power-Up Sequence + // For the most reliable programming, TI recommends this procedure:: + // 1. Apply power to device. + // 2. Program RESET = 1 to reset registers. + // 3. Program RESET = 0 to remove reset. + // 4. Program registers as shown in the register map in REVERSE order from highest to lowest. + // 5. Wait 10 ms. + // 6. Program register R0 one additional time with FCAL_EN = 1 to ensure that the VCO calibration runs from a stable state. + + // Reset + { 0, 0x0002}, + + // Remove Reset + { 0, 0x0000}, + + // Reverse order programming + {106, 0x0000}, + {105, 0x0021}, + {104, 0x0000}, + {103, 0xD555}, + {102, 0x3F97}, + {101, 0x0011}, + {100, 0x0000}, + { 99, 0x2AAB}, + { 98, 0x01A0}, + { 97, 0x0888}, + { 96, 0x0000}, + { 95, 0x0000}, // fixed + { 94, 0x0000}, // fixed + { 93, 0x0000}, // fixed + { 92, 0x0000}, // fixed + { 91, 0x0000}, // fixed + { 90, 0x0000}, // fixed + { 89, 0x0000}, // fixed + { 88, 0x0000}, // fixed + { 87, 0x0000}, // fixed + { 86, 0x5879}, + { 85, 0xEC58}, + { 84, 0x0001}, + { 83, 0x54C9}, + { 82, 0x2961}, + { 81, 0x0000}, + { 80, 0x4000}, + { 79, 0x001F}, + { 78, 0x0003}, // [8:1] VCO_CAPCTRL_STRT + { 77, 0x0000}, // fixed + { 76, 0x000C}, // fixed + { 75, 0x0800}, // [10:6] CHDIV + { 74, 0x0000}, // [11:6] JESD_DAC4_CTRL; [5:0] JESD_DAC3_CTRL + { 73, 0x003F}, // [11:6] JESD_DAC2_CTRL; [5:0] JESD_DAC1_CTRL + { 72, 0x0001}, // [10:0] SYSREF_DIV + { 71, 0x0081}, // [7:5] SYSREF_DIV_PRE; [4] SYSREF_PULSE; [3] SYSREF_EN; [2] SYSREF_REPEAT + { 70, 0xC350}, // [15:0] MASH_RST_COUNT + { 69, 0x0000}, // [15:0] MASH_RST_COUNT + { 68, 0x03E8}, // fixed + { 67, 0x0000}, // fixed + { 66, 0x01F4}, // fixed + { 65, 0x0000}, // fixed + { 64, 0x1388}, // fixed + { 63, 0x0000}, // fixed + { 62, 0x0322}, // fixed + { 61, 0x00A8}, // fixed + { 60, 0x0000}, // [15:0] LD_DLY + { 59, 0x0001}, // [0] LD_TYPE + { 58, 0x9001}, // [15] INPIN_IGNORE; [14] INPIN_HYST; [13:12] INPIN_LVL; [11:9] INPIN_FMT + { 57, 0x0020}, // fixed + { 56, 0x0000}, // fixed + { 55, 0x0000}, // fixed + { 54, 0x0000}, // fixed + { 53, 0x0000}, // fixed + { 52, 0x0820}, // fixed + { 51, 0x0080}, // fixed + { 50, 0x0000}, // fixed + { 49, 0x4180}, // fixed + { 48, 0x0300}, // fixed + { 47, 0x0300}, // fixed + { 46, 0x07FC}, // [1:0] OUTB_MUX + { 45, 0xC0DF}, // [12:11] OUTA_MUX; [10:9] OUT_ISET; [5:0] OUTB_PWR + { 44, 0x1AA3}, // [13:8] OUTA_PWR; [7] OUTB_PD; [6] OUTA_PD; [5] MASH_RESET_N; [2:0] MASH_ORDER + { 43, 0x0000}, // [15:0] PLL_NUM + { 42, 0x0000}, // [15:0] PLL_NUM + { 41, 0x0000}, // [15:0] MASH_SEE + { 40, 0x0000}, // [15:0] MASH_SEE + { 39, 0x03E8}, // [15:0] PLL_DEN + { 38, 0x0000}, // [15:0] PLL_DEN + { 37, 0x0304}, // [37] MASH_SEED_EN; [13:8] PFD_DLY_SEL + { 36, 0x0028}, // [15:0] PLL_N + { 35, 0x0004}, // fixed + { 34, 0x0000}, // [2:0] PLL_N + { 33, 0x1E21}, // fixed + { 32, 0x0393}, // fixed + { 31, 0x43EC}, // [14] SEG1_EN + { 30, 0x318C}, // fixed + { 29, 0x318C}, // fixed + { 28, 0x0488}, // fixed + { 27, 0x0002}, // fixed + { 26, 0x0DB0}, // fixed + { 25, 0x0C2B}, // fixed + { 24, 0x071A}, // fixed + { 23, 0x007C}, // fixed + { 22, 0x0001}, // fixed + { 21, 0x0401}, // fixed + { 20, 0xE048}, // [13:11] VCO_SEL. [10] VCO_SEL_FORCE + { 19, 0x27B7}, // [7:0] VCO_CAPCTRL + { 18, 0x0064}, // fixed + { 17, 0x012C}, // [8:0] VCO_DACISET_STRT + { 16, 0x0080}, // [8:0] VCO_DACISET + { 15, 0x064F}, // fixed + { 14, 0x1E70}, // [6:4] CPG + { 13, 0x4000}, // fixed + { 12, 0x5001}, // [11:0] PLL_R_PR + { 11, 0x0018}, // [11:4] PLL_R + { 10, 0x10D8}, // [11:7] MULT + { 9, 0x0604}, // [12] OSC_2X + { 8, 0x2000}, // [14] VCO_DACISET_FORCE; [11] VCO_CAPCTRL_FORCE + { 7, 0x40B2}, // [14] OUT_FORCE + { 6, 0xC802}, // fixed + { 5, 0x00C8}, // fixed + { 4, 0x0C43}, // [15:8] ACAL_CMP_DLY + { 3, 0x0642}, // fixed + { 2, 0x0500}, // fixed + { 1, 0x0809}, // [2:0] CAL_CLK_DIV + { 0, 0x2598}, // [15] RAMP_EN; [14] VCO_PHASE_SYNC; [9] OUT_MUTE; [8:7] FCAL_HPFD_ADJ; [6:5] FCAL_LPFD_ADJ; [3] FCAL_EN; [2] MUXOUT_LD_SEL; [1] RESET; [0] POWERDOWN + + // one more time + { 0, 0x2598} +}; diff --git a/df_datalink_ge/src/dev_profile/timer_profile.c b/df_datalink_ge/src/dev_profile/timer_profile.c index 343806e..1f82c10 100644 --- a/df_datalink_ge/src/dev_profile/timer_profile.c +++ b/df_datalink_ge/src/dev_profile/timer_profile.c @@ -3,15 +3,19 @@ #include "../config/app_config.h" #include "../drivers/platform/xilinx_timer.h" -struct xil_timer_init_param xil_scutimer_init_param = { +struct xil_timer_init_param xil_apptimer_init_param = { .active_tmr = 0, +#ifdef __aarch64__ + .type = TIMER_PL +#else .type = TIMER_PS +#endif }; -struct timer_init_param scutimer_init_param = { - .id = SCUTIMER_DEVICE_ID, - .freq_hz = SCU_TIMER_CLK_HZ, - .ticks_count = (SCU_TIMER_CLK_HZ/2), //update log every 500ms +struct timer_init_param apptimer_init_param = { + .id = APPTIMER_DEVICE_ID, + .freq_hz = APP_TIMER_CLK_HZ, + .ticks_count = (APP_TIMER_CLK_HZ/10), //update log every 100ms .platform_ops = &xil_timer_ops, - .extra = &xil_scutimer_init_param + .extra = &xil_apptimer_init_param }; diff --git a/df_datalink_ge/src/drivers/adc/ad9653/ad9653.c b/df_datalink_ge/src/drivers/adc/ad9653/ad9653.c new file mode 100644 index 0000000..c2647b8 --- /dev/null +++ b/df_datalink_ge/src/drivers/adc/ad9653/ad9653.c @@ -0,0 +1,129 @@ +/***************************************************************************//** + * @file ad9653.c + * @brief Implementation of AD9653 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9653.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9653_read + *******************************************************************************/ +int32_t ad9653_read(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9653_write + *******************************************************************************/ +int32_t ad9653_write(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9653_init + *******************************************************************************/ +int32_t ad9653_init(struct ad9653_dev **device, + const struct ad9653_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9653_dev *dev; + + dev = (struct ad9653_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9653_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9653_remove(struct ad9653_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/adc/ad9653/ad9653.h b/df_datalink_ge/src/drivers/adc/ad9653/ad9653.h new file mode 100644 index 0000000..71aae2d --- /dev/null +++ b/df_datalink_ge/src/drivers/adc/ad9653/ad9653.h @@ -0,0 +1,233 @@ +/***************************************************************************//** + * @file ad9653.h + * @brief Header file of AD9653 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9653_H_ +#define AD9653_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000 +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001 +#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002 +#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003 +#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004 +#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006 +#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008 +#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009 +#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A +#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B +#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C +#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D +#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F +#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040 +#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108 +#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109 +#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A +#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110 +#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111 +#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112 +#define AD9694_REG_CLK_DETN_CTRL 0x011A +#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B +#define AD9694_REG_CLK_DCS_CTRL_1 0x011C +#define AD9694_REG_CLK_DCS_CTRL_2 0x011E +#define AD9694_REG_CLK_DCS_CTRL_3 0x011F +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A +#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF +#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200 +#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201 +#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228 +#define AD9694_REG_CH_MAP_FD_CTRL 0x0245 +#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247 +#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248 +#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249 +#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C +#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F +#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278 +#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279 +#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A +#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300 +#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310 +#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322 +#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327 +#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330 +#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342 +#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347 +#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A +#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561 +#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564 +#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E +#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F +#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574 +#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578 +#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580 +#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581 +#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583 +#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585 +#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B +#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C +#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D +#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E +#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F +#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590 +#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591 +#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1 +#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6 +#define AD9694_REG_LARGE_DITHER_CTRL 0x0922 +#define AD9694_REG_PLL_CAL 0x1222 +#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228 +#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262 +#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701 +#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B +#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6 +#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0 +#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1 +#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2 +#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3 +#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6 +#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908 +#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910 +#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C +#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9653_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_pdwn; +}; + +struct ad9653_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_pdwn; +}; + +struct ad9653_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9653_read(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9653_write(struct ad9653_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9653_init(struct ad9653_dev **device, + const struct ad9653_init_param *init_param); + +int32_t ad9653_remove(struct ad9653_dev *dev); + +#endif diff --git a/df_datalink_ge/src/drivers/adc/ad9694/ad9694.c b/df_datalink_ge/src/drivers/adc/ad9694/ad9694.c new file mode 100644 index 0000000..336ea4b --- /dev/null +++ b/df_datalink_ge/src/drivers/adc/ad9694/ad9694.c @@ -0,0 +1,128 @@ +/***************************************************************************//** + * @file ad9694.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9694.h" +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9694_read + *******************************************************************************/ +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9694_write + *******************************************************************************/ +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9694_init + *******************************************************************************/ +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9694_dev *dev; + + dev = (struct ad9694_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9694_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9694_remove(struct ad9694_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/adc/ad9694/ad9694.h b/df_datalink_ge/src/drivers/adc/ad9694/ad9694.h new file mode 100644 index 0000000..3c4446a --- /dev/null +++ b/df_datalink_ge/src/drivers/adc/ad9694/ad9694.h @@ -0,0 +1,231 @@ +/***************************************************************************//** + * @file ad9694.h + * @brief Header file of AD9694 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef AD9694_H_ +#define AD9694_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_A 0x0000 +#define AD9694_REG_GLOBAL_MAP_SPI_CONF_B 0x0001 +#define AD9694_REG_CH_MAP_CHIP_CONF 0x0002 +#define AD9694_REG_PAIR_MAP_CHIP_TYPE 0x0003 +#define AD9694_REG_PAIR_MAP_CHIP_ID_LSB 0x0004 +#define AD9694_REG_PAIR_MAP_CHIP_GRADE 0x0006 +#define AD9694_REG_PAIR_MAP_DEV_INDEX 0x0008 +#define AD9694_REG_GLOBAL_MAP_PAIR_INDEX 0x0009 +#define AD9694_REG_PAIR_MAP_SCRATCH_PAD 0x000A +#define AD9694_REG_PAIR_MAP_SPI_REVISION 0x000B +#define AD9694_REG_PAIR_MAP_VENDOR_ID_LSB 0x000C +#define AD9694_REG_PAIR_MAP_VENDOR_ID_MSB 0x000D +#define AD9694_REG_CH_MAP_CHIP_PD_PIN 0x003F +#define AD9694_REG_PAIR_MAP_CHIP_PIN_CTRL_1 0x0040 +#define AD9694_REG_PAIR_MAP_CLK_DIV_CTRL 0x0108 +#define AD9694_REG_CH_MAP_CLK_DIV_PHASE 0x0109 +#define AD9694_REG_PAIR_MAP_CLK_DIV_SYSREF_CTRL 0x010A +#define AD9694_REG_PAIR_MAP_CLK_DELAY_CTRL 0x0110 +#define AD9694_REG_CH_MAP_CLK_SUPER_FINE_DELAY 0x0111 +#define AD9694_REG_CH_MAP_CLK_FINE_DELAY 0x0112 +#define AD9694_REG_CLK_DETN_CTRL 0x011A +#define AD9694_REG_PAIR_MAP_CLK_STAT 0x011B +#define AD9694_REG_CLK_DCS_CTRL_1 0x011C +#define AD9694_REG_CLK_DCS_CTRL_2 0x011E +#define AD9694_REG_CLK_DCS_CTRL_3 0x011F +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_1 0x0120 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_2 0x0121 +#define AD9694_REG_PAIR_MAP_SYSREF_CTRL_4 0x0123 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_1 0x0128 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_2 0x0129 +#define AD9694_REG_PAIR_MAP_SYSREF_STAT_3 0x012A +#define AD9694_REG_PAIR_MAP_CHIP_SYNC 0x01FF +#define AD9694_REG_PAIR_MAP_CHIP_MODE 0x0200 +#define AD9694_REG_PAIR_MAP_CHIP_DEC_RATIO 0x0201 +#define AD9694_REG_CH_MAP_CUSTOM_OFFSET 0x0228 +#define AD9694_REG_CH_MAP_FD_CTRL 0x0245 +#define AD9694_REG_CH_MAP_FD_UT_LSB 0x0247 +#define AD9694_REG_CH_MAP_FD_UT_MSB 0x0248 +#define AD9694_REG_CH_MAP_FD_LT_LSB 0x0249 +#define AD9694_REG_CH_MAP_FD_LT_MSB 0x024A +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_LSB 0x024B +#define AD9694_REG_CH_MAP_FD_DWELL_TIME_MSB 0x024C +#define AD9694_REG_PAIR_MAP_SIG_MON_SYNC_CTRL 0x026F +#define AD9694_REG_CH_MAP_SIG_MON_CTRL 0x0270 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_0 0x0271 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_1 0x0272 +#define AD9694_REG_CH_MAP_SIG_MON_PERIOD_2 0x0273 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_CTRL 0x0274 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_0 0x0275 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_1 0x0276 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_2 0x0277 +#define AD9694_REG_CH_MAP_SIG_MON_STAT_FRAME_CNT 0x0278 +#define AD9694_REG_CH_MAP_SIG_MON_SERIAL_FRAMER_CTRL 0x0279 +#define AD9694_REG_SPORT_OVER_JESD204B_INPUT_SEL 0x027A +#define AD9694_REG_PAIR_MAP_DDC_SYNC_CTRL 0x0300 +#define AD9694_REG_PAIR_MAP_DDC_0_CTRL 0x0310 +#define AD9694_REG_PAIR_MAP_DDC_0_INPUT_SEL 0x0311 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_0 0x0314 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_1 0x0315 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_2 0x0316 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_3 0x0317 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_4 0x0318 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_INC_5 0x031A +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_0 0x031D +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_1 0x031E +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_2 0x031F +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_3 0x0320 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_4 0x0321 +#define AD9694_REG_PAIR_MAP_DDC_0_PHASE_OFFSET_5 0x0322 +#define AD9694_REG_PAIR_MAP_DDC_0_TEST_ENABLE 0x0327 +#define AD9694_REG_PAIR_MAP_DDC_1_CTRL 0x0330 +#define AD9694_REG_PAIR_MAP_DDC_1_INPUT_SEL 0x0331 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_0 0x0334 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_1 0x0335 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_2 0x0336 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_3 0x0337 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_4 0x0338 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_INC_5 0x033A +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_0 0x033D +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_1 0x033E +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_2 0x033F +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_3 0x0340 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_4 0x0341 +#define AD9694_REG_PAIR_MAP_DDC_1_PHASE_OFFSET_5 0x0342 +#define AD9694_REG_PAIR_MAP_DDC_1_TEST_ENABLE 0x0347 +#define AD9694_REG_CH_MAP_TEST_MODE_CTRL 0x0550 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_LSB 0x0551 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_1_MSB 0x0552 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_LSB 0x0553 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_2_MSB 0x0554 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_LSB 0x0555 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_3_MSB 0x0556 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_LSB 0x0557 +#define AD9694_REG_PAIR_MAP_USER_PATTERN_4_MSB 0x0558 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_0 0x0559 +#define AD9694_REG_PAIR_MAP_OUTPUT_CTRL_MODE_1 0x055A +#define AD9694_REG_PAIR_MAP_OUTPUT_SAMPLE_MODE 0x0561 +#define AD9694_REG_PAIR_MAP_OUTPUT_CH_SEL 0x0564 +#define AD9694_REG_JESD204B_MAP_PLL_CTRL 0x056E +#define AD9694_REG_JESD204B_MAP_PLL_STAT 0x056F +#define AD9694_REG_JESD204B_MAP_JTX_QUICK_CONF 0x0570 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_1 0x0571 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_2 0x0572 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_3 0x0573 +#define AD9694_REG_JESD204B_MAP_JTX_LINK_CTRL_4 0x0574 +#define AD9694_REG_JESD204B_MAP_JTX_LMFC_OFFSET 0x0578 +#define AD9694_REG_JESD204B_MAP_JTX_DID_CONF 0x0580 +#define AD9694_REG_JESD204B_MAP_JTX_BID_CONF 0x0581 +#define AD9694_REG_JESD204B_MAP_JTX_LID_0_CONF 0x0583 +#define AD9694_REG_JESD204B_MAP_JTX_LID_1_CONF 0x0585 +#define AD9694_REG_JESD204B_MAP_JTX_SCR_L_CONF 0x058B +#define AD9694_REG_JESD204B_MAP_JTX_F_CONF 0x058C +#define AD9694_REG_JESD204B_MAP_JTX_K_CONF 0x058D +#define AD9694_REG_JESD204B_MAP_JTX_M_CONF 0x058E +#define AD9694_REG_JESD204B_MAP_JTX_CS_N_CONF 0x058F +#define AD9694_REG_JESD204B_MAP_JTX_SUBCLASS_CONF 0x0590 +#define AD9694_REG_JESD204B_MAP_JTX_S_CONF 0x0591 +#define AD9694_REG_JESD204B_MAP_JTX_HD_CF_CONF 0x0592 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_0_CONF 0x05A0 +#define AD9694_REG_JESD204B_MAP_JTX_CHECKSUM_1_CONF 0x05A1 +#define AD9694_REG_SERDOUTX0_SERDOUTX1_LANE_PD 0x05B0 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_1 0x05B2 +#define AD9694_REG_JESD204B_MAP_JTX_LANE_ASSIGN_2 0x05B3 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_0 0x05C0 +#define AD9694_REG_JESD204B_MAP_SERD_ADJUST_1 0x05C1 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_0 0x05C4 +#define AD9694_REG_JESD204B_SER_PE_SEL_LANE_1 0x05C6 +#define AD9694_REG_LARGE_DITHER_CTRL 0x0922 +#define AD9694_REG_PLL_CAL 0x1222 +#define AD9694_REG_JESD204B_STARTUP_CIRCUIT_RST 0x1228 +#define AD9694_REG_PLL_LOSS_OF_LOCK_CTRL 0x1262 +#define AD9694_REG_DC_OFFSET_CAL_CTRL 0x0701 +#define AD9694_REG_DC_OFFSET_CAL_CTRL_2 0x073B +#define AD9694_REG_PAIR_MAP_VREF_CTRL 0x18A6 +#define AD9694_REG_EXT_VCM_BUF_CTRL_1 0x18E0 +#define AD9694_REG_EXT_VCM_BUF_CTRL_2 0x18E1 +#define AD9694_REG_EXT_VCM_BUF_CTRL_3 0x18E2 +#define AD9694_REG_EXT_VCM_BUF_CTRL 0x18E3 +#define AD9694_REG_TEMP_DIODE_EXPORT 0x18E6 +#define AD9694_REG_CH_MAP_ANALOG_INPUT_CTRL 0x1908 +#define AD9694_REG_CH_MAP_INPUT_FULLSCALE_RANGE 0x1910 +#define AD9694_REG_CH_MAP_BUF_CTRL_1 0x1A4C +#define AD9694_REG_CH_MAP_BUF_CTRL_2 0x1A4D + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9694_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct ad9694_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct ad9694_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9694_read(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9694_write(struct ad9694_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9694_init(struct ad9694_dev **device, + const struct ad9694_init_param *init_param); + +int32_t ad9694_remove(struct ad9694_dev *dev); + +#endif diff --git a/df_datalink_ge/src/drivers/api/gpio.c b/df_datalink_ge/src/drivers/api/gpio.c new file mode 100644 index 0000000..5b37137 --- /dev/null +++ b/df_datalink_ge/src/drivers/api/gpio.c @@ -0,0 +1,241 @@ +/***************************************************************************//** + * @file gpio.c + * @brief Implementation of the GPIO Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "gpio.h" +#include +#include "error.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + int32_t ret; + + if (!param || (param->number == -1)) { + *desc = NULL; + return 0; + } + + if (!param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->gpio_ops_get_optional) + return -ENOSYS; + + ret = param->platform_ops->gpio_ops_get_optional(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_remove(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_remove) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_remove(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_input(struct gpio_desc *desc) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_input) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_direction_input(desc); + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_direction_output) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_direction_output(desc, value); + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_get_direction) + return -ENOSYS; + + return desc->platform_ops-> + gpio_ops_get_direction(desc, direction); + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_set_value(desc, value); + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (desc) { + if (!desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->gpio_ops_set_value) + return -ENOSYS; + + return desc->platform_ops->gpio_ops_get_value(desc, value); + } + + return 0; +} diff --git a/df_datalink_ge/src/drivers/api/i2c.c b/df_datalink_ge/src/drivers/api/i2c.c new file mode 100644 index 0000000..149e7cd --- /dev/null +++ b/df_datalink_ge/src/drivers/api/i2c.c @@ -0,0 +1,135 @@ +/***************************************************************************//** + * @file i2c.c + * @brief Implementation of the I2C Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "i2c.h" +#include +#include "error.h" + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->i2c_ops_init) + return -ENOSYS; + + ret = param->platform_ops->i2c_ops_init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + + return 0; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_remove(struct i2c_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_remove) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_remove(desc); +} + +/** + * @brief I2C Write data to slave device. + * @param desc - The I2C descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_write) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_write(desc, data, bytes_number, + stop_bit); +} + +/** + * @brief I2C Read data from slave device. + * @param desc - The i2c descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop conditional control. + * Example: 0 - A stop condition will not be generated. + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->i2c_ops_read) + return -ENOSYS; + + return desc->platform_ops->i2c_ops_read(desc, data, bytes_number, + stop_bit); +} diff --git a/df_datalink_ge/src/drivers/api/spi.c b/df_datalink_ge/src/drivers/api/spi.c new file mode 100644 index 0000000..954f669 --- /dev/null +++ b/df_datalink_ge/src/drivers/api/spi.c @@ -0,0 +1,161 @@ +/***************************************************************************//** + * @file spi.c + * @brief Implementation of the SPI Interface + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include +#include "spi.h" +#include +#include "error.h" + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + + if (!param || !param->platform_ops) + return -EINVAL; + + if (!param->platform_ops->init) + return -ENOSYS; + + ret = param->platform_ops->init(desc, param); + if (ret) + return ret; + + (*desc)->platform_ops = param->platform_ops; + (*desc)->parent = param->parent; + + return 0; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_remove(struct spi_desc *desc) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->remove) + return -ENOSYS; + + return desc->platform_ops->remove(desc); +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read) + return -ENOSYS; + + return desc->platform_ops->write_and_read(desc, data, bytes_number); +} + +/** + * @brief Write and read data to/from SPI in 3 wire mode. + * @param desc - The SPI descriptor. + * @param write_data - The buffer with the transmitted data. + * @param read_data - The buffer with the received data. + * @param write_bytes_number - Number of bytes to write. + * @param read_bytes_number - Number of bytes to read. + * @return SUCCESS in case of success, FAILURE otherwise. + */ +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (!desc->platform_ops->write_and_read_3wire) + return -ENOSYS; + return desc->platform_ops->write_and_read_3wire(desc, write_data, read_data, + write_bytes_number, read_bytes_number); +} +/** + * @brief Iterate over head list and send all spi messages + * @param desc - The SPI descriptor. + * @param msgs - Array of messages. + * @param len - Number of messages in the array. + * @return 0 in case of success, negativ error code otherwise. + */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) +{ + int32_t ret; + uint32_t i; + + if (!desc || !desc->platform_ops) + return -EINVAL; + + if (desc->platform_ops->transfer) + return desc->platform_ops->transfer(desc, msgs, len); + + for (i = 0; i < len; i++) { + if (msgs[i].rx_buff != msgs[i].tx_buff || !msgs[i].tx_buff) + return -EINVAL; + ret = spi_write_and_read(desc, msgs[i].rx_buff, + msgs[i].bytes_number); + if (IS_ERR_VALUE(ret)) + return ret; + } + + return 0; +} diff --git a/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.c b/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.c new file mode 100644 index 0000000..885fc74 --- /dev/null +++ b/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.c @@ -0,0 +1,547 @@ +/******************************************************************************* + * @file axi_dmac.c + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "axi_io.h" +#include "error.h" +#include "delay.h" +#include "axi_dmac.h" + +/******************************************************************************* + * @brief ISR for dev to mem DMA transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /* See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute size of the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* Trigger the next transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + dmac->transfer.transfer_done = true; + dmac->next_dest_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to dev transfer. It computes the next transfer params, + * if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_dev_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if ((dmac->transfer.cyclic == CYCLIC) && + (dmac->next_src_addr >= (dmac->init_addr + dmac->transfer.size - 1))) { + dmac->remaining_size = dmac->transfer.size; + dmac->next_src_addr = dmac->init_addr; + } + + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if ((!dmac->remaining_size) && (dmac->transfer.cyclic != CYCLIC)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + } + } +} + +/******************************************************************************* + * @brief ISR for mem DMA to mem DMA transfer. It computes the next transfer + * params, if any, and sets the transfer structure fields accordingly. + * + * @param instance - the instance that triggered the ISR. + * + * @return None. +*******************************************************************************/ +void axi_dmac_mem_to_mem_isr(void *instance) +{ + struct axi_dmac *dmac = (struct axi_dmac *)instance; + uint32_t burst_size; + uint32_t reg_val; + + /* Get interrupt sources and clear interrupts. */ + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_PENDING, reg_val); + + if (reg_val & AXI_DMAC_IRQ_SOT) { + if (dmac->remaining_size) { + /** See if remaining size is bigger than max transfer size and + * set burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* The current transfer was started; set up the new one. */ + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + + /* Compute parameters for the next transfer. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + /* Address must advance with +1 since the DMAC writes X_LENGTH+1. */ + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + + /* If transfer finished advance src address so that transfer_done can be set*/ + if (!dmac->remaining_size) { + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + } + + /* Trigger the current transfer */ + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } + } + if (reg_val & AXI_DMAC_IRQ_EOT) { + if (!dmac->remaining_size) { + if(dmac->next_src_addr > (dmac->init_addr + dmac->transfer.size)) { + dmac->transfer.transfer_done = true; + dmac->next_src_addr = 0; + dmac->next_dest_addr = 0; + } + } + } +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem read function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to read from. + * @param reg_data - Location where read data will be stored. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_read(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Wrapper for AXI IO through UIO/devmem wrrite function. + * + * @param dmac - DMAC istance containing UIO index (/dev/uioX)/base address. + * @param reg_addr - Address to write to. + * @param reg_data - Data to be written. + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_write(struct axi_dmac *dmac, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(dmac->base, reg_addr, reg_data); + + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @note This function should not be used if DMA IRQ is not used. + * + * @param dmac - DMAC istance. + * @param rdy - Transfer status (0 - not ready, 1 - ready). + * + * @return 0 - success. +*******************************************************************************/ +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy) +{ + *rdy = dmac->transfer.transfer_done; + + return 0; +} + +/******************************************************************************* + * @brief Get DMAC capabilities. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +static int32_t axi_dmac_detect_caps(struct axi_dmac *dmac) +{ + uint32_t reg_val, initial_reg_val = 0; + uint32_t src_mem_mapped = 0; + uint32_t dest_mem_mapped = 0; + + dmac->max_length = -1; + dmac->direction = INVALID_DIR; + + /* Check if HW cyclic possible */ + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, &initial_reg_val); + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, DMA_CYCLIC); + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + if (reg_val == DMA_CYCLIC) + dmac->hw_cyclic = true; + /* Restore initial value for AXI_DMAC_REG_FLAGS register */ + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, initial_reg_val); + + /* Get maximum burst size and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, dmac->max_length); + axi_dmac_read(dmac, AXI_DMAC_REG_X_LENGTH, &dmac->max_length); + + /* Get transfer direction and set value. */ + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_DEST_ADDRESS, &dest_mem_mapped); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, 0xffffffff); + axi_dmac_read(dmac, AXI_DMAC_REG_SRC_ADDRESS, &src_mem_mapped); + + if (dest_mem_mapped && !src_mem_mapped) { + dmac->direction = DMA_DEV_TO_MEM; + } else if (!dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_DEV; + } else if (dest_mem_mapped && src_mem_mapped) { + dmac->direction = DMA_MEM_TO_MEM; + } else { + printf("Destination and source memory-mapped interfaces not supported.\n"); + return -1; + } + return 0; +} + +/******************************************************************************* + * @brief Get transfer status (value of dmac->transfer.transfer_done flag). + * + * @param dmac_core - DMAC istance. + * @param init - Structure containing initializing data. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_init(struct axi_dmac **dmac_core, + const struct axi_dmac_init *init) +{ + struct axi_dmac *dmac; + + dmac = (struct axi_dmac *)calloc(1, sizeof(*dmac)); + if (!dmac) + return -1; + + dmac->name = init->name; + dmac->base = init->base; + dmac->irq_option = init->irq_option; + + *dmac_core = dmac; + + int32_t status = axi_dmac_detect_caps(*dmac_core); + if (status < 0) + return -1; + + return 0; +} + +/******************************************************************************* + * @brief Remove the DMAC instance. + * + * @param dmac - DMAC istance. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_remove(struct axi_dmac *dmac) +{ + if (!dmac) + return -1; + + free(dmac); + + return 0; +} + +/******************************************************************************* + * @brief Start a DMA transfer. + * + * @param dmac - DMAC istance. + * @param dma_transfer - Structure containing transfer details. + * + * @return 0 for success, -1 in case of failure. +*******************************************************************************/ +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer) +{ + uint32_t reg_val, burst_size; + + if (dma_transfer->size == 0) + return 0; /* Nothing to do. */ + + /* Set current transfer parameters. */ + dmac->transfer.size = dma_transfer->size; + dmac->transfer.cyclic = dma_transfer->cyclic; + dmac->transfer.dest_addr = dma_transfer->dest_addr; + dmac->transfer.src_addr = dma_transfer->src_addr; + + dmac->remaining_size = dma_transfer->size; + dmac->next_dest_addr = dma_transfer->dest_addr; + dmac->next_src_addr = dma_transfer->src_addr; + + /* If HW cyclic transfer selected and not available, show error */ + /* HW cyclic transfer available only for MEM to DEV transfers. */ + if ((!dmac->hw_cyclic) && (dma_transfer->cyclic == CYCLIC)) { + printf("Transfer mode not supported!\n"); + return -1; + } + + /* Cyclic transfers not possible for DEV_TO_MEM and MEM_TO_MEM transmissions. */ + if ((dmac->direction == DMA_DEV_TO_MEM) + || (dmac->direction == DMA_MEM_TO_MEM)) { + if (dma_transfer->cyclic == CYCLIC) { + printf("Transfer mode not supported!\n"); + return -1; + } + } + + /* Cyclic transfers set to HW or SW depending on size for MEM to DEV. */ + if ((dmac->direction == DMA_MEM_TO_DEV) && (dmac->transfer.cyclic == CYCLIC)) { + if ((dmac->remaining_size - 1) <= dmac->max_length) { + if (dmac->hw_cyclic) { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val | DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } else { + axi_dmac_read(dmac, AXI_DMAC_REG_FLAGS, ®_val); + reg_val = reg_val & ~DMA_CYCLIC; + axi_dmac_write(dmac, AXI_DMAC_REG_FLAGS, reg_val); + } + } + + /* Enable DMA if not already enabled. */ + axi_dmac_read(dmac, AXI_DMAC_REG_CTRL, ®_val); + if (!(reg_val & AXI_DMAC_CTRL_ENABLE)) { + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_ENABLE); + axi_dmac_write(dmac, AXI_DMAC_REG_IRQ_MASK, 0x0); + } + + axi_dmac_read(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, ®_val); + /* If we don't have a start of transfer then start compute + * values and trigger next transfer. */ + if (!(reg_val & AXI_DMAC_QUEUE_FULL)) { + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->init_addr = dmac->next_dest_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + break; + case DMA_MEM_TO_DEV: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + case DMA_MEM_TO_MEM: + dmac->init_addr = dmac->next_src_addr; + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_ADDRESS, dmac->next_dest_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_DEST_STRIDE, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_ADDRESS, dmac->next_src_addr); + axi_dmac_write(dmac, AXI_DMAC_REG_SRC_STRIDE, 0x0); + break; + default: + return -1; /* Other directions are not supported yet. */ + } + + /* Compute the burst size. */ + if (dmac->remaining_size > dmac->max_length) { + burst_size = dmac->max_length; + } else { + burst_size = dmac->remaining_size - 1; + } + + /* Compute next address (src or dest, or both, depending on type of transfer). */ + switch (dmac->direction) { + case DMA_DEV_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + break; + case DMA_MEM_TO_DEV: + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + case DMA_MEM_TO_MEM: + dmac->next_dest_addr = dmac->next_dest_addr + (burst_size + 1); + dmac->next_src_addr = dmac->next_src_addr + (burst_size + 1); + break; + default: + return -1; + } + + /* Compute remaining size. */ + dmac->remaining_size = dmac->remaining_size - (burst_size + 1); + + /* Specify the length of the transfer and trigger transfer. */ + axi_dmac_write(dmac, AXI_DMAC_REG_X_LENGTH, burst_size); + axi_dmac_write(dmac, AXI_DMAC_REG_Y_LENGTH, 0x0); + axi_dmac_write(dmac, AXI_DMAC_REG_TRANSFER_SUBMIT, AXI_DMAC_TRANSFER_SUBMIT); + } else { + return -1; + } + + return 0; +} + +/******************************************************************************* + * @brief Wait for DMA transfer to be completed. + * + * @param dmac - DMAC istance. + * @param timeout_ms - Number of ms to wait for completion of transfer. + * + * @return 0 for success, -1 in case trasnfer not completed in specified time. +*******************************************************************************/ +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms) +{ + uint32_t timeout = 0; + uint32_t reg_val = 0; + + if (dmac->irq_option == IRQ_ENABLED) { + while (!dmac->transfer.transfer_done) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + } + } else if (dmac->irq_option == IRQ_DISABLED) { + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + while (reg_val != (AXI_DMAC_IRQ_SOT | AXI_DMAC_IRQ_EOT)) { + timeout++; + mdelay(1); + if (timeout == timeout_ms) { + printf("Error transferring data using DMA.\n"); + return -1; + } + axi_dmac_read(dmac, AXI_DMAC_REG_IRQ_PENDING, ®_val); + } + } + + return 0; +} + +/******************************************************************************* + * @brief Stop a DMA transfer. + * + * @param dmac - DMAC istance. + * + * @return None +*******************************************************************************/ +void axi_dmac_transfer_stop(struct axi_dmac *dmac) +{ + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, AXI_DMAC_CTRL_DISABLE); +} diff --git a/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.h b/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.h new file mode 100644 index 0000000..6092a5b --- /dev/null +++ b/df_datalink_ge/src/drivers/axi_core/axi_dmac/axi_dmac.h @@ -0,0 +1,156 @@ +/***************************************************************************//** + * @file axi_dmac.h + * @brief Driver for the Analog Devices AXI-DMAC core. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AXI_DMAC_H_ +#define AXI_DMAC_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define AXI_DMAC_REG_IRQ_MASK 0x80 +#define AXI_DMAC_REG_IRQ_PENDING 0x84 +#define AXI_DMAC_IRQ_SOT BIT(0) +#define AXI_DMAC_IRQ_EOT BIT(1) + +#define AXI_DMAC_REG_INTF_DESC 0x010 +#define AXI_DMAC_DMA_TYPE_DEST GENMASK(5,4) +#define AXI_DMAC_DMA_TYPE_SRC GENMASK(13,12) +//Define macro for src and dest + +#define AXI_DMAC_REG_CTRL 0x400 +#define AXI_DMAC_CTRL_ENABLE BIT(0) +#define AXI_DMAC_CTRL_DISABLE 0u +#define AXI_DMAC_CTRL_PAUSE BIT(1) + +#define AXI_DMAC_REG_TRANSFER_ID 0x404 +#define AXI_DMAC_REG_TRANSFER_SUBMIT 0x408 +#define AXI_DMAC_TRANSFER_SUBMIT BIT(0) +#define AXI_DMAC_QUEUE_FULL BIT(0) +#define AXI_DMAC_REG_FLAGS 0x40c +#define AXI_DMAC_REG_DEST_ADDRESS 0x410 +#define AXI_DMAC_REG_SRC_ADDRESS 0x414 +#define AXI_DMAC_REG_X_LENGTH 0x418 +#define AXI_DMAC_REG_Y_LENGTH 0x41c +#define AXI_DMAC_REG_DEST_STRIDE 0x420 +#define AXI_DMAC_REG_SRC_STRIDE 0x424 +#define AXI_DMAC_REG_TRANSFER_DONE 0x428 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +enum use_irq { + IRQ_DISABLED = 0, + IRQ_ENABLED = 1 +}; + +enum dma_direction { + INVALID_DIR = 0, + DMA_DEV_TO_MEM = 1, + DMA_MEM_TO_DEV = 2, + DMA_MEM_TO_MEM = 3 +}; + +enum dma_flags { + DMA_CYCLIC = 1, + DMA_LAST = 2, + DMA_PARTIAL_REPORTING_EN = 4 +}; + +// Could be transformed to a bool +enum cyclic_transfer { + NO = 0, + CYCLIC = 1 +}; + +struct axi_dma_transfer { + uint32_t size; + volatile bool transfer_done; + enum cyclic_transfer cyclic; + uint32_t src_addr; + uint32_t dest_addr; +}; + +struct axi_dmac { + const char *name; + uint32_t base; + enum use_irq irq_option; + enum dma_direction direction; + bool hw_cyclic; + uint32_t max_length; + volatile struct axi_dma_transfer transfer; + //Current sub-transfer properties + uint32_t init_addr; + uint32_t remaining_size; + uint32_t next_src_addr; + uint32_t next_dest_addr; +}; + +struct axi_dmac_init { + const char *name; + uint32_t base; + enum use_irq irq_option; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +void axi_dmac_dev_to_mem_isr(void *instance); +void axi_dmac_mem_to_dev_isr(void *instance); +void axi_dmac_mem_to_mem_isr(void *instance); +void axi_dmac_write_isr(void *instance); +int32_t axi_dmac_read(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t *reg_data); +int32_t axi_dmac_write(struct axi_dmac *dmac, uint32_t reg_addr, + uint32_t reg_data); +int32_t axi_dmac_is_transfer_ready(struct axi_dmac *dmac, bool *rdy); +int32_t axi_dmac_init(struct axi_dmac **adc_core, + const struct axi_dmac_init *init); +int32_t axi_dmac_remove(struct axi_dmac *dmac); +int32_t axi_dmac_transfer_start(struct axi_dmac *dmac, + struct axi_dma_transfer *dma_transfer); +int32_t axi_dmac_transfer_wait_completion(struct axi_dmac *dmac, + uint32_t timeout_ms); +void axi_dmac_transfer_stop(struct axi_dmac *dmac); + +#endif diff --git a/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.c b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.c new file mode 100644 index 0000000..f94a549 --- /dev/null +++ b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.c @@ -0,0 +1,996 @@ +/******************************************************************************* + * @file spi_engine.c + * @brief Core implementation of the SPI Engine Driver. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +/* In debug mode the printf function used in displaying the messages is causing +significant delays */ +//#define DEBUG_LEVEL 2 + +#include +#include +#include +#include +#include +#include + +#include "axi_io.h" +#include "error.h" +#include "spi_engine.h" + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +const struct spi_platform_ops spi_eng_platform_ops = { + .init = &spi_engine_init, + .write_and_read = &spi_engine_write_and_read, + .write_and_read_3wire = &spi_engine_write_and_read_3wire, + .remove = &spi_engine_remove +}; + +/******************************************************************************/ +/***************************** Static variables *******************************/ +/******************************************************************************/ + +/** + * @brief Static variable used to sync transfers + * + */ +static uint8_t _sync_id = 0x01; + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * @brief Write SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register where the data + * will be written + * @param reg_data Data that will be written + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data) +{ + axi_io_write(desc->spi_engine_baseaddr, reg_addr, reg_data); + + return SUCCESS; +} + +/** + * @brief Read SPI Engine's axi registers + * + * @param desc Decriptor containing SPI Engine's parameters + * @param reg_addr The address of the SPI Engine's axi register from where the + * data where the data will be read + * @param reg_data Pointer where the read that will be stored + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data) +{ + axi_io_read(desc->spi_engine_baseaddr, reg_addr, reg_data); + return SUCCESS; +} + +/** + * @brief Set width of the transferred word over SPI + * + * @param desc Decriptor containing SPI interface parameters + * @param data_width The desired data width + * The supported values are: + * - 8 + * - 16 + * - 24 + * - 32 + */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_width) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + if (data_width > desc_extra->max_data_width) + desc_extra->data_width = desc_extra->max_data_width; + else + desc_extra->data_width = data_width; + + return SUCCESS; +} + +/** + * @brief Set SPI engine clock frequency + * + * @param desc Decriptor containing SPI Engine's parameters + * @param speed_hz SPI engine transfer speed + */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + desc_extra->clk_div = desc_extra->ref_clk_hz / + (2 * speed_hz) - 1; +} + +/** + * @brief Set the number of words transferred in a single transaction + * + * @param desc Decriptor containing SPI Engine's parameters + * @param bytes_number The number of bytes to be converted + * @return uint8_t A number of words in which bytes_number can be grouped + */ +static uint8_t spi_get_words_number(struct spi_engine_desc *desc, + uint8_t bytes_number) +{ + uint8_t xfer_word_len; + uint8_t words_number; + + xfer_word_len = desc->data_width / 8; + words_number = bytes_number / xfer_word_len; + + if ((bytes_number % xfer_word_len) != 0) + words_number++; + + return words_number; +} + +/** + * @brief Get the word length in bytes + * + * @param desc Decriptor containing SPI Engine's parameters + * @return uint8_t Number of bytes that fit in one word + */ +static uint8_t spi_get_word_length(struct spi_engine_desc *desc) +{ + uint8_t word_length; + + word_length = desc->data_width / 8; + + return word_length; +} + +/** + * @brief Compute the prescaler used to set the sleep period. + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns The amount of time where the transfer hangs + * @param sleep_div Clock prescaler + * @return int32_t This function allways returns SUCCESS + */ +static int32_t spi_get_sleep_div(struct spi_desc *desc, + uint32_t sleep_time_ns, + uint32_t *sleep_div) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + /* + * Engine Wiki: + * + * The frequency of the SCLK signal is derived from the + * module clock frequency using the following formula: + * f_sclk = f_clk / ((div + 1) * 2) + */ + + *sleep_div = (desc->max_speed_hz / 1000000 * sleep_time_ns / 1000) / + ((eng_desc->clk_div + 1) * 2) - 1; + + return SUCCESS; +} + +/** + * @brief Create a new commands queue used in a spi transfer + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command with which the buffer will be initiated + * @return int32_t Failure if the memory allocation failed + */ +static int32_t spi_engine_queue_new_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = (spi_engine_cmd_queue*)malloc(sizeof(*local_fifo)); + + if(!local_fifo) + return FAILURE; + + local_fifo->cmd = cmd; + local_fifo->next = NULL; + *fifo = local_fifo; + + return SUCCESS; +} + +/** + * @brief Add a command at the end of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_add_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + struct spi_engine_cmd_queue *local_fifo; + + local_fifo = *fifo; + while (local_fifo->next != NULL) { + // Get the last element + local_fifo = local_fifo->next; + } + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Add as the next element + local_fifo->next = to_add; +} + +/** + * @brief Add a command at the beginning of an existing queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Command to be added + */ +static void spi_engine_queue_append_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t cmd) +{ + struct spi_engine_cmd_queue *to_add = NULL; + + // Create a new element + spi_engine_queue_new_cmd(&to_add, cmd); + // Interchange the addresses + to_add->next = *fifo; + *fifo = to_add; +} + + +/** + * @brief Get the command from the beginning of the queue + * + * @param fifo Command buffer, usually used in fifo mode + * @param cmd Value of the command that was extracted + * @return int32_t Return FAILURE if the queue is empty + */ +static int32_t spi_engine_queue_get_cmd(struct spi_engine_cmd_queue **fifo, + uint32_t *cmd) +{ + struct spi_engine_cmd_queue *local_fifo; + + if (!*fifo) + return FAILURE; + + local_fifo = *fifo; + *cmd = local_fifo->cmd; + if ((*fifo)->next) { + *fifo = local_fifo->next; + free(local_fifo); + } else { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Free the memory allocated by a queue + * + * @param fifo The queue that needs it's memory freed + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_queue_free(struct spi_engine_cmd_queue **fifo) +{ + if(*fifo && (*fifo)->next) + spi_engine_queue_free(&(*fifo)->next); + if((*fifo) != NULL) { + free(*fifo); + *fifo = NULL; + } + + return SUCCESS; +} + +/** + * @brief Write the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param cmd The command that will be written + * @return int32_t Returns FAILURE if the the axi transfer failed + */ +static int32_t spi_engine_write_cmd_reg(struct spi_engine_desc *desc, + uint32_t cmd) +{ + int32_t ret; + + /* Check if offload is enabled */ + if(desc->offload_config & (OFFLOAD_TX_EN | OFFLOAD_RX_EN)) { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_OFFLOAD_CMD_MEM(0), + cmd); + + } else { + ret = spi_engine_write(desc, + SPI_ENGINE_REG_CMD_FIFO, + cmd); + } + + return ret; +} + +/** + * @brief Write a transfer command to the SPI engine's command fifo + * + * @param desc Decriptor containing SPI Engine's parameters + * @param read_write Read/Write operation flag + * @param bytes_number Number of bytes to transfer + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_transfer(struct spi_engine_desc *desc, + uint8_t read_write, + uint8_t bytes_number) +{ + uint8_t words_number; + + words_number = spi_get_words_number(desc, bytes_number); + + desc->offload_tx_len += words_number; + + /* + * Engine Wiki: + * + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine + * + * The words number is zero based + */ + + spi_engine_write_cmd_reg(desc, + SPI_ENGINE_CMD_TRANSFER(read_write, + words_number - 1)); + + return SUCCESS; +} + +/** + * @brief Change the state of the chip select port + * + * @param desc Decriptor containing SPI interface parameters + * @param assert Chip select state. + * The supported values are : + * -true (HIGH) + * -false (LOW) + */ +static void spi_engine_set_cs(struct spi_desc *desc, + bool assert) +{ + uint8_t mask; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + mask = 0xFF; + /* Switch the state only of the selected chip select */ + if (!assert) + mask ^= BIT(desc->chip_select); + + spi_engine_write_cmd_reg(eng_desc, + SPI_ENGINE_CMD_ASSERT(eng_desc->cs_delay, + mask)); +} + +/** + * @brief Add a delay between the engine commands + * + * @param desc Decriptor containing SPI interface parameters + * @param sleep_time_ns Number of nanoseconds to sleep between commands + */ +static void spi_gen_sleep_ns(struct spi_desc *desc, + uint32_t sleep_time_ns) +{ + uint32_t sleep_div; + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + spi_get_sleep_div(desc, sleep_time_ns, &sleep_div); + + spi_engine_write_cmd_reg(eng_desc, SPI_ENGINE_CMD_SLEEP(sleep_div)); +} + +/** + * @brief Spi engine command interpreter + * + * @param desc Decriptor containing SPI interface parameters + * @param cmd Command to send to the engine + * @return int32_t - SUCCESS if the command is transferred + * - FAILURE if the command format is invalid + */ +static int32_t spi_engine_write_cmd(struct spi_desc *desc, + uint32_t cmd) +{ + uint8_t engine_command; + uint8_t parameter; + uint8_t modifier; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + engine_command = (cmd >> 12) & 0x0F; + modifier = (cmd >> 8) & 0x0F; + parameter = cmd & 0xFF; + + switch(engine_command) { + case SPI_ENGINE_INST_TRANSFER: + spi_engine_transfer(desc_extra, modifier, parameter); + break; + + case SPI_ENGINE_INST_ASSERT: + if(parameter == 0xFF) { + /* Set the CS HIGH */ + spi_engine_set_cs(desc, true); + } else if(parameter == 0x00) { + /* Set the CS LOW */ + spi_engine_set_cs(desc, false); + } + break; + + /* The SYNC and SLEEP commands got the same value but different + modifier */ + case SPI_ENGINE_INST_SYNC_SLEEP: + /* SYNC instruction */ + if(modifier == 0x00) { + spi_engine_write_cmd_reg(desc_extra, cmd); + } else if(modifier == 0x01) { + spi_gen_sleep_ns(desc, parameter); + } + break; + case SPI_ENGINE_INST_CONFIG: + spi_engine_write_cmd_reg(desc_extra, cmd); + + break; + + default: + + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Prepare the command queue before sending it to the engine + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t This function always returns SUCCESS + */ +static int32_t spi_engine_compile_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* Configure the prescaler */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CLK_DIV, + desc_extra->clk_div)); + + /* Set the data transfer length */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_DATA_TRANSFER_LEN, + desc_extra->data_width)); + /* + * Configure the spi mode : + * - 3 wire + * - CPOL + * - CPHA + */ + spi_engine_queue_append_cmd(&msg->cmds, + SPI_ENGINE_CMD_CONFIG( + SPI_ENGINE_CMD_REG_CONFIG, + desc->mode)); + + /* Add a sync command to signal that the transfer has finished */ + spi_engine_queue_add_cmd(&msg->cmds, SPI_ENGINE_CMD_SYNC(_sync_id)); + + return SUCCESS; +} + +/** + * @brief Initiate a spi transfer (Blocking) + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Structure used to store the transfer messages + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +static int32_t spi_engine_transfer_message(struct spi_desc *desc, + struct spi_engine_msg *msg) +{ + uint32_t i; + uint32_t data; + uint32_t sync_id; + bool offload_en; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + spi_engine_compile_message(desc, msg); + + offload_en = (desc_extra->offload_config & OFFLOAD_TX_EN) | + (desc_extra->offload_config & OFFLOAD_RX_EN); + + /* Write the command fifo buffer */ + while(msg->cmds != NULL) { + spi_engine_queue_get_cmd(&msg->cmds, &data); + spi_engine_write_cmd(desc, data); + } + + /* Write a number of tx_length WORDS on the SDO line */ + if(offload_en) { + for(i = 0; i < desc_extra->offload_tx_len; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_OFFLOAD_SDO_MEM(0), + msg->tx_buf[i]); + + } else { + if(msg->tx_buf != NULL){ + for(i = 0; i < msg->tx_length; i++) + spi_engine_write(desc_extra, + SPI_ENGINE_REG_SDO_DATA_FIFO, + msg->tx_buf[i]); + } + do { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SYNC_ID, + &sync_id); + } + /* Wait for the end sync signal */ + while(sync_id != _sync_id); + _sync_id++; + + /* Read a number of rx_length WORDS from the SDI line and store + them */ + for(i = 0; i < msg->rx_length; i++) { + spi_engine_read(desc_extra, + SPI_ENGINE_REG_SDI_DATA_FIFO, + &data); + /* Store the rx data if rx buffer valid, flush sdi_fifo if + rx buffer is invalid.*/ + if(msg->rx_buf != NULL){ + msg->rx_buf[i] = data; + } + } + } + + return SUCCESS; +} + +/** + * @brief Initialize the spi engine + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the spi init parameters + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation failed + */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + uint32_t data_width; + uint32_t spi_engine_version; + struct spi_engine_desc *eng_desc; + struct spi_engine_init_param *spi_engine_init; + + if (!param) { + return FAILURE; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return FAILURE; + } + + eng_desc = (struct spi_engine_desc*)malloc(sizeof(*eng_desc)); + + if (!eng_desc) + return FAILURE; + + spi_engine_init = param->extra; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->chip_select = param->chip_select; + (*desc)->mode = param->mode; + (*desc)->extra = eng_desc; + + eng_desc->offload_config = OFFLOAD_DISABLED; + eng_desc->spi_engine_baseaddr = spi_engine_init->spi_engine_baseaddr; + eng_desc->type = spi_engine_init->type; + eng_desc->cs_delay = spi_engine_init->cs_delay; + eng_desc->ref_clk_hz = spi_engine_init->ref_clk_hz; + eng_desc->clk_div = eng_desc->ref_clk_hz / + (2 * param->max_speed_hz) - 1; + + /* Perform a reset */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x01); + usleep(1000); + spi_engine_write(eng_desc, SPI_ENGINE_REG_RESET, 0x00); + + /* Get current data width */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_DATA_WIDTH, &data_width); + eng_desc->max_data_width = data_width; + + spi_engine_set_transfer_width(*desc, spi_engine_init->data_width); + + /* Get spi engine version */ + spi_engine_read(eng_desc, SPI_ENGINE_REG_VERSION, &spi_engine_version); + + printf("Spi engine v%"PRIu32".%"PRIu32".%"PRIu32" successfully initialized.\n", + (spi_engine_version >> 16), + ((spi_engine_version >> 8) & 0xFF), + (spi_engine_version & 0xFF)); + + return SUCCESS; +} + +/** + * @brief Write/read on the spi interface in 4-wire mode (full-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + uint8_t word_len; + uint8_t words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + words_number = spi_get_words_number(desc_extra, bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(uint32_t*)calloc(words_number, sizeof(msg.tx_buf[0])); + msg.rx_buf =(uint32_t*)calloc(words_number, sizeof(msg.rx_buf[0])); + msg.tx_length = words_number; + msg.rx_length = words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + // add read/write command + spi_engine_queue_add_cmd(&msg.cmds, WRITE_READ(bytes_number)); + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < bytes_number; i++) + msg.tx_buf[i / word_len] |= data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < bytes_number; i++) + data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Write and read on the spi interface in 3-wire mode (half-duplex) + * + * @param desc Decriptor containing SPI interface parameters + * @param data Pointer to data buffer + * @param bytes_number Number of bytes to transfer + * @return int32_t - SUCCESS if the transfer finished + * - FAILURE if the memory allocation or transfer failed + */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number) +{ + uint8_t word_len; + uint8_t wr_words_number; + uint8_t rd_words_number; + int32_t ret; + struct spi_engine_msg msg; + struct spi_engine_desc *desc_extra; + + desc_extra = desc->extra; + + /* If we want to access SPI interface and SPI engine offload module was + * activated, we need to disable it + * This is set in spi_engine_offload_init() */ + desc_extra->offload_config = OFFLOAD_DISABLED; + /* This is set in spi_engine_offload_transfer() */ + spi_engine_write(desc_extra, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0); + + wr_words_number = spi_get_words_number(desc_extra, write_bytes_number); + rd_words_number = spi_get_words_number(desc_extra, read_bytes_number); + + msg.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*msg.cmds)); + if (!msg.cmds) + return FAILURE; + + msg.tx_buf =(wr_words_number>0)?(uint32_t*)calloc(wr_words_number, sizeof(msg.tx_buf[0])):NULL; + msg.rx_buf =(rd_words_number>0)?(uint32_t*)calloc(rd_words_number, sizeof(msg.rx_buf[0])):NULL; + msg.tx_length = wr_words_number; + msg.rx_length = rd_words_number; + + /* Get the length of transferred word */ + word_len = spi_get_word_length(desc_extra); + + /* Make sure the CS is HIGH before starting a transaction */ + msg.cmds->next = NULL; + msg.cmds->cmd = CS_HIGH; + + // Assert select. + spi_engine_queue_add_cmd(&msg.cmds, CS_LOW); + + // add read/write command + if(write_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, WRITE(write_bytes_number)); + if(read_bytes_number > 0) + spi_engine_queue_add_cmd(&msg.cmds, READ(read_bytes_number)); + + // Disable select. + spi_engine_queue_add_cmd(&msg.cmds, CS_HIGH); + + /* Pack the bytes into engine WORDS */ + for (int i = 0; i < write_bytes_number; i++) + msg.tx_buf[i / word_len] |= write_data[i] << (desc_extra->data_width- + (i % word_len + 1) * 8); + + ret = spi_engine_transfer_message(desc, &msg); + + for (int i = 0; i < read_bytes_number; i++) + read_data[i] = msg.rx_buf[(i) / word_len] >> + (desc_extra->data_width - + ((i) % word_len + 1) * 8); + + spi_engine_queue_free(&msg.cmds); + free(msg.tx_buf); + free(msg.rx_buf); + + return ret; +} + +/** + * @brief Initialize the SPI engine's offload module + * + * @param desc Decriptor containing SPI interface parameters + * @param param Structure containing the offload init parameters + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param) +{ + struct spi_engine_desc *eng_desc; + struct axi_dmac_init dmac_init; + + eng_desc = desc->extra; + + eng_desc->offload_config = param->offload_config; + + if(!(param->dma_flags)) { + eng_desc->cyclic = CYCLIC; + } else { + if((*(param->dma_flags)) & DMA_CYCLIC) + eng_desc->cyclic = CYCLIC; + else + eng_desc->cyclic = NO; + } + + + if(param->offload_config & OFFLOAD_TX_EN) { + dmac_init.name = "DAC DMAC"; + dmac_init.base = param->tx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_tx_dma, &dmac_init); + if(!eng_desc->offload_tx_dma) + return FAILURE; + } + if(param->offload_config & OFFLOAD_RX_EN) { + dmac_init.name = "ADC DMAC"; + dmac_init.base = param->rx_dma_baseaddr; + axi_dmac_init(&eng_desc->offload_rx_dma, &dmac_init); + if(!eng_desc->offload_rx_dma) + return FAILURE; + } + + return SUCCESS; +} + +/** + * @brief Initiate a SPI transfer in offload mode + * + * @param desc Decriptor containing SPI interface parameters + * @param msg Offload message that get's to be transferred + * @param no_samples Number of time the messages will be transferred + * @return int32_t This function always returns SUCCESS + */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples) +{ + struct spi_engine_msg transfer; + struct spi_engine_desc *eng_desc; + uint32_t i; + uint8_t word_length; + + eng_desc = desc->extra; + + /* Check if offload is disabled */ + if(!((eng_desc->offload_config & OFFLOAD_TX_EN) | + (eng_desc->offload_config & OFFLOAD_RX_EN))) + return FAILURE; + + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 1); + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_RESET(0), 0); + + eng_desc->offload_tx_len = 0; + eng_desc->offload_rx_len = 0; + + transfer.cmds = (spi_engine_cmd_queue*)malloc(sizeof(*transfer.cmds)); + + if (!transfer.cmds) + return -1; + + transfer.tx_buf = msg.commands_data; + + /* Load the commands into the message */ + transfer.cmds->next = NULL; + transfer.cmds->cmd = msg.commands[0]; + i = 1; + while(i < msg.no_commands) { + spi_engine_queue_add_cmd(&transfer.cmds, msg.commands[i++]); + + } + + spi_engine_transfer_message(desc, &transfer); + + /* Start transfer */ + spi_engine_write(eng_desc, SPI_ENGINE_REG_OFFLOAD_CTRL(0), 0x0001); + + word_length = spi_get_word_length(eng_desc); + if(eng_desc->offload_config & OFFLOAD_TX_EN) { + struct axi_dma_transfer tx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = eng_desc->cyclic, + // Address of data source + .src_addr = (uintptr_t)msg.tx_addr, + // Address of data destination + .dest_addr = 0 + }; + axi_dmac_transfer_start(eng_desc->offload_tx_dma, &tx_transfer); + } + + if(eng_desc->offload_config & OFFLOAD_RX_EN) { + struct axi_dma_transfer rx_transfer = { + // Number of bytes to write/read + .size = word_length * eng_desc->offload_tx_len * no_samples, + // Transfer done flag + .transfer_done = 0, + // Signal transfer mode + .cyclic = NO, + // Address of data source + .src_addr = 0, + // Address of data destination + .dest_addr = (uintptr_t)msg.rx_addr + }; + axi_dmac_transfer_start(eng_desc->offload_rx_dma, &rx_transfer); + axi_dmac_transfer_wait_completion(eng_desc->offload_rx_dma, 500); + } + + usleep(1000); + + spi_engine_queue_free(&transfer.cmds); + + return SUCCESS; +} + +/** + * @brief Free the resources allocated by spi_init(). + * + * @param desc Decriptor containing SPI interface parameters + * @return int32_t This function allways returns SUCCESS + */ +int32_t spi_engine_remove(struct spi_desc *desc) +{ + struct spi_engine_desc *eng_desc; + + eng_desc = desc->extra; + + if(eng_desc->offload_config & OFFLOAD_TX_EN) + axi_dmac_remove(eng_desc->offload_tx_dma); + if(eng_desc->offload_config & OFFLOAD_RX_EN) + axi_dmac_remove(eng_desc->offload_rx_dma); + free(desc->extra); + free(desc); + + return SUCCESS; +} diff --git a/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.h b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.h new file mode 100644 index 0000000..9e6887e --- /dev/null +++ b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine.h @@ -0,0 +1,229 @@ +/******************************************************************************* + * @file spi_engine.h + * @brief Header file of SPI Engine core features. + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_H +#define SPI_ENGINE_H + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include "spi_engine_private.h" +#include "../axi_dmac/axi_dmac.h" +#include "../../platform/xilinx_spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define OFFLOAD_DISABLED 0x00 +#define OFFLOAD_TX_EN BIT(0) +#define OFFLOAD_RX_EN BIT(1) +#define OFFLOAD_TX_RX_EN OFFLOAD_TX_EN | OFFLOAD_RX_EN + +#define SPI_ENGINE_MSG_QUEUE_END 0xFFFFFFFF + +/* Spi engine commands */ +#define WRITE(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_W << 8) | no_bytes) + +#define READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_R << 8) | no_bytes) + +#define WRITE_READ(no_bytes) ((SPI_ENGINE_INST_TRANSFER << 12) |\ + (SPI_ENGINE_INSTRUCTION_TRANSFER_RW << 8) | no_bytes) + +#define SLEEP(time) SPI_ENGINE_CMD_SLEEP(time & 0xF) + +/* The delay and chip select parmeters are passed over the engine descriptor +and will be used inside the function call */ +#define CS_HIGH SPI_ENGINE_CMD_ASSERT(0x01, 0xFF) +#define CS_LOW SPI_ENGINE_CMD_ASSERT(0x01, 0x00) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct spi_engine_init_param + * @brief Structure containing the init parameters needed by the SPI engine + */ +struct spi_engine_init_param { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint32_t cs_delay; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; +}; + + +/** + * @struct spi_engine_desc + * @brief Structure representing an SPI engine device + */ +struct spi_engine_desc { + /** SPI engine reference clock */ + uint32_t ref_clk_hz; + /** Type of implementation */ + enum xil_spi_type type; + /** Pointer to a DMAC used in transmission */ + struct axi_dmac *offload_tx_dma; + /** Pointer to a DMAC used in reception */ + struct axi_dmac *offload_rx_dma; + /** Transfer mode for Tx DMAC */ + enum cyclic_transfer cyclic; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; + /** Number of words that the module has to send */ + uint8_t offload_tx_len; + /** Number of words that the module has to receive */ + uint8_t offload_rx_len; + /** Base address where the HDL core is situated */ + uint32_t spi_engine_baseaddr; + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** Delay between the CS toggle and the start of SCLK */ + uint8_t cs_delay; + /** Clock divider used in transmission delays */ + uint32_t clk_div; + /** Data with of one SPI transfer ( in bits ) */ + uint8_t data_width; + /** The maximum data width supported by the engine */ + uint8_t max_data_width; +}; + + +/** + * @struct spi_engine_offload_init_param + * @brief Structure containing the init parameters needed by the offload module + */ +struct spi_engine_offload_init_param { + /** Base address where the RX DMAC core is situated */ + uint32_t rx_dma_baseaddr; + /** Base address where the TX DMAC core is situated */ + uint32_t tx_dma_baseaddr; + /** DMAC flags - if not initialized, the default value is DMA_CYCLIC */ + uint32_t *dma_flags; + /** Offload's module transfer direction : TX, RX or both */ + uint8_t offload_config; +}; + +/** + * @struct spi_engine_offload_message + * @brief Structure representing an offload message + */ +struct spi_engine_offload_message { + /** Pointer to the SPI engine commands buffer that will be sent. + * The available commands can be found at: + * https://wiki.analog.com/resources/fpga/peripherals/spi_engine/ + */ + uint32_t *commands; + /** Length of the SPI engine commands buffer */ + uint32_t no_commands; + /** Pointer of the data that will be sent over spi */ + uint32_t *commands_data; + /** The address where the data that will be transmitted is situated */ + uint32_t tx_addr; + /** The address where the data that will be received is situated */ + uint32_t rx_addr; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/** + * @brief Spi engine platform specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/* Write SPI Engine's axi registers */ +int32_t spi_engine_write(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t reg_data); + +/* Read SPI Engine's axi registers */ +int32_t spi_engine_read(struct spi_engine_desc *desc, + uint32_t reg_addr, + uint32_t *reg_data); +/* Initialize the SPI engine device */ +int32_t spi_engine_init(struct spi_desc **desc, + const struct spi_init_param *param); + +/* Write and read data over SPI using the SPI engine */ +int32_t spi_engine_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number); + +/* Write and read data over SPI using the SPI engine in 3-wire mode */ +int32_t spi_engine_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); +/* Free the resources used by the SPI engine device */ +int32_t spi_engine_remove(struct spi_desc *desc); + +/* Initialize the SPI engine offload module */ +int32_t spi_engine_offload_init(struct spi_desc *desc, + const struct spi_engine_offload_init_param *param); + +/* Write and read data over SPI using the offload module */ +int32_t spi_engine_offload_transfer(struct spi_desc *desc, + struct spi_engine_offload_message msg, + uint32_t no_samples); + +/* Set SPI transfer width */ +int32_t spi_engine_set_transfer_width(struct spi_desc *desc, + uint8_t data_wdith); + +/* Set SPI transfer speed */ +void spi_engine_set_speed(struct spi_desc *desc, + uint32_t speed_hz); + +#endif // SPI_ENGINE_H diff --git a/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine_private.h b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine_private.h new file mode 100644 index 0000000..571a847 --- /dev/null +++ b/df_datalink_ge/src/drivers/axi_core/spi_engine/spi_engine_private.h @@ -0,0 +1,154 @@ +/******************************************************************************* + * @file spi_engine_private.h + * @brief Private definitions of the SPI Engine + * @author Sergiu Cuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef SPI_ENGINE_PRIVATE_H +#define SPI_ENGINE_PRIVATE_H + +#include +#include + +#include "spi.h" +#include "util.h" + +/******************************************************************************/ +/*************************** Spi Engine registers *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_REG_VERSION 0x00 +#define SPI_ENGINE_REG_DATA_WIDTH 0x0C +#define SPI_ENGINE_REG_RESET 0x40 +#define SPI_ENGINE_REG_INT_ENABLE 0x80 +#define SPI_ENGINE_REG_INT_PENDING 0x84 +#define SPI_ENGINE_REG_INT_SOURCE 0x88 +#define SPI_ENGINE_REG_SYNC_ID 0xC0 +#define SPI_ENGINE_REG_CMD_FIFO_ROOM 0xD0 +#define SPI_ENGINE_REG_SDO_FIFO_ROOM 0xD4 +#define SPI_ENGINE_REG_SDI_FIFO_LEVEL 0xD8 +#define SPI_ENGINE_REG_CMD_FIFO 0xE0 +#define SPI_ENGINE_REG_SDO_DATA_FIFO 0xE4 +#define SPI_ENGINE_REG_SDI_DATA_FIFO 0xE8 +#define SPI_ENGINE_REG_SDI_DATA_FIFO_PEEK 0xEC + +/******************************************************************************/ +/************************ Spi Engine register parameters **********************/ +/******************************************************************************/ + +#define SPI_ENGINE_INST_TRANSFER 0x00 +#define SPI_ENGINE_INST_ASSERT 0x01 +#define SPI_ENGINE_INST_CONFIG 0x02 +#define SPI_ENGINE_INST_SYNC_SLEEP 0x03 +#define SPI_ENGINE_INST_MISC 0x03 +#define SPI_ENGINE_CMD_REG_CLK_DIV 0x00 +#define SPI_ENGINE_CMD_REG_CONFIG 0x01 +#define SPI_ENGINE_CMD_DATA_TRANSFER_LEN 0x02 +#define SPI_ENGINE_MISC_SYNC 0x00 +#define SPI_ENGINE_MISC_SLEEP 0x01 +#define SPI_ENGINE_SYNC_TRANSFER_BEGIN BIT(1) +#define SPI_ENGINE_SYNC_TRANSFER_END BIT(2) +#define SPI_ENGINE_INT_CMD_ALMOST_EMPTY BIT(0) +#define SPI_ENGINE_INT_SDO_ALMOST_EMPTY BIT(1) +#define SPI_ENGINE_INT_SDI_ALMOST_FULL BIT(2) +#define SPI_ENGINE_INT_SYNC BIT(3) +#define SPI_ENGINE_OFFLOAD_CTRL_ENABLE BIT(0) +#define SPI_ENGINE_OFFLOAD_STATUS_ENABLED BIT(0) +#define SPI_ENGINE_CONFIG_CPHA BIT(0) +#define SPI_ENGINE_CONFIG_CPOL BIT(1) +#define SPI_ENGINE_CONFIG_3WIRE BIT(2) +#define SPI_ENGINE_VERSION_MAJOR(x) ((x >> 16) & 0xff) +#define SPI_ENGINE_VERSION_MINOR(x) ((x >> 8) & 0xff) +#define SPI_ENGINE_VERSION_PATCH(x) (x & 0xff) + +/******************************************************************************/ +/**************************** Spi Engine commands *****************************/ +/******************************************************************************/ + +#define SPI_ENGINE_INSTRUCTION_TRANSFER_W 0x01 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_R 0x02 +#define SPI_ENGINE_INSTRUCTION_TRANSFER_RW 0x03 + +#define SPI_ENGINE_REG_OFFLOAD_CTRL(x) (0x100 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_STATUS(x) (0x104 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_RESET(x) (0x108 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_CMD_MEM(x) (0x110 + (0x20 * x)) +#define SPI_ENGINE_REG_OFFLOAD_SDO_MEM(x) (0x114 + (0x20 * x)) + +#define SPI_ENGINE_CMD(inst, arg1, arg2) \ + (((inst & 0x03) << 12) | \ + ((arg1 & 0x03) << 8) | arg2 ) + +#define SPI_ENGINE_CMD_TRANSFER(readwrite, n) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_TRANSFER, \ + (readwrite), (n)) + +#define SPI_ENGINE_CMD_ASSERT(delay, cs) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_ASSERT, \ + (delay), (cs)) + +#define SPI_ENGINE_CMD_CONFIG(reg, val) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_CONFIG, \ + (reg), (val)) + +#define SPI_ENGINE_CMD_SLEEP(delay) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SLEEP, \ + (delay)) + +#define SPI_ENGINE_CMD_SYNC(id) \ + SPI_ENGINE_CMD(SPI_ENGINE_INST_MISC, \ + SPI_ENGINE_MISC_SYNC, \ + (id)) + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +typedef struct spi_engine_cmd_queue { + uint32_t cmd; + struct spi_engine_cmd_queue *next; +} spi_engine_cmd_queue; + +typedef struct spi_engine_msg { + uint32_t *tx_buf; + uint32_t *rx_buf; + uint32_t tx_length; + uint32_t rx_length; + struct spi_engine_cmd_queue *cmds; +} spi_engine_msg; + +#endif // SPI_ENGINE_PRIVATE_H diff --git a/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.c b/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.c new file mode 100644 index 0000000..7894fd6 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.c @@ -0,0 +1,783 @@ +/** + * \file ad9528.c + * \brief Contains source code for configuring and initializing AD9528 clock device + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license. +* +*/ + +#include +#include +#include "ad9528.h" +#include "../../../include/error.h" + +static uint32_t _desired_time_to_elapse_ms = 0; + +/** + * \brief Write data to a register + */ +int32_t AD9528_spiWriteByte(ad9528Device_t *device, uint16_t addr, + uint8_t data) +{ + uint8_t buf[3]; + int32_t status; + + buf[0] = (addr >> 8) & 0x7F; + buf[1] = addr & 0xFF; + buf[2] = data; + status = spi_write_and_read_3wire(device->spi_desc, + buf, NULL, 3, 0); + + return status; +} + +/** + * \brief Read data from a register + */ +int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr, + uint8_t *readdata) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t status; + + tx_buf[0] = 0x80 | addr >> 8; + tx_buf[1] = addr & 0xFF; + + status = spi_write_and_read_3wire(device->spi_desc, + tx_buf, rx_buf, 2, 1); + + *readdata = rx_buf[0]; + + return status; +} + +/** + * \brief Modify a field of bits from a register + */ +int32_t AD9528_spiWriteField(ad9528Device_t *device, + uint16_t addr, uint8_t fieldVal, uint8_t mask, uint8_t startBit) +{ + int32_t errVal; + uint8_t readVal; + + errVal = AD9528_spiReadByte(device, addr, &readVal); + if (errVal < 0) + return errVal; + + readVal = (readVal & ~mask) | ((fieldVal << startBit) & mask); + + return AD9528_spiWriteByte(device, addr, readVal); +} + +/** + * \brief Set the desired timeout value + */ +int32_t AD9528_setTimeout_ms(uint32_t timeOut_ms) +{ + _desired_time_to_elapse_ms = timeOut_ms; + + return SUCCESS; +} + +/** + * \brief Verify if the desired time has elapsed + */ +int32_t AD9528_hasTimeoutExpired() +{ + udelay(1000); + + _desired_time_to_elapse_ms--; + if (_desired_time_to_elapse_ms > 0) + return SUCCESS; + + return FAILURE; +} + +/** + * \brief Performs a hard reset on the AD9528 DUT + * + * Dependencies + * - device->spiSettings->chipSelectIndex + * + * \param device is structure pointer to the AD9528 data structure containing settings + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +int32_t AD9528_resetDevice(ad9528Device_t *device) +{ + gpio_direction_output(device->gpio_resetb, 0); + mdelay(100); + gpio_direction_output(device->gpio_resetb, 1); + mdelay(100); + + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x81); + mdelay(100); + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x00); + mdelay(100); + + return SUCCESS; +} + +/** + * \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc). + * + * This function will use the settings in the device->spiSettings structure + * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, + * and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0). + * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and + * longInstructionWord =1 to use a 16bit instruction word. + * + * Dependencies + * - writes device->spiSettings->CPHA = 0 + * - writes device->spiSettings->CPOL = 0 + * - writes device->spiSettings->longInstructionWord = 1 + * + * - device->spiSettings->MSBFirst + * - device->spiSettings->enSpiStreaming + * - device->spiSettings->autoIncAddrUp + * - device->spiSettings->fourWireMode + * + * \param device is structure pointer to the AD9528 data structure containing settings + * + * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail + */ +int32_t AD9528_setSpiSettings(ad9528Device_t *device) +{ + uint8_t spiReg = 0; + + device->spiSettings->CPHA = 0; + device->spiSettings->CPOL = 0; + device->spiSettings->longInstructionWord = 1; + + if (device->spiSettings->MSBFirst == 0) { + spiReg |= 0x42; /* SPI bit is 1=LSB first */ + } + + if (device->spiSettings->autoIncAddrUp > 0) { + spiReg |= 0x24; + } + + if (device->spiSettings->fourWireMode > 0) { + spiReg |= 0x18; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg); + + if (device->spiSettings->enSpiStreaming > 0) { + /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); + } else { + /* Force single instruction mode */ + AD9528_spiWriteByte(device, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80); + } + + return SUCCESS; +} + +/** + * \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure + * + * This function inits the AD9528 device data structure with defaults that + * are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will + * modify the contents of the AD9528 device data structure. + * + * Dependencies + * - spi->chipSelectIndex + * - spi + * + * \param device Pointer to the AD9528 device data structure to initialize + * \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528 + * \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input + * \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail +*/ +int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device, + uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, + uint32_t outputDeviceClock_Hz) +{ +// uint16_t chDiv; +// uint8_t i = 0; +// +// uint32_t pll1PfdFreq_Hz = 0; +// uint8_t pll1Ndiv = 0; +// uint8_t validPll1DivSetting = 0; +// uint8_t refAdiv = 1; +// +// +// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */ +// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */ +// uint32_t pll2InputFreq_Hz = 0; +// uint64_t pll2VcoFreq_Hz = 0; +// uint16_t pll2NdivStart = 0; +// uint8_t validPll2DivSetting = 0; +// uint64_t chDivU64 = 0; +// +// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL; +// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL; + +// struct spi_init_param spi_param; +// int32_t status; +// +// status = gpio_get(&device->gpio_resetb, CLK_RESETB); +// status |= gpio_get(&device->gpio_sysref_req, ADRV_SYSREF_REQ); +// +// spi_param.id = 0; +// spi_param.mode = SPI_MODE_0; +// spi_param.chip_select = CLK_CS; +// status |= spi_init(&device->spi_desc, &spi_param); +// +// if (status != SUCCESS) +// return FAILURE; + + /******************************************************************* + * PLL1 Settings + ******************************************************************* + */ + + /* find valid PLL1 Ndiv and REFA div */ +// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) { +// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv; +// +// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) && +// (pll1PfdFreq_Hz <= refAFrequency_Hz) && +// (refAFrequency_Hz % pll1PfdFreq_Hz == 0) +// ) { +// validPll1DivSetting = 1; +// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ; +// break; +// } +// } +// +// if (validPll1DivSetting == 0) { +// return FAILURE; +// } + +// device->pll1Settings->nDivider = +// pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate +// device->pll1Settings->refA_bufferCtrl = +// DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refA_Divider = refAdiv; +// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz; +// device->pll1Settings->refB_bufferCtrl = +// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->refB_Divider = 1; +// device->pll1Settings->refB_Frequency_Hz = 0; +// device->pll1Settings->vcxoBufferCtrl = +// NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz; + + /******************************************************************* + * PLL2 Settings + ******************************************************************* + */ + + /******************************************************************* + * Output Distribution Settings + * 9369CE02A uses the following clock outputs + * OUT 1: FPGA REFCLK + * OUT 3: FPGA SYSREF + * OUT 12: DUT SYSREF + * OUT 13: DUT REFCLK + ******************************************************************* + */ + + /* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use + * PLL 1 output (VCXO Frequency) with no scaling + */ +// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz; +// validPll2DivSetting = 0; + + /* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/ +// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) { +// +// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz); +// /* find valid PLL2 Ndiv (1-256) */ +// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) { +// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv); +// +// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) { +// /* Continue to next PLL2 N div */ +// continue; +// } else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) { +// /* Break to next PLL2 RF div */ +// break; +// } +// +// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) { +// +// device->pll2Settings->rfDivider = pll2RfDiv; +// device->pll2Settings->n2Divider = pll2Ndiv; +// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv; +// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz); +// +// if ((chDivU64 < 1) || (chDivU64 > 256)) { +// return FAILURE; +// } else { +// chDiv = (uint16_t)(chDivU64); +// } +// +// validPll2DivSetting = 1; +// break; +// } +// } +// +// if (validPll2DivSetting == 1) { +// break; +// } +// } +// +// if (validPll2DivSetting == 0) { +// return FAILURE; +// } +// +// device->outputSettings->outPowerDown = (uint16_t)( +// ~0x318A); //enable outputs 13,12,8,7,3 and 1 +// +// for (i=0; i<14; i++) { +// device->outputSettings->outSource[i] = +// CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT +// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL +// device->outputSettings->outChannelDiv[i] = chDiv; +// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz; +// device->outputSettings->outAnalogDelay[i] = 0; +// device->outputSettings->outDigitalDelay[i] = 0; +// } +// +// +// device->outputSettings->outSource[3] = SYSREF; +// device->outputSettings->outSource[7] = SYSREF; +// device->outputSettings->outSource[12] = SYSREF; +// +// +// device->sysrefSettings->sysrefDivide = +// 512; //SYSREF frequency = VCXO / 2 / sysrefDivde +// device->sysrefSettings->sysrefNshotMode = +// ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 +// device->sysrefSettings->sysrefPatternMode = +// CONTINUOUS; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3 +// device->sysrefSettings->sysrefPinBufferMode = +// DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +// device->sysrefSettings->sysrefPinEdgeMode = +// LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3 +// device->sysrefSettings->sysrefRequestMethod = PIN; //SPI=0,PIN=1 +// device->sysrefSettings->sysrefSource = +// INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2 + + return SUCCESS; +} + +int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device) +{ + int ret = SUCCESS; + ad9528Device_t *dev; + + dev = (ad9528Device_t *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_device->spi_init); + ret |= gpio_get(&dev->gpio_resetb, init_device->gpio_init_resetb); + ret |= gpio_get(&dev->gpio_sysref_req, init_device->gpio_init_sysref_req); + + gpio_direction_output(dev->gpio_resetb, 0); + gpio_direction_output(dev->gpio_sysref_req, 0); + + AD9528_resetDevice(dev); + + dev->spiSettings = init_device->spiSettings; + dev->pll1Settings = init_device->pll1Settings; + dev->pll2Settings = init_device->pll2Settings; + dev->outputSettings = init_device->outputSettings; + dev->sysrefSettings = init_device->sysrefSettings; + + *device = dev; + + return ret; +} + +/** + * \brief Initializes the AD9528 by writing all SPI registers + * + * Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with + * a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz. + * The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M. + * Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz + * SYNC(SYSREF) pulses output at rate of 120kHz + * + * Dependencies + * - All parameters in device structure + * + * \param device is structure pointer to AD9528 clock device structure + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + */ +int32_t AD9528_config(ad9528Device_t + *device) //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled. +{ + uint8_t pll2_Adiv=0; + uint8_t pll2_Bdiv=0; + uint8_t reg108=0; + uint8_t reg109=0x4; + uint8_t i = 0; + uint8_t j = 0; + uint8_t reg508; + int32_t retval = SUCCESS; + + retval = AD9528_setSpiSettings(device); + if (retval != SUCCESS) { + return retval; + } + + /********************************************************************** + * Configure PLL1 + ********************************************************************** + */ + + AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_LSB, + device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_A_DIVIDER_MSB, + (device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_LSB, + device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_REF_B_DIVIDER_MSB, + (device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_LSB, + device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_N_DIV_MSB, + (device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CHARGEPUMP, + 0x0A); //PLL1 Charge Pump control 1 + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_CP_CTRL2, + 0x03); //PLL1 Charge Pump control 2 + + switch (device->pll1Settings->refA_bufferCtrl) { + case DISABLED: + reg108 &= ~0x28; + reg109 &= ~0x01; + break; //clear all REFA enable bits + case SINGLE_ENDED: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //Set REFA receiver enable, clear REFA SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x08; + reg108 &= ~0x10; + reg109 |= 0x01; + break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input + case DIFFERENTIAL: + reg108 |= 0x28; + reg109 &= ~0x01; + break; + default: + reg108 |= 0x08; + reg109 &= ~0x01; + break; //default to single ended case + } + switch (device->pll1Settings->refB_bufferCtrl) { + case DISABLED: + reg108 &= ~0x50; + reg109 &= ~0x02; + break; //clear all REFB enable bits + case SINGLE_ENDED: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //Set REFB receiver enable, clear REFB SE negative input enable + case NEG_SINGLE_ENDED: + reg108 |= 0x10; + reg108 &= ~0x40; + reg109 |= 0x02; + break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input + case DIFFERENTIAL: + reg108 |= 0x50; + reg109 &= ~0x02; + break; + default: + reg108 |= 0x10; + reg109 &= ~0x02; + break; //default to single ended case + } + switch (device->pll1Settings->vcxoBufferCtrl) { + case DISABLED: + reg108 &= ~0x03; + reg108 |= 0x04; + break; //power down VCXO input + case SINGLE_ENDED: + reg108 &= ~0x07; + break; //Clear VCXO receiver power down, defaults to Single ended mode + case NEG_SINGLE_ENDED: + reg108 &= ~0x07; + reg108 |= 0x02; + break; //Clear VCXO power down, enable Negative single ended mode[1] + case DIFFERENTIAL: + reg108 &= ~0x07; + reg108 |= 0x01; + break; //Clear VCXO power down, enable differential input buffer[0] + default: + reg108 &= ~0x07; + break; //default to positive single ended case + } + + + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS1, + reg108); //Input receiver settings (single ended or differential clock inputs) + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS2, + reg109); //Input receiver settings + AD9528_spiWriteByte(device, AD9528_ADDR_INPUT_RECEIVERS3, + 0x0A); //Reference selection mode + AD9528_spiWriteByte(device, AD9528_ADDR_PLL1_FASTLOCK, + 0x00); //Disable Fast lock + + /********************************************************************** + * Configure PLL2 + ********************************************************************** + */ + pll2_Bdiv = device->pll2Settings->totalNdiv / 4; + pll2_Adiv = device->pll2Settings->totalNdiv % 4; + + if (pll2_Adiv > 3) { //A div valid range (0 to 3) + return FAILURE; + } + if (pll2_Bdiv < 3 || pll2_Bdiv > 63) { + return FAILURE; + } + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CHARGEPUMP, + 0xE6); //PLL2 Charge Pump[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_N_DIV, + ((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL + + if (device->pll2Settings->rfDivider < 3 + || device->pll2Settings->rfDivider > 5) { + return FAILURE; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_VCO_DIV, + device->pll2Settings->rfDivider); //VCO divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL1, + 0x3A); //PLL2 Loop filter [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_LF_CTRL2, + 0x00); //PLL2 Loop filter [8] + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_RDIV, 0x01); //R divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_CHDIV, + (device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider) + -1 ); //Replica channel divider: Ndivider = rfDivider * R divider + AD9528_spiWriteByte(device, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE, + 0x00); //Replica Channel Divider phase + + /********************************************************************** + * Configure Output Distribution + ********************************************************************** + */ + for (i=0; i<14; i=i+1) { + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL1 + j, + ((device->outputSettings->outSource[i] & 0x7) << 5) | + (device->outputSettings->outAnalogDelay[i] & 0x1F)); + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CTRL2 + j, + ((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) | + (device->outputSettings->outDigitalDelay[i] & 0x3F)); + AD9528_spiWriteByte(device, AD9528_ADDR_CH_OUT0_CHDIV + j, + device->outputSettings->outChannelDiv[i]-1); + j = j+3; + } + + AD9528_spiWriteByte(device, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs + AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8] + AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL1, + 0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution + AD9528_spiWriteByte(device, AD9528_ADDR_EN_OUTPUT_PATH_SEL2, + 0x00); //Bypass SYSREF resample [13:7] + + /********************************************************************** + * Configure SYSREF operation + ********************************************************************** + */ + AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_LSB, + device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_SYSERF_DIV_MSB, + (device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0] + + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL3, + ((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) | + ((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) ); + + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, + ((device->sysrefSettings->sysrefSource & 0x03) << 6) | + ((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) | + ((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) ); + + if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x00); //enable positive singled ended input + } else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x02); //enable negative singled ended input + } else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x01); //enable differential input buffer + } else { + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL5, + 0x04); //power down input buffer for external SYSREF + } + + /********************************************************************** + * Power down control + ********************************************************************** + */ + + if (device->pll1Settings->bypassPll1 > 0) { + AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL, + 0x14);// power up PLL2 and output distribution, power down PLL1 + } else { + AD9528_spiWriteByte(device, AD9528_ADDR_POWERDOWN_CTRL, + 0x10);// power up PLL1, PLL2 and output distribution + } + + AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN1, + device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_CH_POWERDOWN2, + ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] + AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES1, + 0xFF); //LDO enable per output channel [7:0] + AD9528_spiWriteByte(device, AD9528_ADDR_LDO_ENABLES2, + 0xFF); //LDO enable per output channel [15:8] + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS0_CTRL, + 0x07); //STATUS 0 outputs REFA present + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS1_CTRL, + 0x01); //STATUS 1 outputs PLL1 and PLL2 locked + AD9528_spiWriteByte(device, AD9528_ADDR_STATUS_OE, + 0x0C);// Make Status0 and Status1 outputs after reset. + + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + AD9528_setTimeout_ms(1000); + + do { + AD9528_spiReadByte(device, AD9528_ADDR_STATUS_READBACK0, ®508); + if(AD9528_hasTimeoutExpired() > 0) { + return FAILURE; + } + } while((reg508 & 0x26) != 0x26); + + return SUCCESS; +} + + +/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528. +/*******************************************************************************//** + * Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF + * that are current configured in the AD9528. This could be a single pulse, + * multiple pulses, or continuous pulses. + * Dependencies + * - device->spiSettings + * - device->sysrefSettings->sysrefPatternMode + * + * \param device is structure pointer to AD9528 clock device structure + * \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF. + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF) +{ + uint8_t _enableSYSREF=0; + + if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) { + _enableSYSREF = 1; + } else { + _enableSYSREF = 0; + } + + AD9528_spiWriteField(device, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01, + 0x00); //Set SPI SYSREF request bit + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + return SUCCESS; +} + +/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode) +/*******************************************************************************//** + * NOTE: this function will update the device structure with the parameter values passed + * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, + * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. + * + * Dependencies + * - device->spiSettings + * + * \param device is structure pointer to AD9528 clock device structure + * \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out + * \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP + * \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 + * + * \return Returns enum ADI_ERR, 0=pass, >0 = fail + ***********************************************************************************/ +int32_t AD9528_setupSYSREF(ad9528Device_t *device, + uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, + sysrefNshotMode_t nShotPulses) +{ + uint8_t reg403=0; + + device->sysrefSettings->sysrefPatternMode = sysrefPatternMode; + device->sysrefSettings->sysrefNshotMode = nShotPulses; + device->sysrefSettings->sysrefDivide = divideFromPll1Out >> + 1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide + + AD9528_spiReadByte(device, AD9528_ADDR_SYSREF_CTRL4, ®403); + + reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on. + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, reg403); + + reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields + reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1); + AD9528_spiWriteByte(device, AD9528_ADDR_SYSREF_CTRL4, + reg403); //update internal sysref pattern mode and Nshot mode (number of pulses) + + //SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF + AD9528_spiWriteByte(device, AD9528_ADDR_IO_UPDATE, + 0x01); //IO update to make all these settings valid in the 9528 + + + return SUCCESS; +} + +int32_t AD9528_sysrefReq(ad9528Device_t *device, + ad9528SysrefReqMode_t mode) +{ + if (mode == SYSREF_CONT_ON) + gpio_direction_output(device->gpio_sysref_req, 1); + else if (mode == SYSREF_CONT_OFF) + gpio_direction_output(device->gpio_sysref_req, 0); + else if (mode == SYSREF_PULSE) { + gpio_direction_output(device->gpio_sysref_req, 1); + mdelay(1); + gpio_direction_output(device->gpio_sysref_req, 0); + } else + return FAILURE; + + return SUCCESS; +} + +/** + * \brief Free the allocated resources + */ +int32_t AD9528_remove(ad9528Device_t *device) +{ + int32_t status; + + status = gpio_remove(device->gpio_resetb); + status |= gpio_remove(device->gpio_sysref_req); + status |= spi_remove(device->spi_desc); + + return SUCCESS; +} diff --git a/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.h b/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.h new file mode 100644 index 0000000..9f89655 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/ad9528/ad9528.h @@ -0,0 +1,245 @@ +/** + * \file ad9528.h + * \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c + */ + +/** +* \page Disclaimer Legal Disclaimer +* Copyright 2015-2017 Analog Devices Inc. +* Released under the AD9371 API license. +* +*/ + +#ifndef _AD9528_H_ +#define _AD9528_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/* AD9528 SPI Address defines */ +#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000 +#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001 +#define AD9528_ADDR_IO_UPDATE 0x00F + +#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100 +#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101 +#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102 +#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103 +#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104 +#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105 +#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106 +#define AD9528_ADDR_PLL1_CP_CTRL2 0x107 +#define AD9528_ADDR_INPUT_RECEIVERS1 0x108 +#define AD9528_ADDR_INPUT_RECEIVERS2 0x109 +#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A +#define AD9528_ADDR_PLL1_FASTLOCK 0x10B + +#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200 +#define AD9528_ADDR_PLL2_N_DIV 0x201 +#define AD9528_ADDR_PLL2_CTRL 0x202 +#define AD9528_ADDR_PLL2_VCO_CTRL 0x203 +#define AD9528_ADDR_PLL2_VCO_DIV 0x204 +#define AD9528_ADDR_PLL2_LF_CTRL1 0x205 +#define AD9528_ADDR_PLL2_LF_CTRL2 0x206 +#define AD9528_ADDR_PLL2_RDIV 0x207 +#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208 +#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209 + +#define AD9528_ADDR_CH_OUT0_CTRL1 0x300 +#define AD9528_ADDR_CH_OUT0_CTRL2 0x301 +#define AD9528_ADDR_CH_OUT0_CHDIV 0x302 +#define AD9528_ADDR_OUTPUT_SYNC 0x32A +#define AD9528_ADDR_MASK_SYNC1 0x32B +#define AD9528_ADDR_MASK_SYNC2 0x32C +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D +#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E + +#define AD9528_ADDR_SYSERF_DIV_LSB 0x400 +#define AD9528_ADDR_SYSERF_DIV_MSB 0x401 +#define AD9528_ADDR_SYSREF_CTRL3 0x402 +#define AD9528_ADDR_SYSREF_CTRL4 0x403 +#define AD9528_ADDR_SYSREF_CTRL5 0x404 + +#define AD9528_ADDR_POWERDOWN_CTRL 0x500 +#define AD9528_ADDR_CH_POWERDOWN1 0x501 +#define AD9528_ADDR_CH_POWERDOWN2 0x502 +#define AD9528_ADDR_LDO_ENABLES1 0x503 +#define AD9528_ADDR_LDO_ENABLES2 0x504 +#define AD9528_ADDR_STATUS0_CTRL 0x505 +#define AD9528_ADDR_STATUS1_CTRL 0x506 +#define AD9528_ADDR_STATUS_OE 0x507 +#define AD9528_ADDR_STATUS_READBACK0 0x508 +#define AD9528_ADDR_STATUS_READBACK1 0x509 + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +///Enum to select what source outputs from each AD9528 output channel +typedef enum { + AD9528_CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency + SYSREF = 2, + INV_PLL1_OUTPUT = 5 //VCXO inverted +} ad9528outSourceSel_t; + +///Enum to select what output buffer standard is used for the clock outputs +typedef enum { + AD9528_LVDS = 0, AD9528_LVDS_BOOST = 1, AD9528_HSTL = 2 +} ad9528outBufferControl_t; + +///Enum to select the clock input buffer mode. +typedef enum { + DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL +} ad9528RefBuffer_t; + +/// Structure to hold AD9528 PLL1 settings +typedef struct { + uint32_t refA_Frequency_Hz; + uint16_t refA_Divider; + ad9528RefBuffer_t refA_bufferCtrl; + + uint32_t refB_Frequency_Hz; + uint16_t refB_Divider; + ad9528RefBuffer_t refB_bufferCtrl; + + uint32_t vcxo_Frequency_Hz; + ad9528RefBuffer_t vcxoBufferCtrl; + + uint16_t nDivider; + uint8_t bypassPll1; +} ad9528pll1Settings_t; + +/// Structure to hold AD9528 PLL2 settings +typedef struct { + uint8_t rfDivider; //VCO divider: Valid range (3,4,5) + uint8_t n2Divider; //PLL2 N2 Divider + uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3) +} ad9528pll2Settings_t; + +/// Structure to hold AD9528 Output Clock settings +typedef struct { + uint16_t outPowerDown; //bit per output, if 1 power down that output. + ad9528outSourceSel_t + outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT + ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL + uint8_t outAnalogDelay[14]; //5 bits + uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency + uint8_t outChannelDiv[14]; //8 bit channel divider + uint32_t outFrequency_Hz[14]; //output clock frequency per clock output +} ad9528outputSettings_t; + +///Enum to select the SYSREF output source +typedef enum { + EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2 +} sysrefSourceSelection_t; + +///Enum to choose the SYSREF pattern mode. +typedef enum { + NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3 +} sysrefPatternMode_t; + +///Enum to select the SYSREF input pin mode. +typedef enum { + LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3 +} sysrefPinEdgeMode_t; + +///Enum to select the SYSREF output # of pulses for NSHOT mode. +typedef enum { + ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5 +} sysrefNshotMode_t; + +//Enum to select how a SYSREF is requested. +typedef enum { + SPI = 0, PIN = 1 +} sysrefRequestMethod_t; + +/// Structure to hold AD9528 SYSREF output settings +typedef struct { + sysrefRequestMethod_t sysrefRequestMethod; + sysrefSourceSelection_t sysrefSource; + sysrefPinEdgeMode_t sysrefPinEdgeMode; + ad9528RefBuffer_t sysrefPinBufferMode; + sysrefPatternMode_t sysrefPatternMode; + sysrefNshotMode_t sysrefNshotMode; + uint16_t sysrefDivide; + +} ad9528sysrefSettings_t; + +/// Structure to hold AD9528 SPI settings +typedef struct { + uint8_t chipSelectIndex; ///< valid 1~8 + uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation + uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word + uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst + uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1) + uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high + uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput. + uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1 + uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode. + uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */ +} ad9528spiSettings_t; + +/// Structure to hold AD9528 settings +typedef struct { + struct gpio_desc *gpio_resetb; + struct gpio_desc *gpio_sysref_req; + struct spi_desc *spi_desc; + ad9528spiSettings_t *spiSettings; + ad9528pll1Settings_t *pll1Settings; + ad9528pll2Settings_t *pll2Settings; + ad9528outputSettings_t *outputSettings; + ad9528sysrefSettings_t *sysrefSettings; +} ad9528Device_t; + +typedef struct { + struct gpio_init_param *gpio_init_resetb; + struct gpio_init_param *gpio_init_sysref_req; + struct spi_init_param *spi_init; + ad9528spiSettings_t *spiSettings; + ad9528pll1Settings_t *pll1Settings; + ad9528pll2Settings_t *pll2Settings; + ad9528outputSettings_t *outputSettings; + ad9528sysrefSettings_t *sysrefSettings; +} ad9528Init_t; + +typedef enum { + SYSREF_CONT_ON, + SYSREF_CONT_OFF, + SYSREF_PULSE, +} ad9528SysrefReqMode_t; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards +int32_t AD9528_initDeviceDataStruct(ad9528Device_t *device, + uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, + uint32_t outputDeviceClock_Hz); +int32_t AD9528_spiReadByte(ad9528Device_t *device, uint16_t addr, + uint8_t *readdata); + +//AD9528 API functions +int32_t AD9528_hasTimeoutExpired(); +int32_t AD9528_resetDevice(ad9528Device_t *device); +int32_t AD9528_init(ad9528Device_t **device, const ad9528Init_t *init_device); +int32_t AD9528_config(ad9528Device_t + *device); //writes all registers to desired values, leaves clock outputs off. +int32_t AD9528_setupSYSREF(ad9528Device_t *device, + uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, + sysrefNshotMode_t nShotPulses); +int32_t AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF); +int32_t AD9528_sysrefReq(ad9528Device_t *device, + ad9528SysrefReqMode_t mode); +int32_t AD9528_remove(ad9528Device_t *device); + +#endif diff --git a/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.c b/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.c new file mode 100644 index 0000000..2574d9a --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.c @@ -0,0 +1,927 @@ +/***************************************************************************//** + * @file hmc7044.c + * @brief Implementation of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "hmc7044.h" +#include "../../../include/error.h" +#include "../../../include/util.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define HMC7044_WRITE (0 << 15) +#define HMC7044_READ (1 << 15) +#define HMC7044_CNT(x) (((x) - 1) << 13) +#define HMC7044_ADDR(x) ((x) & 0xFFF) + +/* Global Control */ +#define HMC7044_REG_SOFT_RESET 0x0000 +#define HMC7044_SOFT_RESET BIT(0) + +#define HMC7044_REG_REQ_MODE_0 0x0001 +#define HMC7044_RESEED_REQ BIT(7) +#define HMC7044_HIGH_PERF_DISTRIB_PATH BIT(6) +#define HMC7044_HIGH_PERF_PLL_VCO BIT(5) +#define HMC7044_FORCE_HOLDOVER BIT(4) +#define HMC7044_MUTE_OUT_DIV BIT(3) +#define HMC7044_PULSE_GEN_REQ BIT(2) +#define HMC7044_RESTART_DIV_FSM BIT(1) +#define HMC7044_SLEEP_MODE BIT(0) + +#define HMC7044_REG_REQ_MODE_1 0x0002 +#define HMC7044_PLL2_AUTOTUNE_TRIG BIT(2) +#define HMC7044_SLIP_REQ BIT(1) + +#define HMC7044_REG_EN_CTRL_0 0x0003 +#define HMC7044_RF_RESEEDER_EN BIT(5) +#define HMC7044_VCO_SEL(x) (((x) & 0x3) << 3) +#define HMC7044_VCO_EXT 0 +#define HMC7044_VCO_HIGH 1 +#define HMC7044_VCO_LOW 2 +#define HMC7044_SYSREF_TIMER_EN BIT(2) +#define HMC7044_PLL2_EN BIT(1) +#define HMC7044_PLL1_EN BIT(0) + +#define HMC7044_REG_EN_CTRL_1 0x0004 +#define HMC7044_SEVEN_PAIRS(x) ((x) & 0x7f) + +#define HMC7044_REG_GLOB_MODE 0x0005 +#define HMC7044_REF_PATH_EN(x) ((x) & 0xf) +#define HMC7044_RFSYNC_EN BIT(4) +#define HMC7044_VCOIN_MODE_EN BIT(5) +#define HMC7044_SYNC_PIN_MODE(x) (((x) & 0x3) << 6) + +/* PLL1 */ +#define HMC7044_REG_CLKIN0_BUF_CTRL 0x000A +#define HMC7044_REG_CLKIN1_BUF_CTRL 0x000B +#define HMC7044_REG_CLKIN2_BUF_CTRL 0x000C +#define HMC7044_REG_CLKIN3_BUF_CTRL 0x000D +#define HMC7044_REG_OSCIN_BUF_CTRL 0x000E + +#define HMC7044_REG_PLL1_REF_PRIO_CTRL 0x0014 + +#define HMC7044_HIGH_Z_EN BIT(4) +#define HMC7044_LVPECL_EN BIT(3) +#define HMC7044_AC_COUPLING_EN BIT(2) +#define HMC7044_100_OHM_EN BIT(1) +#define HMC7044_BUF_EN BIT(0) + +#define HMC7044_REG_CLKIN_PRESCALER(x) (0x001C + (x)) +#define HMC7044_REG_OSCIN_PRESCALER 0x0020 + +#define HMC7044_REG_PLL1_R_LSB 0x0021 +#define HMC7044_R1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_R_MSB 0x0022 +#define HMC7044_R1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_N_LSB 0x0026 +#define HMC7044_N1_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL1_N_MSB 0x0027 +#define HMC7044_N1_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_PLL1_LOCK_DETECT 0x0028 +#define HMC7044_LOCK_DETECT_SLIP BIT(5) +#define HMC7044_LOCK_DETECT_TIMER(x) ((x) & 0x1f) + +/* PLL2 */ +#define HMC7044_REG_PLL2_FREQ_DOUBLER 0x0032 +#define HMC7044_PLL2_FREQ_DOUBLER_DIS BIT(0) + +#define HMC7044_REG_PLL2_R_LSB 0x0033 +#define HMC7044_R2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_R_MSB 0x0034 +#define HMC7044_R2_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_REG_PLL2_N_LSB 0x0035 +#define HMC7044_N2_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_PLL2_N_MSB 0x0036 +#define HMC7044_N2_MSB(x) (((x) & 0xff00) >> 8) + +#define HMC7044_REG_OSCOUT_PATH 0x0039 +#define HMC7044_REG_OSCOUT_DRIVER_0 0x003A +#define HMC7044_REG_OSCOUT_DRIVER_1 0x003B + +/* GPIO/SDATA Control */ +#define HMC7044_REG_GPI_CTRL(x) (0x0046 + (x)) +#define HMC7044_REG_GPI_SEL(x) ((x) & 0xf) + +#define HMC7044_REG_GPO_CTRL(x) (0x0050 + (x)) +#define HMC7044_GPO_SEL(x) (((x) & 0x3f) << 2) +#define HMC7044_GPO_MODE BIT(1) +#define HMC7044_GPO_EN BIT(0) + +/* SYSREF/SYNC Control */ +#define HMC7044_REG_PULSE_GEN 0x005A +#define HMC7044_PULSE_GEN_MODE(x) ((x) & 0x7) + +#define HMC7044_REG_SYNC 0x005B +#define HMC7044_SYNC_RETIME BIT(2) +#define HMC7044_SYNC_THROUGH_PLL2 BIT(1) +#define HMC7044_SYNC_POLARITY BIT(0) + +#define HMC7044_REG_SYSREF_TIMER_LSB 0x005C +#define HMC7044_SYSREF_TIMER_LSB(x) ((x) & 0xff) + +#define HMC7044_REG_SYSREF_TIMER_MSB 0x005D +#define HMC7044_SYSREF_TIMER_MSB(x) (((x) & 0xf00) >> 8) + +#define HMC7044_CLK_INPUT_CTRL 0x0064 +#define HMC7044_LOW_FREQ_INPUT_MODE BIT(0) +#define HMC7044_DIV_2_INPUT_MODE BIT(1) + +/* Status and Alarm readback */ +#define HMC7044_REG_ALARM_READBACK 0x007D +#define HMC7044_REG_PLL1_STATUS 0x0082 + +#define HMC7044_PLL1_FSM_STATE(x) ((x) & 0x7) +#define HMC7044_PLL1_ACTIVE_CLKIN(x) (((x) >> 3) & 0x3) + +#define HMC7044_PLL2_LOCK_DETECT(x) ((x) & 0x1) +#define HMC7044_SYSREF_SYNC_STAT(x) ((x) & 0x2) +#define HMC7044_CLK_OUT_PH_STATUS(x) ((x) & 0x4) +#define HMC7044_PLL1_PLL2_LOCK_STAT(x) ((x) & 0x8) +#define HMC7044_SYNC_REQ_STATUS(x) ((x) & 0x10) + +/* Other Controls */ +#define HMC7044_REG_CLK_OUT_DRV_LOW_PW 0x009F +#define HMC7044_REG_CLK_OUT_DRV_HIGH_PW 0x00A0 +#define HMC7044_REG_PLL1_DELAY 0x00A5 +#define HMC7044_REG_PLL1_HOLDOVER 0x00A8 +#define HMC7044_REG_VTUNE_PRESET 0x00B0 + +/* Clock Distribution */ +#define HMC7044_REG_CH_OUT_CRTL_0(ch) (0x00C8 + 0xA * (ch)) +#define HMC7044_HI_PERF_MODE BIT(7) +#define HMC7044_SYNC_EN BIT(6) +#define HMC7044_CH_EN BIT(0) +#define HMC7044_START_UP_MODE_DYN_EN (BIT(3) | BIT(2)) + +#define HMC7044_REG_CH_OUT_CRTL_1(ch) (0x00C9 + 0xA * (ch)) +#define HMC7044_DIV_LSB(x) ((x) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_2(ch) (0x00CA + 0xA * (ch)) +#define HMC7044_DIV_MSB(x) (((x) >> 8) & 0xFF) + +#define HMC7044_REG_CH_OUT_CRTL_3(ch) (0x00CB + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_4(ch) (0x00CC + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_5(ch) (0x00CD + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_6(ch) (0x00CE + 0xA * (ch)) +#define HMC7044_REG_CH_OUT_CRTL_7(ch) (0x00CF + 0xA * (ch)) + +#define HMC7044_REG_CH_OUT_CRTL_8(ch) (0x00D0 + 0xA * (ch)) +#define HMC7044_DRIVER_MODE(x) (((x) & 0x3) << 3) +#define HMC7044_DRIVER_Z_MODE(x) (((x) & 0x3) << 0) +#define HMC7044_DYN_DRIVER_EN BIT(5) +#define HMC7044_FORCE_MUTE_EN BIT(7) + +#define HMC7044_NUM_CHAN 14 + +#define HMC7044_LOW_VCO_MIN 2150000 +#define HMC7044_LOW_VCO_MAX 2880000 +#define HMC7044_HIGH_VCO_MIN 2650000 +#define HMC7044_HIGH_VCO_MAX 3200000 + +#define HMC7044_RECOMM_LCM_MIN 30000 +#define HMC7044_RECOMM_LCM_MAX 70000 +#define HMC7044_RECOMM_FPD1 10000 + +#define HMC7044_R1_MAX 65535 +#define HMC7044_N1_MAX 65535 + +#define HMC7044_R2_MIN 1 +#define HMC7044_R2_MAX 4095 +#define HMC7044_N2_MIN 8 +#define HMC7044_N2_MAX 65535 + +#define HMC7044_OUT_DIV_MIN 1 +#define HMC7044_OUT_DIV_MAX 4094 + +/******************************************************************************/ +/************************** Functions Implementation **************************/ +/******************************************************************************/ + +/** + * SPI register write to device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, + uint8_t val) +{ + uint8_t buf[3]; + uint16_t cmd; + + cmd = HMC7044_WRITE | HMC7044_CNT(1) | HMC7044_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + return spi_write_and_read_3wire(dev->spi_desc, buf, NULL, + ARRAY_SIZE(buf), 0); +} + +/** + * SPI register read from device. + * @param dev - The device structure. + * @param reg - The register address. + * @param val - The register data. + * @return SUCCESS in case of success, negative error code otherwise. + */ + +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val) +{ + uint8_t wr_buf[2]; + uint8_t rd_data[1]; + uint16_t cmd; + int ret; + + cmd = HMC7044_READ | HMC7044_CNT(1) | HMC7044_ADDR(reg); + wr_buf[0] = cmd >> 8; + wr_buf[1] = cmd & 0xFF; + + ret = spi_write_and_read_3wire(dev->spi_desc, wr_buf, rd_data, + ARRAY_SIZE(wr_buf), ARRAY_SIZE(rd_data)); + if (ret != SUCCESS) + return ret; + + *val = rd_data[0]; + + return SUCCESS; +} + +/** + * Calculate the output channel divider. + * @param rate - The desired rate. + * @param parent_rate - The parent rate. + * @return The output divider. + */ +uint32_t hmc7044_calc_out_div(uint32_t rate, + uint32_t parent_rate) +{ + uint32_t div; + + div = DIV_ROUND_CLOSEST(parent_rate, rate); + + /* Supported odd divide ratios are 1, 3, and 5 */ + if ((div != 1) && (div != 3) && (div != 5) && (div % 2)) + div = DIV_ROUND_CLOSEST(parent_rate, rate * 2) * 2; + + div = clamp_t(unsigned int, + div, + HMC7044_OUT_DIV_MIN, + HMC7044_OUT_DIV_MAX); + + return div; +} + +/** + * Recalculate rate corresponding to a channel. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate) +{ + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + *rate = dev->pll2_freq / chan->divider; + + return SUCCESS; +} + +/** + * Calculate closest possible rate + * @param dev - The device structure + * @param rate - The desired rate. + * @param rounded_rate - The closest possible rate of desired rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate) +{ + uint32_t div = hmc7044_calc_out_div(rate, dev->pll2_freq); + + *rounded_rate = DIV_ROUND_CLOSEST(dev->pll2_freq, div); + + return SUCCESS; +} + +/** + * Set channel rate. + * @param dev - The device structure. + * @param chan_num - Channel number. + * @param rate - Channel rate. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate) +{ + uint32_t div; + int32_t ret; + int i; + struct hmc7044_chan_spec *chan = NULL; + + /* Find the reqested channel number */ + for (i = 0; i < dev->num_channels; i++) { + if (dev->channels[i].num == chan_num) { + chan = &dev->channels[i]; + break; + } + } + if (chan == NULL ) + return FAILURE; + + div = hmc7044_calc_out_div(rate, dev->pll2_freq); + chan->divider = div; + + ret = hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(div)); + if(ret < 0) + return ret; + + return hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(div)); +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7044_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + bool high_vco_en; + bool pll2_freq_doubler_en; + uint32_t vcxo_freq, pll2_freq; + uint32_t clkin_freq[4]; + uint32_t lcm_freq; + uint32_t in_prescaler[5]; + uint32_t pll1_lock_detect; + uint32_t n1, r1; + uint32_t pfd1_freq; + uint32_t vco_limit; + uint32_t n2[2], r2[2]; + uint32_t i, ref_en = 0; + + vcxo_freq = dev->vcxo_freq / 1000; + pll2_freq = dev->pll2_freq / 1000; + + lcm_freq = vcxo_freq; + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (dev->clkin_freq_ccf[i]) + clkin_freq[i] = dev->clkin_freq_ccf[i] / 1000; + else + clkin_freq[i] = dev->clkin_freq[i] / 1000; + + if (clkin_freq[i]) { + lcm_freq = greatest_common_divisor(clkin_freq[i], lcm_freq); + ref_en |= BIT(i); + } + } + + while (lcm_freq > HMC7044_RECOMM_LCM_MAX) + lcm_freq /= 2; + + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + if (clkin_freq[i]) + in_prescaler[i] = clkin_freq[i] / lcm_freq; + else + in_prescaler[i] = 1; + } + in_prescaler[4] = vcxo_freq / lcm_freq; + + pll1_lock_detect = log_base_2((lcm_freq * 4000) / dev->pll1_loop_bw); + + /* fVCXO / N1 = fLCM / R1 */ + rational_best_approximation(vcxo_freq, lcm_freq, + HMC7044_N1_MAX, HMC7044_R1_MAX, + &n1, &r1); + + pfd1_freq = vcxo_freq / n1; + while ((pfd1_freq > HMC7044_RECOMM_FPD1) && + (n1 <= HMC7044_N1_MAX / 2) && + (r1 <= HMC7044_R1_MAX / 2)) { + pfd1_freq /= 2; + n1 *= 2; + r1 *= 2; + } + + dev->pll1_pfd = pfd1_freq; + + if (pll2_freq < HMC7044_LOW_VCO_MIN || + pll2_freq > HMC7044_HIGH_VCO_MAX) + return FAILURE; + + vco_limit = (HMC7044_LOW_VCO_MAX + HMC7044_HIGH_VCO_MIN) / 2; + if (pll2_freq >= vco_limit) + high_vco_en = true; + else + high_vco_en = false; + + /* fVCO / N2 = fVCXO * doubler / R2 */ + pll2_freq_doubler_en = true; + rational_best_approximation(pll2_freq, vcxo_freq * 2, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[0], &r2[0]); + + if (pll2_freq != vcxo_freq * n2[0] / r2[0]) { + rational_best_approximation(pll2_freq, vcxo_freq, + HMC7044_N2_MAX, HMC7044_R2_MAX, + &n2[1], &r2[1]); + + if (abs((int)pll2_freq - (int)(vcxo_freq * 2 * n2[0] / r2[0])) > + abs((int)pll2_freq - (int)(vcxo_freq * n2[1] / r2[1]))) { + n2[0] = n2[1]; + r2[0] = r2[1]; + pll2_freq_doubler_en = false; + } + } + + while ((n2[0] < HMC7044_N2_MIN) && (r2[0] <= HMC7044_R2_MAX / 2)) { + n2[0] *= 2; + r2[0] *= 2; + } + if (n2[0] < HMC7044_N2_MIN) + return -FAILURE; + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + hmc7044_write(dev, HMC7044_REG_PLL1_DELAY, 0x06); + hmc7044_write(dev, HMC7044_REG_PLL1_HOLDOVER, 0x06); + hmc7044_write(dev, HMC7044_REG_VTUNE_PRESET, 0x04); + + uint8_t rd_back; + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_DELAY, &rd_back); + hmc7044_read(dev, HMC7044_REG_PLL1_HOLDOVER, &rd_back); + hmc7044_read(dev, HMC7044_REG_VTUNE_PRESET, &rd_back); + + hmc7044_write(dev, HMC7044_REG_GLOB_MODE, + HMC7044_SYNC_PIN_MODE(dev->sync_pin_mode) | + (dev->clkin0_rfsync_en ? HMC7044_RFSYNC_EN : 0) | + (dev->clkin1_vcoin_en ? HMC7044_VCOIN_MODE_EN : 0) | + HMC7044_REF_PATH_EN(ref_en)); + + /* Program PLL2 */ + + /* Select the VCO range */ + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_VCO_SEL(high_vco_en ? + HMC7044_VCO_HIGH : + HMC7044_VCO_LOW) | + HMC7044_SYSREF_TIMER_EN | HMC7044_PLL2_EN | + HMC7044_PLL1_EN); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL2_R_LSB, + HMC7044_R2_LSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_R_MSB, + HMC7044_R2_MSB(r2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_LSB, + HMC7044_N2_LSB(n2[0])); + hmc7044_write(dev, HMC7044_REG_PLL2_N_MSB, + HMC7044_N2_MSB(n2[0])); + + /* Program the reference doubler */ + hmc7044_write(dev, HMC7044_REG_PLL2_FREQ_DOUBLER, + pll2_freq_doubler_en ? 0 : HMC7044_PLL2_FREQ_DOUBLER_DIS); + + /* Program PLL1 */ + + /* Set the lock detect timer threshold */ + hmc7044_write(dev, HMC7044_REG_PLL1_LOCK_DETECT, + HMC7044_LOCK_DETECT_TIMER(pll1_lock_detect)); + + /* Set the LCM */ + for (i = 0; i < ARRAY_SIZE(clkin_freq); i++) { + hmc7044_write(dev, HMC7044_REG_CLKIN_PRESCALER(i), + in_prescaler[i]); + } + hmc7044_write(dev, HMC7044_REG_OSCIN_PRESCALER, + in_prescaler[4]); + + /* Program the dividers */ + hmc7044_write(dev, HMC7044_REG_PLL1_R_LSB, + HMC7044_R2_LSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_R_MSB, + HMC7044_R2_MSB(r1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_LSB, + HMC7044_N2_LSB(n1)); + hmc7044_write(dev, HMC7044_REG_PLL1_N_MSB, + HMC7044_N2_MSB(n1)); + + hmc7044_write(dev, HMC7044_REG_PLL1_REF_PRIO_CTRL, + dev->pll1_ref_prio_ctrl); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + hmc7044_write(dev, HMC7044_REG_CLKIN2_BUF_CTRL, + dev->in_buf_mode[2]); + hmc7044_write(dev, HMC7044_REG_CLKIN3_BUF_CTRL, + dev->in_buf_mode[3]); + hmc7044_write(dev, HMC7044_REG_OSCIN_BUF_CTRL, + dev->in_buf_mode[4]); + + /* Set GPIOs */ + for (i = 0; i < ARRAY_SIZE(dev->gpi_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(i), + dev->gpi_ctrl[i]); + } + + for (i = 0; i < ARRAY_SIZE(dev->gpo_ctrl); i++) { + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(i), + dev->gpo_ctrl[i]); + } + + mdelay(10); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/** + * Setup the device. + * @param dev - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +static int32_t hmc7043_setup(struct hmc7044_dev *dev) +{ + struct hmc7044_chan_spec *chan; + uint32_t i; + + if (dev->clkin_freq_ccf[0]) + dev->pll2_freq = dev->clkin_freq_ccf[0]; + else + dev->pll2_freq = dev->clkin_freq[0]; + + if (!dev->pll2_freq) { + printf("%s: Failed to get valid parent rate\n", __func__); + return FAILURE; + } + + /* Resets all registers to default values */ + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, HMC7044_SOFT_RESET); + mdelay(10); + hmc7044_write(dev, HMC7044_REG_SOFT_RESET, 0); + mdelay(10); + + /* Load the configuration updates (provided by Analog Devices) */ + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_LOW_PW, 0x4d); + hmc7044_write(dev, HMC7044_REG_CLK_OUT_DRV_HIGH_PW, 0xdf); + + /* Disable all channels */ + for (i = 0; i < HMC7044_NUM_CHAN; i++) + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(i), 0); + + if (dev->pll2_freq < 1000000000U) + hmc7044_write(dev, HMC7044_CLK_INPUT_CTRL, + HMC7044_LOW_FREQ_INPUT_MODE); + + hmc7044_write(dev, HMC7044_REG_EN_CTRL_0, + (dev->rf_reseeder_en ? HMC7044_RF_RESEEDER_EN : 0) | + HMC7044_SYSREF_TIMER_EN); + + /* Program the SYSREF timer */ + + /* Set the divide ratio */ + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_LSB, + HMC7044_SYSREF_TIMER_LSB(dev->sysref_timer_div)); + hmc7044_write(dev, HMC7044_REG_SYSREF_TIMER_MSB, + HMC7044_SYSREF_TIMER_MSB(dev->sysref_timer_div)); + + /* Set the pulse generator mode configuration */ + hmc7044_write(dev, HMC7044_REG_PULSE_GEN, + HMC7044_PULSE_GEN_MODE(dev->pulse_gen_mode)); + + /* Enable the input buffers */ + hmc7044_write(dev, HMC7044_REG_CLKIN0_BUF_CTRL, + dev->in_buf_mode[0]); + hmc7044_write(dev, HMC7044_REG_CLKIN1_BUF_CTRL, + dev->in_buf_mode[1]); + + /* Set GPIOs */ + hmc7044_write(dev, HMC7044_REG_GPI_CTRL(0), + dev->gpi_ctrl[0]); + + hmc7044_write(dev, HMC7044_REG_GPO_CTRL(0), + dev->gpo_ctrl[0]); + + /* Program the output channels */ + for (i = 0; i < dev->num_channels; i++) { + chan = &dev->channels[i]; + + if (chan->num >= HMC7044_NUM_CHAN || chan->disable) + continue; + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_1(chan->num), + HMC7044_DIV_LSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_2(chan->num), + HMC7044_DIV_MSB(chan->divider)); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_8(chan->num), + HMC7044_DRIVER_MODE(chan->driver_mode) | + HMC7044_DRIVER_Z_MODE(chan->driver_impedance) | + (chan->dynamic_driver_enable ? + HMC7044_DYN_DRIVER_EN : 0) | + (chan->force_mute_enable ? + HMC7044_FORCE_MUTE_EN : 0)); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_3(chan->num), + chan->fine_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_4(chan->num), + chan->coarse_delay & 0x1F); + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_7(chan->num), + chan->out_mux_mode & 0x3); + + hmc7044_write(dev, HMC7044_REG_CH_OUT_CRTL_0(chan->num), + (chan->start_up_mode_dynamic_enable ? + HMC7044_START_UP_MODE_DYN_EN : 0) | + (chan->output_control0_rb4_enable ? BIT(4) : 0) | + (chan->high_performance_mode_dis ? + 0 : HMC7044_HI_PERF_MODE) | HMC7044_SYNC_EN | + HMC7044_CH_EN); + } + mdelay(10); + + + /* Do a restart to reset the system and initiate calibration */ + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + HMC7044_RESTART_DIV_FSM); + mdelay(1); + hmc7044_write(dev, HMC7044_REG_REQ_MODE_0, + (dev->high_performance_mode_clock_dist_en ? + HMC7044_HIGH_PERF_DISTRIB_PATH : 0)); + mdelay(1); + + return SUCCESS; +} + +/***************************************************************************//** + * @brief hmc7044_reg_init + *******************************************************************************/ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + int ret = SUCCESS; + struct hmc7044_dev *dev; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/** + * Initialize the device. + * @param device - The device structure. + * @param init_param - The structure that contains the device initial + * parameters. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param) +{ + struct hmc7044_dev *dev; + int32_t ret; + unsigned int i; + + dev = (struct hmc7044_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + ret = spi_init(&dev->spi_desc, init_param->spi_init); + if (ret < 0) + return ret; + + dev->is_hmc7043 = init_param->is_hmc7043; + + dev->clkin_freq[0] = init_param->clkin_freq[0]; + dev->clkin_freq[1] = init_param->clkin_freq[1]; + dev->clkin_freq[2] = init_param->clkin_freq[2]; + dev->clkin_freq[3] = init_param->clkin_freq[3]; + + dev->clkin_freq_ccf[0] = init_param->clkin_freq_ccf[0]; + dev->clkin_freq_ccf[1] = init_param->clkin_freq_ccf[1]; + dev->clkin_freq_ccf[2] = init_param->clkin_freq_ccf[2]; + dev->clkin_freq_ccf[3] = init_param->clkin_freq_ccf[3]; + + dev->vcxo_freq = init_param->vcxo_freq; + dev->pll1_pfd = init_param->pll1_pfd; + dev->pll2_freq = init_param->pll2_freq; + dev->pll1_loop_bw = init_param->pll1_loop_bw; + + dev->sysref_timer_div = init_param->sysref_timer_div; + dev->pll1_ref_prio_ctrl = init_param->pll1_ref_prio_ctrl; + dev->clkin0_rfsync_en = init_param->clkin0_rfsync_en; + dev->clkin1_vcoin_en = init_param->clkin1_vcoin_en; + dev->high_performance_mode_clock_dist_en = + init_param->high_performance_mode_clock_dist_en; + dev->rf_reseeder_en = !init_param->rf_reseeder_disable; + dev->sync_pin_mode = init_param->sync_pin_mode; + dev->pulse_gen_mode = init_param->pulse_gen_mode; + + dev->in_buf_mode[0] = init_param->in_buf_mode[0]; + dev->in_buf_mode[1] = init_param->in_buf_mode[1]; + dev->in_buf_mode[2] = init_param->in_buf_mode[2]; + dev->in_buf_mode[3] = init_param->in_buf_mode[3]; + dev->in_buf_mode[4] = init_param->in_buf_mode[4]; + + dev->gpi_ctrl[0] = init_param->gpi_ctrl[0]; + dev->gpi_ctrl[1] = init_param->gpi_ctrl[1]; + dev->gpi_ctrl[2] = init_param->gpi_ctrl[2]; + dev->gpi_ctrl[3] = init_param->gpi_ctrl[3]; + + dev->gpo_ctrl[0] = init_param->gpo_ctrl[0]; + dev->gpo_ctrl[1] = init_param->gpo_ctrl[1]; + dev->gpo_ctrl[2] = init_param->gpo_ctrl[2]; + dev->gpo_ctrl[3] = init_param->gpo_ctrl[3]; + + dev->num_channels = init_param->num_channels; + dev->channels = (struct hmc7044_chan_spec *) + malloc(sizeof(*dev->channels) * dev->num_channels); + + for (i = 0; i < dev->num_channels; i++) { + dev->channels[i].num = init_param->channels[i].num; + dev->channels[i].disable = init_param->channels[i].disable; + dev->channels[i].divider = init_param->channels[i].divider; + dev->channels[i].driver_mode = + init_param->channels[i].driver_mode; + dev->channels[i].high_performance_mode_dis = + init_param->channels[i].high_performance_mode_dis; + dev->channels[i].start_up_mode_dynamic_enable = + init_param->channels[i].start_up_mode_dynamic_enable; + dev->channels[i].dynamic_driver_enable = + init_param->channels[i].dynamic_driver_enable; + dev->channels[i].output_control0_rb4_enable = + init_param->channels[i].output_control0_rb4_enable; + dev->channels[i].force_mute_enable = + init_param->channels[i].force_mute_enable; + dev->channels[i].driver_impedance = + init_param->channels[i].driver_impedance; + dev->channels[i].coarse_delay = + init_param->channels[i].coarse_delay; + dev->channels[i].fine_delay = + init_param->channels[i].fine_delay; + dev->channels[i].out_mux_mode = + init_param->channels[i].out_mux_mode; + } + + *device = dev; + + if (!dev->is_hmc7043) + return hmc7044_setup(dev); + else + return hmc7043_setup(dev); +} + +/** + * Remove the device - release resources. + * @param device - The device structure. + * @return SUCCESS in case of success, negative error code otherwise. + */ +int32_t hmc7044_remove(struct hmc7044_dev *device) +{ + int32_t ret; + + ret = spi_remove(device->spi_desc); + free(device->channels); + free(device); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.h b/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.h new file mode 100644 index 0000000..a178975 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/hmc7044/hmc7044.h @@ -0,0 +1,276 @@ +/***************************************************************************//** + * @file hmc7044.h + * @brief Header file of HMC7044, HMC7043 Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2018-2020(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef HMC7044_H_ +#define HMC7044_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "delay.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +// Enum to select SYNC pin configuration with respect to PLL2 (0x0005) +typedef enum +{ + SYNC_DISABLED = 0, + SYNC_MULTICHIP = 1, + SYNC_PULSE_GEN = 2, + SYNC_ALARM = 3 +} hmc7044SyncPinModeSelect_t; + +// Enum to select input buffer mode (0x000A, 0x000B, 0x000C, 0x000D, 0x000E) +typedef enum +{ + BUFFER_ENABLE = (1) << 0, + BUFFER_DISABLE = (0) << 0, + ENABLE_INTERNAL_TERM = (1) << 1, + ENABLE_AC_COUPLE = (1) << 2, + ENABLE_LVPECL = (1) << 3, + ENABLE_HIGH_Z = (1) << 4 +} hmc7044InputBufferMode_t; + +// Enum to select output driver mode (0x003A, 0x003B, 0x00D0, 0x00DA, 0x00E4, +// 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, 0x0134, 0x013E, +// 0x0148, 0x0152) +typedef enum +{ + CML = 0, + LVPECL = 1, + LVDS = 2, + CMOS = 3 +} hmc7044DriverMode_t; + +// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049) +typedef enum +{ + GPI_ENABLE = (1) << 0, + GPI_DISABLE = (0) << 0, + FORCE_PLL1_HOLDOVER = (0x01) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT1 = (0x02) << 1 | GPI_ENABLE, + SELECT_PLL1_REF_BIT2 = (0x03) << 1 | GPI_ENABLE, + CHIP_SLEEP_MODE = (0x04) << 1 | GPI_ENABLE, + MUTE_REQUSET = (0x05) << 1 | GPI_ENABLE, + SELECT_INTERNAL_VCO_TYPE = (0x06) << 1 | GPI_ENABLE, + SELECT_HI_PERF_MODE = (0x07) << 1 | GPI_ENABLE, + PULSE_GEN_REQUSET = (0x08) << 1 | GPI_ENABLE, + RESEED_REQUEST = (0x09) << 1 | GPI_ENABLE, + RESTART_REQUSET = (0x0A) << 1 | GPI_ENABLE, + FORCE_FANOUT_MODE = (0x0B) << 1 | GPI_ENABLE, + SLIP_REQUEST = (0x0D) << 1 | GPI_ENABLE, +} hmc7044GPIControl_t; + +// Enum to select the GPOx functionality. (0x0050, 0x0051, 0x0052, 0x0053) +typedef enum +{ + GPO_ENABLE = (1) << 0, + GPO_DISABLE = (0) << 0, + GPO_CMOS_MODE = (1) << 1, + GPO_OPEN_DRAIN_MODE = (0) << 1, + ALARM_SIGNAL = (0x00) << 3 | GPO_ENABLE, + SPI_SDATA = (0x01) << 3 | GPO_ENABLE, + CLKIN3_SIGNAL_LOSS = (0x02) << 3 | GPO_ENABLE, + CLKIN2_SIGNAL_LOSS = (0x03) << 3 | GPO_ENABLE, + CLKIN1_SIGNAL_LOSS = (0x04) << 3 | GPO_ENABLE, + CLKIN0_SIGNAL_LOSS = (0x05) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_ENABLE = (0x06) << 3 | GPO_ENABLE, + PLL1_LOCK_DETECT = (0x07) << 3 | GPO_ENABLE, + PLL1_ACQUIRING_LOCK = (0x08) << 3 | GPO_ENABLE, + PLL1_NEAR_CLOCK_ACQ_STAT = (0x09) << 3 | GPO_ENABLE, + PLL2_LOCK_DETECT = (0x0A) << 3 | GPO_ENABLE, + PLL2_SYSREF_SYNC = (0x0B) << 3 | GPO_ENABLE, + CLOCK_OUTPUT_PHASE_STAT = (0x0C) << 3 | GPO_ENABLE, + PLL1_PLL2_LOCKED = (0x0D) << 3 | GPO_ENABLE, + SYNC_REQUSRT_STAT = (0x0E) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN0 = (0x0F) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKIN1 = (0x10) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_RANGE_STAT = (0x11) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_IN_STAT = (0x12) << 3 | GPO_ENABLE, + PLL1_VCXO_STAT = (0x13) << 3 | GPO_ENABLE, + PLL1_ACTIVE_CLKINx_STAT = (0x14) << 3 | GPO_ENABLE, + PLL1_FSM_BIT0 = (0x15) << 3 | GPO_ENABLE, + PLL1_FSM_BIT1 = (0x16) << 3 | GPO_ENABLE, + PLL1_FSM_BIT2 = (0x17) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT0 = (0x18) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_EXIT_PHASE_BIT1 = (0x19) << 3 | GPO_ENABLE, + CHANNEL_OUTPUT_FSM_BUSY = (0x1A) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT0 = (0x1B) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT1 = (0x1C) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT2 = (0x1D) << 3 | GPO_ENABLE, + SYSREF_FSM_STAT_BIT3 = (0x1E) << 3 | GPO_ENABLE, + FORCE_LOGIC_1 = (0x1F) << 3 | GPO_ENABLE, + FORCE_LOGIC_0 = (0x20) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT0 = (0x27) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT1 = (0x28) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT2 = (0x29) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_AVG_VALUE_BIT3 = (0x2A) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT0 = (0x2B) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT1 = (0x2C) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT2 = (0x2D) << 3 | GPO_ENABLE, + PLL1_HOLDOVER_CURR_VALUE_BIT3 = (0x2E) << 3 | GPO_ENABLE +} hmc7044GPOControl_t; + +// Enum to select output channel (0x00CF, 0x00D9, 0x00E3, 0x00ED, 0x00F7, +// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151 +typedef enum +{ + CHANNEL_DIV = 0, + ANALOG_DELAY = 1, + OTHER_CHANNEL = 2, + VCO_CLOCK = 3 +} hmc7044OutputMuxSelect_t; + +// Enum to select output driver impedance selection for CML mode (0x00D0, +// 0x00DA, 0x00E4, 0x00EE, 0x00F8, 0x0102, 0x010C, 0x0116, 0x0120, 0x012A, +// 0x0134, 0x013E, 0x0148, 0x0152) +typedef enum +{ + INTERNAL_RES_DISABLE = 0, + INTERNAL_100OHM_PER_PIN = 1, +// INTERNAL_RES_RESERVED = 2, + INTERNAL_50OHM_PER_PIN = 3 +} hmc7044DriverImpedance_t; + +// Enum to select pulse generator mode (0x005A) +typedef enum +{ + PULSE_LEVEL_SENSITIVE = 0, + PULSE_ONE = 1, + PULSE_TWO = 2, + PULSE_FOUR = 3, + PULSE_EIGHT = 4, + PULSE_SIXTEEN = 5, +// PULSE_SIXTEEN = 6, + PULSE_CONTINOUS = 7 +} hmc7044SyncPulseGenControl_t; + +struct hmc7044_chan_spec { + unsigned int num; + bool disable; + bool high_performance_mode_dis; + bool start_up_mode_dynamic_enable; + bool dynamic_driver_enable; + bool output_control0_rb4_enable; + bool force_mute_enable; + unsigned int divider; + unsigned int coarse_delay; + unsigned int fine_delay; + hmc7044DriverMode_t driver_mode; + hmc7044DriverImpedance_t driver_impedance; + hmc7044OutputMuxSelect_t out_mux_mode; +}; + +struct hmc7044_config { + uint16_t addr; + uint8_t value; +}; + +struct hmc7044_dev { + struct spi_desc *spi_desc; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_en; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +struct hmc7044_init_param { + struct spi_init_param *spi_init; + bool is_hmc7043; + uint32_t clkin_freq[4]; + uint32_t clkin_freq_ccf[4]; + uint32_t vcxo_freq; + uint32_t pll1_pfd; + uint32_t pll2_freq; + uint32_t pll1_loop_bw; + uint32_t sysref_timer_div; + unsigned int pll1_ref_prio_ctrl; + bool clkin0_rfsync_en; + bool clkin1_vcoin_en; + bool high_performance_mode_clock_dist_en; + bool rf_reseeder_disable; + hmc7044SyncPinModeSelect_t sync_pin_mode; + hmc7044SyncPulseGenControl_t pulse_gen_mode; + uint32_t in_buf_mode[5]; + uint32_t gpi_ctrl[4]; + uint32_t gpo_ctrl[4]; + uint32_t num_channels; + struct hmc7044_chan_spec *channels; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the device. */ +int32_t hmc7044_reg_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +int32_t hmc7044_init(struct hmc7044_dev **device, + const struct hmc7044_init_param *init_param); +/* Remove the device. */ +int32_t hmc7044_remove(struct hmc7044_dev *device); +int32_t hmc7044_write(struct hmc7044_dev *dev, + uint16_t reg, uint8_t val); +int32_t hmc7044_read(struct hmc7044_dev *dev, uint16_t reg, uint8_t *val); +int32_t hmc7044_clk_recalc_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t *rate); +int32_t hmc7044_clk_round_rate(struct hmc7044_dev *dev, uint32_t rate, + uint64_t *rounded_rate); +int32_t hmc7044_clk_set_rate(struct hmc7044_dev *dev, uint32_t chan_num, + uint64_t rate); + +#endif // HMC7044_H_ diff --git a/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.c b/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.c new file mode 100644 index 0000000..2ef3ec5 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.c @@ -0,0 +1,128 @@ +/***************************************************************************//** + * @file lmk04828.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "lmk04828.h" +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief lmk04828_read + *******************************************************************************/ +int32_t lmk04828_read(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = 0x80 | (reg_addr >> 8); + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief lmk04828_write + *******************************************************************************/ +int32_t lmk04828_write(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief lmk04828_init + *******************************************************************************/ +int32_t lmk04828_init(struct lmk04828_dev **device, + const struct lmk04828_init_param *init_param) +{ + int ret = SUCCESS; + struct lmk04828_dev *dev; + + dev = (struct lmk04828_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by lmk04828_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t lmk04828_remove(struct lmk04828_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.h b/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.h new file mode 100644 index 0000000..995ba49 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/lmk04828/lmk04828.h @@ -0,0 +1,90 @@ +/***************************************************************************//** + * @file lmk04828.h + * @brief Header file of lmk04828 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef LMK04828_H_ +#define LMK04828_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct lmk04828_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct lmk04828_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct lmk04828_config { + uint16_t addr; + uint8_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t lmk04828_read(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t lmk04828_write(struct lmk04828_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t lmk04828_init(struct lmk04828_dev **device, + const struct lmk04828_init_param *init_param); + +int32_t lmk04828_remove(struct lmk04828_dev *dev); + +#endif diff --git a/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.c b/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.c new file mode 100644 index 0000000..755c818 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.c @@ -0,0 +1,129 @@ +/***************************************************************************//** + * @file lmx2594.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "../lmx2594/lmx2594.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief lmx2594_read + *******************************************************************************/ +int32_t lmx2594_read(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t *reg_data) +{ + uint8_t tx_buf[1]; + uint8_t rx_buf[2]; + int32_t ret; + + tx_buf[0] = 0x80 | reg_addr; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 1, 2); + + *reg_data = rx_buf[1]; + *reg_data |= ((uint16_t)rx_buf[0]) << 8; + + return ret; +} + +/***************************************************************************//** + * @brief lmx2594_write + *******************************************************************************/ +int32_t lmx2594_write(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = reg_addr; + buf[1] = reg_data >> 8; + buf[2] = reg_data & 0xFF; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief lmx2594_init + *******************************************************************************/ +int32_t lmx2594_init(struct lmx2594_dev **device, + const struct lmx2594_init_param *init_param) +{ + int ret = SUCCESS; + struct lmx2594_dev *dev; + + dev = (struct lmx2594_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + + *device = dev; + + return ret; +} + +/***************************************************************************//** + * @brief Free the resources allocated by lmx2594_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t lmx2594_remove(struct lmx2594_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.h b/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.h new file mode 100644 index 0000000..a9903b2 --- /dev/null +++ b/df_datalink_ge/src/drivers/frequency/lmx2594/lmx2594.h @@ -0,0 +1,90 @@ +/***************************************************************************//** + * @file lmx2594.h + * @brief Header file of lmx2594 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef LMX2594_H_ +#define LMX2594_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct lmx2594_dev { + /* SPI */ + struct spi_desc *spi_desc; +}; + +struct lmx2594_init_param { + /* SPI */ + struct spi_init_param *spi_init; +}; + +struct lmx2594_config { + uint8_t addr; + uint16_t value; +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t lmx2594_read(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t *reg_data); + +int32_t lmx2594_write(struct lmx2594_dev *dev, + uint8_t reg_addr, + uint16_t reg_data); + +int32_t lmx2594_init(struct lmx2594_dev **device, + const struct lmx2594_init_param *init_param); + +int32_t lmx2594_remove(struct lmx2594_dev *dev); + +#endif diff --git a/df_datalink_ge/src/drivers/platform/xilinx_delay.c b/df_datalink_ge/src/drivers/platform/xilinx_delay.c new file mode 100644 index 0000000..3c320f6 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_delay.c @@ -0,0 +1,100 @@ +/***************************************************************************//** + * @file xilinx/xilinx_delay.c + * @brief Implementation of Xilinx Delay Functions. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "delay.h" +#include +#ifdef _XPARAMETERS_PS_H_ +#include "util.h" +#include "xtime_l.h" +#endif + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Generate microseconds delay. + * @param usecs - Delay in microseconds. + * @return None. + */ +void udelay(uint32_t usecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(usecs); +#else + usleep_MB(usecs); +#endif +} + +/** + * @brief Generate miliseconds delay. + * @param msecs - Delay in miliseconds. + * @return None. + */ +void mdelay(uint32_t msecs) +{ +#ifdef _XPARAMETERS_PS_H_ + usleep(msecs * 1000); +#else + usleep_MB(msecs * 1000); +#endif +} + +/** + * @brief Get current time. + * @return Current time structure from system start (seconds, microseconds). + */ +struct time get_time(void) +{ + struct time t = {0, 0}; +#ifdef _XPARAMETERS_PS_H_ + unsigned long long Xtime_Global; + uint32_t rem; + + XTime_GetTime(&Xtime_Global); + t.s = div_u64_rem(Xtime_Global, COUNTS_PER_SECOND, &rem); + t.us = div_u64((uint64_t)rem * 1000000, COUNTS_PER_SECOND); +#endif + + return t; +} diff --git a/df_datalink_ge/src/drivers/platform/xilinx_gpio.c b/df_datalink_ge/src/drivers/platform/xilinx_gpio.c new file mode 100644 index 0000000..274399d --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_gpio.c @@ -0,0 +1,464 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio.c + * @brief Implementation of Xilinx GPIO Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XGPIO_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XGPIOPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "gpio.h" +#include "xilinx_gpio.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Prepare the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - The structure that contains the GPIO parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t _gpio_init(struct gpio_desc *desc, + const struct gpio_init_param *param) +{ + int32_t ret; + struct xil_gpio_desc *xdesc; + struct xil_gpio_init_param *xinit; + + ret = -1; + + xdesc = desc->extra; + xinit = param->extra; + + xdesc->type = xinit->type; + desc->number = param->number; + + switch (xinit->type) { + case GPIO_PL: +#ifdef XGPIO_H + xdesc->instance = (XGpio *)malloc(sizeof(XGpio)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XGpio_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XGpio_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpio_Config*)xdesc->config) + ->BaseAddress); + if(ret < 0) + goto pl_error; + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case GPIO_PS: +#ifdef XGPIOPS_H + xdesc->instance = (XGpioPs *)malloc(sizeof(XGpioPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XGpioPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XGpioPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XGpioPs_Config*)xdesc->config)->BaseAddr); + if(ret < 0) + goto ps_error; + break; +ps_error: + free(xdesc->instance); +#endif + goto error; +error: + default: + return -1; + } + + return 0; +} + +/** + * @brief Obtain the GPIO decriptor. + * @param desc - The GPIO descriptor. + * @param param - GPIO initialization parameters + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + struct gpio_desc *descriptor; + struct xil_gpio_desc *extra; + int32_t ret; + + descriptor = (struct gpio_desc *)malloc(sizeof(*descriptor)); + extra = (struct xil_gpio_desc*)malloc(sizeof(*extra)); + + if (!descriptor || !extra) + return -1; + + descriptor->extra = extra; + ret = _gpio_init(descriptor, param); + + if(ret != 0) + goto error; + + *desc = descriptor; + + return 0; +error: + free(extra); + free(descriptor); + + return -1; +} + +/** + * @brief Get the value of an optional GPIO. + * @param desc - The GPIO descriptor. + * @param param - GPIO Initialization parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_optional(struct gpio_desc **desc, + const struct gpio_init_param *param) +{ + if(param == NULL) { + *desc = NULL; + return 0; + } + + return xil_gpio_get(desc, param); +} + +/** + * @brief Free the resources allocated by gpio_get(). + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_remove(struct gpio_desc *desc) +{ + if (desc != NULL) { + free(((struct xil_gpio_desc *)(desc->extra))->instance); + free(desc->extra); + free(desc); + } + + return 0; +} + +/** + * @brief Enable the input direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_input(struct gpio_desc *desc) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint32_t channel = 1; + uint32_t config = 0; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + /* We assume that pin 32 is the first pin from channel 2 */ + if (pin >= 32) { + channel = 2; + pin -= 32; + } + + config = XGpio_GetDataDirection((XGpio *)extra->instance, + channel); + config |= (1 << pin); + XGpio_SetDataDirection((XGpio *)extra->instance, + channel, + config); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_IN); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Enable the output direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_direction_output(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_GetDataDirection(extra->instance, + channel); + reg_val &= ~(1 << pin); + XGpio_SetDataDirection(extra->instance, + channel, + reg_val); + reg_val = XGpio_DiscreteRead(extra->instance, + channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, + channel, + reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_SetDirectionPin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_SetOutputEnablePin(extra->instance, + desc->number, + GPIO_OUT); + XGpioPs_WritePin(extra->instance, + desc->number, + value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the direction of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param direction - The direction. + * Example: GPIO_OUT + * GPIO_IN + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_direction(struct gpio_desc *desc, + uint8_t *direction) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *direction = ((XGpio_GetDataDirection(extra->instance, + channel) >> pin) & 0x1) ^ 0x1; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *direction = XGpioPs_GetDirectionPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Set the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_set_value(struct gpio_desc *desc, + uint8_t value) +{ + struct xil_gpio_desc *extra; +#ifdef XGPIO_H + uint8_t pin = desc->number; + uint8_t channel; + uint32_t reg_val; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + + reg_val = XGpio_DiscreteRead(extra->instance, channel); + if(value) + reg_val |= (1 << pin); + else + reg_val &= ~(1 << pin); + XGpio_DiscreteWrite(extra->instance, channel, reg_val); +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + XGpioPs_WritePin(extra->instance, desc->number, value); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Get the value of the specified GPIO. + * @param desc - The GPIO descriptor. + * @param value - The value. + * Example: GPIO_HIGH + * GPIO_LOW + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_get_value(struct gpio_desc *desc, + uint8_t *value) +{ + if (!desc) + return -1; + + struct xil_gpio_desc *extra; + uint8_t pin = desc->number; + +#ifdef XGPIO_H + uint8_t channel; +#endif + extra = desc->extra; + + switch (extra->type) { + case GPIO_PL: +#ifdef XGPIO_H + if (pin >= 32) { + channel = 2; + pin -= 32; + } else + channel = 1; + *value = (XGpio_DiscreteRead(extra->instance, channel) >> pin) & 0x01; +#endif + break; + case GPIO_PS: +#ifdef XGPIOPS_H + *value = XGpioPs_ReadPin(extra->instance, pin); +#endif + break; + default: + return -1; + } + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO platform ops structure + */ +const struct gpio_platform_ops xil_gpio_ops = { + .gpio_ops_get = &xil_gpio_get, + .gpio_ops_get_optional = &xil_gpio_get_optional, + .gpio_ops_remove = &xil_gpio_remove, + .gpio_ops_direction_input = &xil_gpio_direction_input, + .gpio_ops_direction_output = &xil_gpio_direction_output, + .gpio_ops_get_direction = &xil_gpio_get_direction, + .gpio_ops_set_value = &xil_gpio_set_value, + .gpio_ops_get_value = &xil_gpio_get_value, +}; diff --git a/df_datalink_ge/src/drivers/platform/xilinx_gpio.h b/df_datalink_ge/src/drivers/platform/xilinx_gpio.h new file mode 100644 index 0000000..041a1d6 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_gpio.h @@ -0,0 +1,95 @@ +/******************************************************************************* + * @file xilinx/xilinx_gpio.h + * @brief Header containing extra types used in the gpio driver + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_H_ +#define XILINX_GPIO_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_gpio_type + * @brief Xilinx platform architecture sections + */ +enum xil_gpio_type { + /** Programmable Logic */ + GPIO_PL, + /** Processing System */ + GPIO_PS +}; + +/** + * @struct xil_gpio_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO parameters. + */ +struct xil_gpio_init_param { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_gpio_desc + * @brief Xilinx platform specific GPIO descriptor + */ +struct xil_gpio_desc { + /** Xilinx architecture */ + enum xil_gpio_type type; + /** Xilinx GPIO configuration */ + void *config; + /** Xilinx GPIO Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific gpio platform ops structure + */ +extern const struct gpio_platform_ops xil_gpio_ops; + +#endif diff --git a/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.c b/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.c new file mode 100644 index 0000000..f153c2a --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.c @@ -0,0 +1,360 @@ +/***************************************************************************//** + * @file xilinx/xilinx_gpio_irq.c + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "xparameters.h" +#include "error.h" +#include "xilinx_gpio_irq.h" +#include "util.h" +#include "list.h" +#include "irq.h" + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Comparing function used by list. + * @param desc_a - Compared item + * @param desc_b - Reference item + * @return - 0 if items match + */ +static int32_t call_cmp(struct xil_callback_desc *desc_a, + struct xil_callback_desc *desc_b) +{ + return desc_a->pin_nb - desc_b->pin_nb; +} + +/** + * @brief Function called when GPIO IRQ occurs. + * @param param - GPIO IRQ desc's extra field + * @return - None. + */ +static void xil_gpio_irq_handler(struct xil_gpio_irq_desc *param) +{ + int32_t status = 0; + int32_t pin_nb; + struct xil_callback_desc *callback_desc; + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(XGpioPs_IntrGetStatusPin(¶m->my_Gpio, callback_desc->pin_nb)) + callback_desc->triggered = true; + } + + status = iterator_move_to_idx(param->it, 0); + while(!status) { + iterator_read(param->it, &callback_desc); + status = iterator_move(param->it, 1); + if(callback_desc->triggered == true) { + callback_desc->triggered = false; + XGpioPs_IntrDisablePin(¶m->my_Gpio, callback_desc->pin_nb); + XGpioPs_IntrClearPin(¶m->my_Gpio, callback_desc->pin_nb); + callback_desc->callback.legacy_callback(callback_desc->callback.ctx, 0U, NULL); + if(callback_desc->enabled) + XGpioPs_IntrEnablePin(¶m->my_Gpio, callback_desc->pin_nb); + } + } +} + +/** + * @brief Disable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_disable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = false; + break; + } + } + + XGpioPs_IntrDisablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Initialize the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @param param - The GPIO IRQ controller initial parameters. + * irq_ctrl_id from irq_init_param is the interrupt id for the parent controller + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_init(struct irq_ctrl_desc **desc, + const struct irq_init_param *param) +{ + int32_t i; + int32_t status; + struct irq_ctrl_desc *ldesc; + static XGpioPs_Config *GPIO_Config; + struct xil_gpio_irq_desc *xil_desc; + struct xil_gpio_irq_init_param *xil_ip; + struct callback_desc callback; + + xil_desc = (struct xil_gpio_irq_desc *)calloc(1, sizeof(*xil_desc)); + if(!xil_desc) + return -ENOMEM; + + ldesc = (struct irq_ctrl_desc *)calloc(1, sizeof(*ldesc)); + if(!ldesc) { + free(xil_desc); + return -ENOMEM; + } + + xil_ip = param->extra; + GPIO_Config = XGpioPs_LookupConfig(xil_ip->gpio_device_id); + status = XGpioPs_CfgInitialize(&xil_desc->my_Gpio, GPIO_Config, + GPIO_Config->BaseAddr); + if(status) + goto error_desc; + + ldesc->extra = xil_desc; + xil_desc->parent_desc = xil_ip->parent_desc; + + status = list_init(&xil_desc->callback_list, LIST_DEFAULT, + call_cmp); + if(status) + goto error_list; + + status = iterator_init(&xil_desc->it, xil_desc->callback_list, 0); + if(status) { + iterator_remove(xil_desc->it); + goto error_list; + } + + ldesc->irq_ctrl_id = param->irq_ctrl_id; + status = irq_trigger_level_set(xil_desc->parent_desc, ldesc->irq_ctrl_id, + IRQ_EDGE_RISING); + if(status) + goto error_op; + + status = irq_enable(xil_desc->parent_desc, ldesc->irq_ctrl_id); + if(status) + goto error_op; + + callback.legacy_callback = &xil_gpio_irq_handler; + callback.ctx = ldesc->extra; + status = irq_register_callback(xil_desc->parent_desc, ldesc->irq_ctrl_id, + &callback); + if(status) + goto error_op; + + *desc = ldesc; + + return 0; + +error_op: + iterator_remove(xil_desc->it); +error_list: + list_remove(xil_desc->callback_list); +error_desc: + free(xil_desc); + free(ldesc); + return status; +} + +/** + * @brief Set GPIO interrupt trigger level. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param trig - New trigger level for the GPIO interrupt. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_trigger_level_set(struct irq_ctrl_desc *desc, + uint32_t irq_id, + enum irq_trig_level trig) +{ + static const int32_t trig_level[5] = {XGPIOPS_IRQ_TYPE_LEVEL_LOW, + XGPIOPS_IRQ_TYPE_LEVEL_HIGH, + XGPIOPS_IRQ_TYPE_EDGE_FALLING, + XGPIOPS_IRQ_TYPE_EDGE_RISING, + XGPIOPS_IRQ_TYPE_EDGE_BOTH + }; + struct xil_gpio_irq_desc *extra; + + extra = desc->extra; + XGpioPs_SetIntrTypePin(&extra->my_Gpio, irq_id, trig_level[trig]); + + return 0; +} + +/** + * @brief Register pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param callback_desc - Callback. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_register_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, + struct callback_desc *callback_desc) +{ + struct xil_callback_desc *dev_callback; + struct xil_gpio_irq_desc *extra; + + dev_callback = (struct xil_callback_desc *)calloc(1, + sizeof(*dev_callback)); + if(!dev_callback) + return -1; + + dev_callback->pin_nb = irq_id; + dev_callback->callback.legacy_callback = callback_desc->legacy_callback; + dev_callback->callback.ctx = callback_desc->ctx; + dev_callback->triggered = false; + + extra = desc->extra; + XGpioPs_SetDirectionPin(&extra->my_Gpio, irq_id, 0); + list_add_last(extra->callback_list, dev_callback); + + return 0; +} + +/** + * @brief Unregister pin specific GPIO interrupt. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @param cb - Callback descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_unregister_callback(struct irq_ctrl_desc *desc, + uint32_t irq_id, struct callback_desc *cb) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *dev_callback; + struct xil_callback_desc search_callback; + + extra = desc->extra; + search_callback.pin_nb = irq_id; + status = list_get_find(extra->callback_list, &dev_callback, + &search_callback); + if(status) + return -ENXIO; + + free(dev_callback); + + return 0; +} + +/** + * @brief Enable specific GPIO IRQ pin. + * @param desc - The GPIO IRQ controller descriptor. + * @param irq_id - Pin number. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_enable(struct irq_ctrl_desc *desc, uint32_t irq_id) +{ + int32_t status; + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + extra = desc->extra; + + status = iterator_move_to_idx(extra->it, 0); + while(!status) { + iterator_read(extra->it, &callback_desc); + status = iterator_move(extra->it, 1); + if(callback_desc->pin_nb == irq_id) { + callback_desc->enabled = true; + XGpioPs_IntrClearPin(&extra->my_Gpio, irq_id); + break; + } + } + + XGpioPs_IntrEnablePin(&extra->my_Gpio, irq_id); + + return 0; +} + +/** + * @brief Remove the GPIO IRQ controller. + * @param desc - The GPIO IRQ controller descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_gpio_irq_ctrl_remove(struct irq_ctrl_desc *desc) +{ + struct xil_gpio_irq_desc *extra; + struct xil_callback_desc *callback_desc; + + if (!desc) + return -EINVAL; + + extra = desc->extra; + while (0 == list_get_first(extra->callback_list, &callback_desc)) + free(callback_desc); + + iterator_remove(extra->it); + list_remove(extra->callback_list); + free(extra); + free(desc); + + return 0; +} + +/** + * @brief Xilinx platform specific GPIO IRQ platform ops structure + */ +const struct irq_platform_ops xil_gpio_irq_ops = { + .init = &xil_gpio_irq_ctrl_init, + .enable = &xil_gpio_irq_enable, + .disable = &xil_gpio_irq_disable, + .trigger_level_set = &xil_gpio_irq_trigger_level_set, + .register_callback = &xil_gpio_irq_register_callback, + .unregister_callback = xil_gpio_irq_unregister_callback, + .remove = &xil_gpio_irq_ctrl_remove +}; diff --git a/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.h b/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.h new file mode 100644 index 0000000..c0c8348 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_gpio_irq.h @@ -0,0 +1,92 @@ +/***************************************************************************//** + * @file xilinx_gpio_irq.h + * @brief Implementation of Xilinx GPIO IRQ Generic Driver. + * @author Porumb Andrei (andrei.porumb@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_GPIO_IRQ_H_ +#define XILINX_GPIO_IRQ_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include "stdbool.h" +#include "list.h" +#include "xgpiops.h" +#include "irq.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +/** + * @struct xil_callback_desc + * @brief Structure holding callback parameters for each pin + */ +struct xil_callback_desc { + int32_t pin_nb; + struct callback_desc callback; + bool triggered; + bool enabled; +}; + +/** + * @struct xil_gpio_irq_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific GPIO IRQ parameters. + */ +struct xil_gpio_irq_init_param { + struct irq_ctrl_desc *parent_desc; + int32_t gpio_device_id; +}; + +/** + * @struct xil_gpio_irq_desc + * @brief Xilinx platform specific GPIO IRQ descriptor + */ +struct xil_gpio_irq_desc { + struct irq_ctrl_desc *parent_desc; + XGpioPs my_Gpio; + struct list_desc *callback_list; + struct iterator *it; +}; + +/** + * @brief Xilinx specific GPIO IRQ platform ops structure + */ +extern const struct irq_platform_ops xil_gpio_irq_ops; + +#endif diff --git a/df_datalink_ge/src/drivers/platform/xilinx_i2c.c b/df_datalink_ge/src/drivers/platform/xilinx_i2c.c new file mode 100644 index 0000000..de4ecb4 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_i2c.c @@ -0,0 +1,514 @@ +/***************************************************************************//** + * @file xilinx/xilinx_i2c.c + * @brief Implementation of Xilinx I2C Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XIIC_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XIICPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "i2c.h" +#include "xilinx_i2c.h" +#include "list.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +static struct list_desc *pl_list = NULL; +static struct iterator *pl_it = NULL; + +#ifdef XIICPS_H +static struct list_desc *ps_list = NULL; +static struct iterator *ps_it = NULL; +#endif /* XIICPS_H */ + +/** + * @struct inst_table_item + * @brief Table item for I2C cores already started. + */ +struct inst_table_item { + /** Instance the BSP driver uses for this core. */ + void *instance; + /** Core ID in BSP. */ + uint32_t device_id; + /** Number of ADI driver instances running on this core. */ + uint32_t inst_no; +}; + +#ifdef XPAR_XIICPS_NUM_INSTANCES +/** Save the current state of the bitrate to not change it each time */ +static uint32_t ps_last_bitrate = 0; +#endif + +/** + * @brief Xilinx platform specific I2C platform ops structure + */ +const struct i2c_platform_ops xil_i2c_ops = { + .i2c_ops_init = &xil_i2c_init, + .i2c_ops_write = &xil_i2c_write, + .i2c_ops_read = &xil_i2c_read, + .i2c_ops_remove = &xil_i2c_remove +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Compare two I2C cores by ID. + * @param el1 - First I2C core to compare. + * @param el2 - Second I2C core to compare. + * @return \ref 0 if the two cores have the same ID, + * \ref difference between the first and the second IDs otherwise. + */ +static int32_t xil_i2c_cmp(void *el1, void *el2) +{ + struct inst_table_item *sel1 = el1, *sel2 = el2; + + return (sel1->device_id - sel2->device_id); +} + +/** + * @brief Configure slave address and bitrate if needed + * @param desc - Descriptor of the I2C device + * @return 0 in case of success, -1 otherwise. + */ +static int32_t xil_i2c_set_transmission_config(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xil_i2c_desc = desc->extra; +#ifdef XIICPS_H + int32_t ret; +#endif + + switch (xil_i2c_desc->type) { + case IIC_PL: +#ifdef XIIC_H + break; +#endif + return -1; + case IIC_PS: +#ifdef XIICPS_H + if (desc->max_speed_hz != ps_last_bitrate) { + ret = XIicPs_SetSClk(xil_i2c_desc->instance, desc->max_speed_hz); + if (ret != XST_SUCCESS) + return -1; + ps_last_bitrate = desc->max_speed_hz; + } + break; +#endif + return -1; + default: + + return -1; + } + + return 0; +} + +/** + * @brief Initialize the I2C communication peripheral. + * @param desc - The I2C descriptor. + * @param param - The structure that contains the I2C parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param) +{ + int32_t ret; + struct i2c_desc *idesc; + struct xil_i2c_desc *xdesc; + struct xil_i2c_init_param *xinit; + + idesc = (struct i2c_desc *)malloc(sizeof(*idesc)); + xdesc = (struct xil_i2c_desc *)malloc(sizeof(*xdesc)); + + if(!idesc || !xdesc) + goto error; + + idesc->max_speed_hz = param->max_speed_hz; + idesc->slave_address = param->slave_address; + xinit = param->extra; + + idesc->extra = xdesc; + xdesc->type = xinit->type; + xdesc->device_id = xinit->device_id; + switch (xinit->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + + if (!pl_list) + list_init(&pl_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&pl_it, pl_list, true); + + tab_check_pl.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(pl_list, (void **)&temp_el_pl, + &tab_check_pl))) { + xdesc->instance = temp_el_pl->instance; + temp_el_pl->inst_no++; + break; + } + + xdesc->instance = (XIic *)malloc(sizeof(XIic)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XIic_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XIic_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIic_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XIic_Start(xdesc->instance); + if(ret != 0) + goto pl_error; + + ret = XIic_SetAddress(xdesc->instance, + XII_ADDR_TO_SEND_TYPE, + param->slave_address); + if(ret != 0) + goto pl_error; + + ret = XIic_SelfTest(xdesc->instance); + if(ret < 0) + goto pl_error; + + ret = XIic_SetGpOutput(xdesc->instance, 1); + if(ret < 0) + goto pl_error; + + temp_el_pl = (struct inst_table_item*)calloc(1, sizeof(*temp_el_pl)); + temp_el_pl->device_id = xinit->device_id; + temp_el_pl->inst_no = 1; + temp_el_pl->instance = xdesc->instance; + pl_list->push(pl_list, temp_el_pl); + + break; +pl_error: + free(xdesc->instance); +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + + if (!pl_list) + list_init(&ps_list, LIST_DEFAULT, xil_i2c_cmp); + if (!pl_it) + iterator_init(&ps_it, ps_list, true); + + tab_check_ps.device_id = xdesc->device_id; + + if (!IS_ERR_VALUE(list_read_find(ps_list, + (void **)&temp_el_ps, + &tab_check_ps))) { + xdesc->instance = temp_el_ps->instance; + temp_el_ps->inst_no++; + break; + } + + xdesc->instance = (XIicPs *)malloc(sizeof(XIicPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XIicPs_LookupConfig(xinit->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XIicPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XIicPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + XIicPs_SetSClk(xdesc->instance, param->max_speed_hz); + + temp_el_ps = (struct inst_table_item*)calloc(1, sizeof(*temp_el_ps)); + temp_el_ps->device_id = xinit->device_id; + temp_el_ps->inst_no = 1; + temp_el_ps->instance = xdesc->instance; + ps_list->push(ps_list, temp_el_ps); + + break; +ps_error: + free(xdesc->instance); +#endif + goto error; + + default: + goto error; + break; + } + + *desc = idesc; + + return 0; + +error: + free(idesc); + free(xdesc); + + return -1; +} + +/** + * @brief Free the resources allocated by i2c_init(). + * @param desc - The I2C descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_remove(struct i2c_desc *desc) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_pl; + struct inst_table_item *temp_el_pl; + tab_check_pl.device_id = xdesc->device_id; + ret = iterator_find(pl_it, &tab_check_pl); + if (ret != 0) + goto error; + iterator_read(pl_it, (void **)&temp_el_pl); + temp_el_pl->inst_no--; + if (temp_el_pl->inst_no != 0) + break; + + ret = XIic_Stop(((XIic *)xdesc->instance)); + + if(ret != 0) + goto error; + + /** Remove list element */ + iterator_get(pl_it, (void **)&temp_el_pl); + free(temp_el_pl); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ; /** Intentional empty statement */ + struct inst_table_item tab_check_ps; + struct inst_table_item *temp_el_ps; + tab_check_ps.device_id = xdesc->device_id; + ret = iterator_find(ps_it, &tab_check_ps); + if (ret != 0) + goto error; + iterator_read(ps_it, (void **)&temp_el_ps); + temp_el_ps->inst_no--; + if (temp_el_ps->inst_no != 0) + break; + + /** Remove list element */ + iterator_get(ps_it, (void **)&temp_el_ps); + free(temp_el_ps); + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write data to a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that stores the transmission data. + * @param bytes_number - Number of bytes to write. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + XIic_Send(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterSend(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + + return -1; + } + + return 0; +} + +/** + * @brief Read data from a slave device. + * @param desc - The I2C descriptor. + * @param data - Buffer that will store the received data. + * @param bytes_number - Number of bytes to read. + * @param stop_bit - Stop condition control. + * Example: 0 - A stop condition will not be generated; + * 1 - A stop condition will be generated. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit) +{ + struct xil_i2c_desc *xdesc; + int32_t ret; + + xdesc = desc->extra; + + switch (xdesc->type) { + case IIC_PL: +#ifdef XIIC_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIic_Recv(((XIic*)xdesc->instance)->BaseAddress, + desc->slave_address, + data, + bytes_number, + stop_bit ? XIIC_STOP : XIIC_REPEATED_START); + if(ret != bytes_number) + goto error; + + break; +#endif + goto error; + case IIC_PS: +#ifdef XIICPS_H + ret = xil_i2c_set_transmission_config(desc); + if (ret != 0) + return -1; + + ret = XIicPs_SetOptions(xdesc->instance, + stop_bit ? 0 : XIICPS_REP_START_OPTION); + if(ret != 0) + goto error; + + XIicPs_MasterRecv(xdesc->instance, + data, + bytes_number, + desc->slave_address); + if(ret != 0) + goto error; + + break; +#endif + /* Intended fallthrough */ +error: + default: + return -1; + + break; + } + + return 0; +} diff --git a/df_datalink_ge/src/drivers/platform/xilinx_i2c.h b/df_datalink_ge/src/drivers/platform/xilinx_i2c.h new file mode 100644 index 0000000..b091318 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_i2c.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_i2c.h + * @brief Header containing types used in the i2c driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef XILINX_I2C_H_ +#define XILINX_I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_i2c_type + * @brief Xilinx platform architecture sections + */ +enum xil_i2c_type { + /** Programmable Logic */ + IIC_PL, + /** Processing System */ + IIC_PS +}; + +/** + * @struct xil_i2c_init + * @brief Structure holding the initialization parameters for Xilinx platform + * specific I2C parameters. + */ +struct xil_i2c_init_param { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; +}; + +/** + * @struct xil_i2c_desc + * @brief Xilinx platform specific I2C descriptor + */ +struct xil_i2c_desc { + /** Xilinx architecture */ + enum xil_i2c_type type; + /** Device ID */ + uint32_t device_id; + /** Xilinx I2C configuration */ + void *config; + /** Xilinx I2C Instance */ + void *instance; +}; + +/** + * @brief Xilinx platform specific i2c platform ops structure + */ +extern const struct i2c_platform_ops xil_i2c_ops; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t xil_i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t xil_i2c_remove(struct i2c_desc *desc); + +/* I2C Write data */ +int32_t xil_i2c_write(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +/* I2C Read data. */ +int32_t xil_i2c_read(struct i2c_desc *desc, uint8_t *data, + uint8_t bytes_number, uint8_t stop_bit); + +#endif // XILINX_I2C_H_ diff --git a/df_datalink_ge/src/drivers/platform/xilinx_spi.c b/df_datalink_ge/src/drivers/platform/xilinx_spi.c new file mode 100644 index 0000000..832ea91 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_spi.c @@ -0,0 +1,462 @@ +/***************************************************************************//** + * @file xilinx/xilinx_spi.c + * @brief Implementation of Xilinx SPI Generic Driver. + * @author Antoniu Miclaus (antoniu.miclaus@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +#include +#ifdef XPAR_XSPI_NUM_INSTANCES +#include +#endif +#ifdef XPAR_XSPIPS_NUM_INSTANCES +#include +#endif + +#include "error.h" +#include "spi.h" +#include "xilinx_spi.h" + +#if defined(PLATFORM_ZYNQ) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PS7_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#elif defined(PLATFORM_ZYNQMP) +#define SPI_CLK_FREQ_HZ(dev) (XPAR_PSU_SPI_ ## dev ## _SPI_CLK_FREQ_HZ) +#define SPI_NUM_INSTANCES XPAR_XSPIPS_NUM_INSTANCES +#else +#define SPI_NUM_INSTANCES 0 +#endif + +#warning SPI delays are not supported on the xilinx platform + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_pl(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPI_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpi*)calloc(1, sizeof(XSpi)); + if(!xdesc->instance) + goto pl_error; + + xdesc->config = XSpi_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto pl_error; + + ret = XSpi_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpi_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto pl_error; + + ret = XSpi_Initialize(xdesc->instance, param->device_id); + if (ret != 0) + goto pl_error; + + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto pl_error; + + ret = XSpi_Start(xdesc->instance); + if (ret != 0) + goto pl_error; + + XSpi_IntrGlobalDisable((XSpi *)(xdesc->instance)); + + return 0; + +pl_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the hardware SPI peripherial + * + * @param xdesc Platform specific SPI descriptor + * @param xinit Platform specific SPI init param + * @return int32_t -1 if the device couldn't be found or configured + */ +static int32_t spi_init_ps(struct spi_desc *desc, + const struct spi_init_param *param) +{ +#ifdef XSPIPS_H + int32_t ret; + struct xil_spi_desc *xdesc; + struct xil_spi_init_param *xinit; + const uint32_t prescaler_default = XSPIPS_CLK_PRESCALE_64; + const uint32_t prescaler_min = XSPIPS_CLK_PRESCALE_4; + const uint32_t prescaler_max = XSPIPS_CLK_PRESCALE_256; + uint32_t prescaler = 0u; + uint32_t input_clock = 0u; + + xdesc = (struct xil_spi_desc*)malloc(sizeof(struct xil_spi_desc)); + if(!xdesc) { + free(xdesc); + return -1; + } + + desc->extra = xdesc; + xinit = param->extra; + xdesc->type = xinit->type; + xdesc->flags = xinit->flags; + + xdesc->instance = (XSpiPs*)malloc(sizeof(XSpiPs)); + if(!xdesc->instance) + goto ps_error; + + xdesc->config = XSpiPs_LookupConfig(param->device_id); + if(xdesc->config == NULL) + goto ps_error; + + ret = XSpiPs_CfgInitialize(xdesc->instance, + xdesc->config, + ((XSpiPs_Config*)xdesc->config) + ->BaseAddress); + if(ret != 0) + goto ps_error; + + switch (param->device_id) { +#if (SPI_NUM_INSTANCES >= 1) + case 0: + input_clock = SPI_CLK_FREQ_HZ(0); + break; +#endif +#if (SPI_NUM_INSTANCES >= 2) + case 1: + input_clock = SPI_CLK_FREQ_HZ(1); + break; +#endif + default: + goto ps_error; + }; + + if (desc->max_speed_hz != 0u) { + uint32_t div = input_clock / desc->max_speed_hz; + uint32_t rem = input_clock % desc->max_speed_hz; + uint32_t po2 = !(div & (div - 1)) && !rem; + + // find the power of two just higher than div and + // store the exponent in prescaler + while(div) { + prescaler += 1; + div >>= 1u; + } + + // this exponent - 1 is needed because of the way + // xilinx stores it into registers + if (prescaler) + prescaler -= 1; + + // this exponent - 1 is needed when initial div was + // precisely a power of two + if (prescaler && po2) + prescaler -= 1; + + if (prescaler < prescaler_min) + prescaler = prescaler_min; + + if (prescaler > prescaler_max) + prescaler = prescaler_max; + } else + prescaler = prescaler_default; + + ret = XSpiPs_SetClkPrescaler(xdesc->instance, prescaler); + + if(ret != 0) + goto ps_error; + + return 0; + +ps_error: + free(xdesc->instance); + free(xdesc); +#endif + return -1; +} + +/** + * @brief Initialize the SPI communication peripheral. + * @param desc - The SPI descriptor. + * @param param - The structure that contains the SPI parameters. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_init(struct spi_desc **desc, + const struct spi_init_param *param) +{ + int32_t ret; + enum xil_spi_type *spi_type; + + if (!param) { + return -1; + } + + *desc = malloc(sizeof(**desc)); + if(! *desc) { + free(*desc); + return -1; + } + + spi_type = param->extra; + + if(!spi_type) + goto init_error; + + (*desc)->max_speed_hz = param->max_speed_hz; + (*desc)->mode = param->mode; + (*desc)->bit_order = param->bit_order; + (*desc)->chip_select = param->chip_select; + + switch (*spi_type) { + case SPI_PL: + ret = spi_init_pl(*desc, param); + break; + case SPI_PS: + ret = spi_init_ps(*desc, param); + break; + + default: + goto init_error; + break; + } + + if (ret != 0) { +init_error: + free(*desc); + + return -1; + } + + return ret; +} + +/** + * @brief Free the resources allocated by spi_init(). + * @param desc - The SPI descriptor. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_remove(struct spi_desc *desc) +{ +#ifdef XSPI_H + int32_t ret; +#endif + struct xil_spi_desc *xdesc = NULL; + enum xil_spi_type *spi_type; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + switch (*spi_type ) { + case SPI_PL: +#ifdef XSPI_H + xdesc = desc->extra; + + if(!xdesc) + return -1; + + ret = XSpi_Stop((XSpi *)(xdesc->instance)); + if(ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + xdesc = desc->extra; + + if(!xdesc) + return -1; +#endif + break; + + /* Intended fallthrough */ +#ifdef XSPI_H +error: +#endif + default: + return -1; + } + + if(xdesc) + free(xdesc->instance); + free(desc->extra); + free(desc); + + return 0; +} + +/** + * @brief Write and read data to/from SPI. + * @param desc - The SPI descriptor. + * @param data - The buffer with the transmitted/received data. + * @param bytes_number - Number of bytes to write/read. + * @return 0 in case of success, -1 otherwise. + */ +int32_t xil_spi_write_and_read(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + int32_t ret; +#ifdef XSPI_H + uint32_t ctrl_reg; +#endif + struct xil_spi_desc *xdesc; + enum xil_spi_type *spi_type; + + ret = -1; + + spi_type = desc->extra; + + if(!spi_type) + return -1; + + xdesc = desc->extra; + + switch (*spi_type) { + case SPI_PL: +#ifdef XSPI_H + ret = XSpi_SetOptions(xdesc->instance, + XSP_MASTER_OPTION | + ((desc->mode & SPI_CPOL) ? + XSP_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSP_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ctrl_reg = XSpi_GetControlReg(((XSpi*)xdesc->instance)); + if (desc->bit_order == SPI_BIT_ORDER_LSB_FIRST) + ctrl_reg |= XSP_CR_LSB_MSB_FIRST_MASK; + else + ctrl_reg &= ~ XSP_CR_LSB_MSB_FIRST_MASK; + XSpi_SetControlReg(((XSpi*)xdesc->instance), ctrl_reg); + + ret = XSpi_SetSlaveSelect(xdesc->instance, + 0x01 << desc->chip_select); + if (ret != 0) + goto error; + + ret = XSpi_Transfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; +#endif + break; + case SPI_PS: +#ifdef XSPIPS_H + ret = XSpiPs_SetOptions(xdesc->instance, + XSPIPS_MASTER_OPTION | + ((xdesc->flags & SPI_CS_DECODE) ? + XSPIPS_DECODE_SSELECT_OPTION : 0) | + XSPIPS_FORCE_SSELECT_OPTION | + ((desc->mode & SPI_CPOL) ? + XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | + ((desc->mode & SPI_CPHA) ? + XSPIPS_CLK_PHASE_1_OPTION : 0)); + if (ret != 0) + goto error; + + ret = XSpiPs_SetSlaveSelect(xdesc->instance, + desc->chip_select); + if (ret != 0) + goto error; + ret = XSpiPs_PolledTransfer(xdesc->instance, + data, + data, + bytes_number); + if (ret != 0) + goto error; + ret = XSpiPs_SetSlaveSelect(xdesc->instance, SPI_DEASSERT_CURRENT_SS); + if (ret != 0) + goto error; +#endif + break; +error: + default: + return -1; + } + + return ret; +} + +/** + * @brief Xilinx platform specific SPI platform ops structure + */ +const struct spi_platform_ops xil_spi_ops = { + .init = &xil_spi_init, + .write_and_read = &xil_spi_write_and_read, + .remove = &xil_spi_remove +}; diff --git a/df_datalink_ge/src/drivers/platform/xilinx_spi.h b/df_datalink_ge/src/drivers/platform/xilinx_spi.h new file mode 100644 index 0000000..fc42c7b --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_spi.h @@ -0,0 +1,115 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi.h + * @brief Header containing extra types used in the spi driver. + * @author scuciurean (sergiu.cuciurean@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef XILINX_SPI_H_ +#define XILINX_SPI_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include "spi.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define SPI_CS_DECODE 0x01 +#define SPI_DEASSERT_CURRENT_SS 0x0F + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @enum xil_spi_type + * @brief Xilinx platform architecture sections + */ +enum xil_spi_type { + /** Programmable Logic */ + SPI_PL, + /** Processing System */ + SPI_PS, + /** SPI Engine */ + SPI_ENGINE +}; + +/** + * @struct xil_spi_init_param + * @brief Structure holding the initialization parameters for Xilinx platform + * specific SPI parameters when using xil_spi_ops. + */ +struct xil_spi_init_param { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; +}; + +/** + * @struct xil_spi_desc + * @brief Xilinx platform specific SPI descriptor + */ +struct xil_spi_desc { + /** Xilinx architecture */ + enum xil_spi_type type; + /** SPI flags */ + uint32_t flags; + /** SPI configuration */ + void *config; + /** SPI instance */ + void *instance; +}; + +/** + * @brief SPI engine platform ops structure + */ +extern const struct spi_platform_ops spi_eng_platform_ops; + +/** + * @brief Xilinx specific SPI platform ops structure + */ +extern const struct spi_platform_ops xil_spi_ops; + +/** + * @brief Xilinx SPI PS register functions. No extra param needed + */ +extern const struct spi_platform_ops xil_spi_pl_ops; + +#endif // XILINX_SPI_H_ diff --git a/df_datalink_ge/src/drivers/platform/xilinx_spi_pl.c b/df_datalink_ge/src/drivers/platform/xilinx_spi_pl.c new file mode 100644 index 0000000..270cc29 --- /dev/null +++ b/df_datalink_ge/src/drivers/platform/xilinx_spi_pl.c @@ -0,0 +1,533 @@ +/******************************************************************************* + * @file xilinx/xilinx_spi_pl.c + * @brief Driver for spi pl device using registers + * @author Mihail Chindris (mihail.chindris@analog.com) +******************************************************************************** + * Copyright 2021(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#include + +#ifdef XPAR_XSPI_NUM_INSTANCES + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include +#include +#include +#include "spi.h" +#include "error.h" +#include "delay.h" +#include "util.h" +#include "alloc.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +#define XPS_TYPE_WRITE 0x1 +#define XPS_TYPE_READ 0x2 +#define XSP_DEFAULT_SR_VALUE 0x25 +#define XSP_DUMMY_DATA 0xFF + +/* + * Used to store current spi device configuration in order to not update it for + * each spi transaction if not needed. + */ +static struct spi_desc g_spi_desc[XPAR_XSPI_NUM_INSTANCES]; + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/* Xilinx PL spi specific data */ +struct xspi_desc { + uint32_t base_addr; + uint32_t disable_slaves_mask; + uint32_t fifo_depth; + uint8_t cs_asserted; +}; + +/* Structure used to iterate over SPI messages */ +struct msg_iter { + struct spi_msg *msgs; + uint32_t len; + uint32_t i; + uint32_t buff_i; + uint8_t is_wr; +}; + +/******************************************************************************/ +/************************ Functions Definitions *******************************/ +/******************************************************************************/ + +/* Read device register */ +static inline uint32_t _read(struct xspi_desc *xdesc, uint32_t reg) +{ + return Xil_In32(xdesc->base_addr + reg); +} + +/* Write device register */ +static inline void _write(struct xspi_desc *xdesc, uint32_t reg, uint32_t val) +{ + Xil_Out32(xdesc->base_addr + reg, val); +} + +/* Update device register. Only bits set to 1 in mask will be modified */ +static inline void _wr_mask(struct xspi_desc *xdesc, uint32_t reg, + uint32_t val, uint32_t mask) +{ + uint32_t tmp; + + tmp = _read(xdesc, reg); + tmp &= ~mask; + tmp |= val & mask; + _write(xdesc, reg, tmp); +} + +/* Update spi device configuration if needed */ +static void _update_mode(struct spi_desc *desc) +{ + uint32_t val; + uint32_t mask; + + if (desc->mode == g_spi_desc[desc->device_id].mode && + desc->bit_order == g_spi_desc[desc->device_id].bit_order) + return ; + + /* Update mode */ + val = desc->mode | SPI_CPOL ? XSP_CR_CLK_POLARITY_MASK : 0; + val |= desc->mode | SPI_CPHA ? XSP_CR_CLK_PHASE_MASK : 0; + mask = XSP_CR_CLK_POLARITY_MASK | XSP_CR_CLK_PHASE_MASK; + + val |= desc->bit_order == SPI_BIT_ORDER_LSB_FIRST ? + XSP_CR_LSB_MSB_FIRST_MASK : 0; + mask |= XSP_CR_LSB_MSB_FIRST_MASK; + + _wr_mask(desc->extra, XSP_CR_OFFSET, val, mask); + g_spi_desc[desc->device_id] = *desc; +} + +/* Configure SPI PL device */ +static int32_t _xil_spi_init_dev(struct xspi_desc *xdesc) +{ + uint32_t val; + + /* Software reset */ + _write(xdesc, XSP_SRR_OFFSET, XSP_SRR_RESET_MASK); + mdelay(1); + + /* Check if success reset */ + val = _read(xdesc, XSP_SR_OFFSET); + if (val != XSP_DEFAULT_SR_VALUE) + return -ENODEV; + + /* Disable interrupts. Drivers only works with pooled mode */ + _write(xdesc, XSP_IIER_OFFSET, 0); + + /* Deasert chip selects */ + _write(xdesc, XSP_SSR_OFFSET, 0xFFFFFFFF); + + /* Get fifo depth */ + while (!(_read(xdesc, XSP_SR_OFFSET) & XSP_SR_TX_FULL_MASK)) + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + xdesc->fifo_depth = _read(xdesc, XSP_TFO_OFFSET) + 1; + + /* Configure spi device */ + val = XSP_CR_ENABLE_MASK | + XSP_CR_MANUAL_SS_MASK | + XSP_CR_TXFIFO_RESET_MASK | + XSP_CR_RXFIFO_RESET_MASK | + XSP_CR_MASTER_MODE_MASK | + XSP_CR_TRANS_INHIBIT_MASK; + + _write(xdesc, XSP_CR_OFFSET, val); + + return 0; +} + +/* Initialize spi_desc structure and device */ +static int32_t xil_spi_init_pl(struct spi_desc **desc, + const struct spi_init_param *param) +{ + struct spi_desc *ldesc; + struct xspi_desc *xdesc; + int32_t err; + XSpi_Config *cfg; + + if (!desc || !param || param->device_id >= XPAR_XSPI_NUM_INSTANCES) + return -EINVAL; + + cfg = XSpi_LookupConfig(param->device_id); + if (!cfg) + return -EINVAL; + + if (param->chip_select > cfg->NumSlaveBits) + return -EINVAL; + + ldesc = (struct spi_desc *)calloc(1, sizeof(*ldesc)); + if (!ldesc) + return -ENOMEM; + + xdesc = (struct xspi_desc *)calloc(1, sizeof(*xdesc)); + if (!xdesc) { + err = -ENOMEM; + goto error; + } + + ldesc->bit_order = param->bit_order; + ldesc->chip_select = param->chip_select; + ldesc->mode = param->mode; + xdesc->base_addr = cfg->BaseAddress; + xdesc->disable_slaves_mask = (1 << cfg->NumSlaveBits) - 1; + xdesc->cs_asserted = 0; + + err = _xil_spi_init_dev(xdesc); + if (IS_ERR_VALUE(err)) + goto error; + + ldesc->extra = xdesc; + *desc = ldesc; + + return 0; + +error: + free(xdesc); + free(ldesc); + + return err; +} + +/* Remove allocated resources */ +static int32_t xil_spi_remove_pl(struct spi_desc *desc) +{ + if (!desc) + return -EINVAL; + + free(desc->extra); + free(desc); + + return 0; +} + +/* + * Fill fifo until fifo is full or no more data available. + * Return the number of written bytes. + */ +static uint32_t _wr_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t i; + uint32_t to_write; + uint32_t tx_available; + + tx_available = xdesc->fifo_depth - _read(xdesc, XSP_TFO_OFFSET); + to_write = min(tx_available, len); + for (i = 0; i < to_write; ++i) + if (data) + _write(xdesc, XSP_DTR_OFFSET, data[i]); + else + _write(xdesc, XSP_DTR_OFFSET, XSP_DUMMY_DATA); + + return to_write; +} + +/* + * Read fifo until fifo is empty or no more buffer available to read into + * Returns the number of read bytes + */ +static uint32_t _rd_fifo(struct xspi_desc *xdesc, uint8_t *data, + uint32_t len) +{ + uint32_t rx_available; + uint32_t to_read; + uint32_t tmp; + uint32_t i; + + tmp = _read(xdesc, XSP_SR_OFFSET); + if (tmp & XSP_SR_RX_EMPTY_MASK) + return 0; + + rx_available = _read(xdesc, XSP_RFO_OFFSET) + 1; + to_read = min(rx_available, len); + for (i = 0; i < to_read; ++i) { + tmp = _read(xdesc, XSP_DRR_OFFSET); + if (data) + data[i] = tmp; + } + + return to_read; +} + +/* If start is 0 stop transfer, else start it. + * CS will be asserted if needed. If different CS othere than the one needed + * is asserted. Deassert it and assert correct one */ +static void _xil_spi_start_transfer(struct spi_desc *desc, uint8_t start) +{ + struct xspi_desc *xdesc; + + xdesc = desc->extra; + if (start) { + if (xdesc->cs_asserted) { + if (desc->chip_select == + g_spi_desc[desc->device_id].chip_select) + return ; + else + /* Stop transfer to start again with new CS */ + _xil_spi_start_transfer(desc, 0); + } + _write(xdesc, XSP_SSR_OFFSET, ~(1 << desc->chip_select)); + _wr_mask(xdesc, XSP_CR_OFFSET, 0, XSP_CR_TRANS_INHIBIT_MASK); + } else { + _wr_mask(xdesc, XSP_CR_OFFSET, XSP_CR_TRANS_INHIBIT_MASK, + XSP_CR_TRANS_INHIBIT_MASK); + _write(xdesc, XSP_SSR_OFFSET, xdesc->disable_slaves_mask); + } + xdesc->cs_asserted = start; +} + + +/* SPI polled transfer */ +static int32_t xil_spi_write_and_read_pl(struct spi_desc *desc, + uint8_t *data, + uint16_t bytes_number) +{ + struct xspi_desc *xdesc; + uint32_t rx; + uint32_t tx; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + _xil_spi_start_transfer(desc, 1); + rx = 0; + tx = 0; + while (rx < bytes_number) { + if (tx < bytes_number) + tx += _wr_fifo(xdesc, data + tx, bytes_number - tx); + rx += _rd_fifo(xdesc, data + rx, bytes_number - rx); + } + _xil_spi_start_transfer(desc, 0); + + return 0; +} + +/* Get type of message. It can be READ, WRITE or both */ +static uint32_t _get_msg_type(struct spi_msg *msg) +{ + uint32_t type; + + type = 0; + if (msg->tx_buff) + type |= XPS_TYPE_WRITE; + if (msg->rx_buff) + type |= XPS_TYPE_READ; + + return type; +} + +/* Get information based on current iterator position */ +static void _get_data(struct msg_iter *it, uint8_t **buff, uint32_t *len, + uint32_t *type) +{ + struct spi_msg *msg; + + if (it->i == it->len) { + *len = 0; + return ; + } + + msg = it->msgs + it->i; + if (it->is_wr) + *buff = msg->tx_buff; + else + *buff = msg->rx_buff; + + if (*buff) + *buff += it->buff_i; + + *len = msg->bytes_number - it->buff_i; + if (type) + *type = _get_msg_type(msg); +} + +/* + * Increment iterator position with desired length. + * If the new position has a different message type, new_type will be set to 1 + * If a CS change is needed, cs_change is set + */ +static void _increment_iter(struct msg_iter *it, uint32_t len, + uint8_t *cs_change, uint8_t *new_type) +{ + struct spi_msg *msg; + uint32_t type; + uint32_t extra_len; + + if (!len) + return ; + + *cs_change = 0; + *new_type = 0; + msg = it->msgs + it->i; + if (it->buff_i + len > msg->bytes_number) + extra_len = it->buff_i + len - msg->bytes_number; + else + extra_len = 0; + len -= extra_len; + it->buff_i += len; + if (it->buff_i == msg->bytes_number) { + type = _get_msg_type(msg); + ++it->i; + it->buff_i = 0; + if (cs_change && msg->cs_change) + *cs_change = 1; + if (new_type) + if (it->i == it->len || + type != _get_msg_type(it->msgs + it->i)) + *new_type = 1; + } + if (extra_len) + _increment_iter(it, extra_len, cs_change, new_type); +} + +/* + * SPI polling transfer of multiple messages. + */ +static int32_t xil_spi_transfer_pl(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len) + +{ + struct xspi_desc *xdesc; + uint8_t cs_change; + uint8_t new_type; + struct msg_iter rx = {.msgs = msgs, .len = len, .is_wr = 0}; + struct msg_iter tx = {.msgs = msgs, .len = len, .is_wr = 1}; + uint8_t *buff; + uint32_t bytes; + uint32_t type; + /* Bytes to increment rx when only a write transaction is executed */ + uint32_t to_inc_rx; + /* Difference between rx and tx iterators in bytes */ + uint32_t tx_advance; + /* Save bytes sent during a write loop */ + uint32_t tx_sent; + /* Used to loop if need to empty the RX FIFO */ + uint32_t loop; + + if (!desc || !desc->extra) + return -EINVAL; + + xdesc = desc->extra; + _update_mode(desc); + + tx_advance = 0; + to_inc_rx = 0; + buff = NULL; + type = 0; + do { + _xil_spi_start_transfer(desc, 1); + + tx_sent = 0; + /* Writing loop */ + do { + _get_data(&tx, &buff, &bytes, &type); + if (type & XPS_TYPE_READ) + /* + * Do not write more bytes than fifo_depth if + * they haven't been read. + */ + bytes = min(bytes, + xdesc->fifo_depth - tx_advance); + bytes = _wr_fifo(xdesc, buff, bytes); + tx_sent += bytes; + _increment_iter(&tx, bytes, &cs_change, &new_type); + tx_advance += bytes; + } while (!cs_change && !new_type && bytes); + + if (type & XPS_TYPE_READ) { + loop = 1; + /* + * Loop only when no more data to write otherwise read + * only available data. + */ + while (loop) { + if (!new_type) + loop = 0; + _get_data(&rx, &buff, &bytes, NULL); + bytes = _rd_fifo(xdesc, buff, bytes); + _increment_iter(&rx, bytes, &cs_change, &new_type); + tx_advance -= bytes; + if (loop && new_type) + break; + } + } else { + /* Clean RX FIFO if it was only a WRITE message */ + to_inc_rx += tx_sent; + if (new_type) { + /* Wait for TX to be sent */ + while (!(_read(xdesc, XSP_SR_OFFSET) & + XSP_SR_TX_EMPTY_MASK)) + ; + /* Reset fifo. Only write was performed */ + _wr_mask(xdesc, XSP_CR_OFFSET, + XSP_CR_RXFIFO_RESET_MASK, + XSP_CR_RXFIFO_RESET_MASK); + + _increment_iter(&rx, to_inc_rx, NULL, NULL); + tx_advance -= to_inc_rx; + to_inc_rx = 0; + } + } + + if ((cs_change && rx.i != len) || (!cs_change && rx.i == len)) + _xil_spi_start_transfer(desc, 0); + } while (rx.i < len); + + return 0; +} + +const struct spi_platform_ops xil_spi_pl_ops = { + .init = xil_spi_init_pl, + .remove = xil_spi_remove_pl, + .write_and_read = xil_spi_write_and_read_pl, + .transfer = xil_spi_transfer_pl +}; + +#endif // XPAR_XSPI_NUM_INSTANCES diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.c b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.c new file mode 100644 index 0000000..0305df3 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.c @@ -0,0 +1,7475 @@ +/***************************************************************************//** + * @file ad9361.c + * @brief Implementation of AD9361 Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "spi.h" +#include "gpio.h" +#include "delay.h" +#include "util.h" +#include "../../../config/app_config.h" + +#define diff_abs(x, y) ((x) > (y) ? (x - y) : (y - x)) + +#define NO_GAIN_TABLE ((uint32_t)-1) + +/* Used for static code size optimization: please see app_config.h */ +const bool has_split_gt = HAVE_SPLIT_GAIN_TABLE; +const bool have_tdd_tables = HAVE_TDD_SYNTH_TABLE; + +#define SYNTH_LUT_SIZE 53 + +static const struct SynthLUT SynthLUT_FDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 5, 15}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 14, 5, 15}, + {11588, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 14, 5, 15}, + {11007, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 14, 5, 15}, + {10492, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 14, 5, 15}, + {10036, 13, 1, 6, 2, 15, 12, 11, 15, 6, 14, 5, 15}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 14, 5, 15}, + {9631, 13, 1, 6, 2, 13, 12, 12, 15, 6, 14, 5, 15}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 14, 5, 15}, + {9269, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8946, 13, 1, 6, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 14, 5, 15}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 14, 5, 15}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 14, 5, 15}, + {8153, 12, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 14, 5, 15}, + {7934, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7733, 10, 1, 7, 3, 13, 12, 16, 15, 6, 14, 5, 15}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 14, 5, 15}, + {7547, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 14, 5, 15}, + {7374, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 14, 5, 15}, + {7135, 10, 2, 7, 3, 14, 13, 15, 15, 7, 14, 5, 15}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6988, 10, 1, 7, 3, 12, 14, 20, 15, 6, 14, 5, 15}, + {6918, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6720, 9, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 14, 5, 15}, + {6482, 8, 2, 7, 2, 13, 13, 16, 15, 6, 14, 5, 15}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 14, 5, 15}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6270, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 14, 5, 15}, + {6083, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 14, 5, 15}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 13, 15, 12, 12, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 13, 15, 13, 12, 5, 13}, + {11588, 13, 1, 4, 2, 15, 12, 14, 15, 13, 12, 5, 13}, + {11288, 13, 1, 5, 2, 15, 12, 15, 15, 13, 12, 5, 13}, + {11007, 13, 1, 5, 2, 15, 12, 16, 15, 13, 12, 5, 13}, + {10742, 13, 1, 5, 2, 15, 12, 16, 15, 12, 12, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 17, 15, 12, 12, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 18, 15, 13, 12, 5, 13}, + {10036, 13, 1, 6, 2, 15, 12, 19, 15, 13, 12, 5, 13}, + {9827, 13, 1, 6, 2, 14, 12, 20, 15, 13, 12, 5, 13}, + {9631, 13, 1, 6, 2, 13, 12, 21, 15, 13, 12, 5, 13}, + {9445, 13, 1, 6, 2, 12, 12, 22, 15, 13, 12, 5, 13}, + {9269, 13, 1, 6, 2, 12, 12, 22, 15, 12, 12, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 23, 15, 13, 12, 5, 13}, + {8946, 13, 1, 6, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8797, 12, 1, 7, 2, 12, 12, 24, 15, 13, 12, 5, 13}, + {8655, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8520, 12, 1, 7, 2, 12, 12, 25, 15, 13, 12, 5, 13}, + {8392, 12, 1, 7, 2, 12, 12, 26, 15, 13, 12, 5, 13}, + {8269, 12, 1, 7, 2, 12, 12, 27, 15, 13, 12, 5, 13}, + {8153, 12, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {8041, 12, 1, 7, 2, 13, 12, 29, 15, 13, 12, 5, 13}, + {7934, 11, 1, 7, 2, 12, 12, 28, 15, 13, 12, 5, 13}, + {7831, 11, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7733, 10, 1, 7, 3, 13, 12, 28, 15, 13, 12, 5, 13}, + {7638, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7547, 10, 1, 7, 2, 12, 12, 29, 15, 13, 12, 5, 13}, + {7459, 10, 1, 7, 2, 12, 12, 30, 15, 13, 12, 5, 13}, + {7374, 10, 2, 7, 3, 14, 13, 24, 15, 13, 12, 5, 13}, + {7291, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7212, 10, 2, 7, 3, 14, 13, 25, 15, 13, 12, 5, 13}, + {7135, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {7061, 10, 2, 7, 3, 14, 13, 26, 15, 13, 12, 5, 13}, + {6988, 10, 1, 7, 3, 12, 14, 35, 15, 13, 12, 5, 13}, + {6918, 9, 1, 7, 3, 12, 14, 33, 15, 13, 12, 5, 13}, + {6850, 9, 1, 7, 3, 12, 14, 34, 15, 13, 12, 5, 13}, + {6784, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6720, 9, 1, 7, 2, 11, 14, 35, 15, 13, 12, 5, 13}, + {6658, 8, 2, 7, 3, 15, 13, 26, 15, 13, 12, 5, 13}, + {6597, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6539, 8, 2, 7, 2, 15, 13, 27, 15, 13, 12, 5, 13}, + {6482, 8, 2, 7, 2, 15, 13, 28, 15, 13, 12, 5, 13}, + {6427, 7, 2, 7, 3, 14, 13, 27, 15, 13, 12, 5, 13}, + {6373, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6321, 7, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6270, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6222, 7, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6174, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6128, 6, 2, 7, 3, 15, 13, 27, 15, 13, 12, 5, 13}, + {6083, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {6040, 6, 2, 7, 3, 15, 13, 28, 15, 13, 12, 5, 13}, + {5997, 6, 2, 7, 3, 15, 13, 29, 15, 13, 12, 5, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11906, 13, 1, 4, 2, 15, 12, 7, 15, 6, 13, 5, 14}, + {11588, 13, 1, 4, 2, 15, 12, 7, 14, 6, 14, 4, 14}, + {11288, 13, 1, 4, 2, 15, 12, 8, 15, 6, 13, 5, 14}, + {11007, 13, 1, 4, 2, 15, 12, 8, 14, 6, 13, 5, 14}, + {10742, 13, 1, 4, 2, 15, 12, 9, 15, 6, 13, 5, 14}, + {10492, 13, 1, 6, 2, 15, 12, 9, 14, 6, 13, 5, 14}, + {10258, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {10036, 13, 1, 6, 2, 15, 12, 10, 15, 6, 13, 5, 14}, + {9827, 13, 1, 6, 2, 14, 12, 11, 15, 6, 13, 5, 14}, + {9631, 13, 1, 6, 2, 13, 12, 11, 15, 6, 13, 5, 14}, + {9445, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9269, 13, 1, 6, 2, 12, 12, 12, 15, 6, 13, 5, 14}, + {9103, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8946, 13, 1, 6, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8797, 12, 1, 7, 2, 12, 12, 13, 15, 6, 13, 5, 14}, + {8655, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8520, 12, 1, 7, 2, 12, 12, 14, 15, 6, 13, 5, 14}, + {8392, 12, 1, 7, 2, 12, 12, 15, 15, 7, 13, 5, 14}, + {8269, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8153, 12, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {8041, 12, 1, 7, 2, 13, 12, 16, 15, 6, 13, 5, 14}, + {7934, 11, 1, 7, 2, 12, 12, 15, 15, 6, 13, 5, 14}, + {7831, 11, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7733, 10, 1, 7, 3, 13, 12, 15, 15, 6, 13, 5, 14}, + {7638, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7547, 10, 1, 7, 2, 12, 12, 16, 15, 6, 13, 5, 14}, + {7459, 10, 1, 7, 2, 12, 12, 17, 15, 6, 13, 5, 14}, + {7374, 10, 2, 7, 3, 14, 13, 13, 15, 6, 13, 5, 14}, + {7291, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7212, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7135, 10, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {7061, 10, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6988, 10, 1, 7, 3, 12, 14, 19, 15, 6, 13, 5, 14}, + {6918, 9, 2, 7, 3, 14, 13, 14, 15, 6, 13, 5, 14}, + {6850, 9, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6784, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6720, 9, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6658, 8, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6597, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6539, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6482, 8, 2, 7, 2, 13, 13, 15, 15, 6, 13, 5, 14}, + {6427, 7, 2, 7, 3, 14, 13, 15, 15, 6, 13, 5, 14}, + {6373, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6321, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6270, 7, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6222, 7, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {6174, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6128, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6083, 6, 2, 7, 3, 15, 13, 15, 15, 6, 13, 5, 14}, + {6040, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + {5997, 6, 2, 7, 3, 15, 13, 16, 15, 6, 13, 5, 14}, + } +}; + +static const struct SynthLUT SynthLUT_TDD[LUT_FTDD_ENT][SYNTH_LUT_SIZE] = { + { + {12605, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, /* 40 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 27, 12, 15, 12, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 11, 15, 12, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 28, 12, 15, 12, 4, 13}, + {11288, 13, 1, 4, 2, 15, 12, 30, 12, 15, 12, 4, 13}, + {11007, 13, 1, 4, 2, 15, 12, 32, 12, 15, 12, 4, 13}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 12, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 35, 12, 15, 12, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 37, 12, 15, 12, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 12, 4, 13}, + {9827, 13, 1, 6, 2, 14, 12, 40, 12, 15, 12, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 42, 12, 15, 12, 4, 13}, + {9445, 13, 1, 6, 2, 12, 12, 44, 12, 15, 12, 4, 13}, + {9269, 13, 1, 6, 2, 12, 12, 45, 12, 15, 12, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 47, 12, 15, 12, 4, 13}, + {8946, 13, 1, 6, 2, 12, 12, 49, 12, 15, 12, 4, 13}, + {8797, 12, 1, 7, 2, 12, 12, 48, 12, 15, 12, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 50, 12, 15, 12, 4, 13}, + {8520, 12, 1, 7, 2, 12, 12, 51, 12, 15, 12, 4, 13}, + {8392, 12, 1, 7, 2, 12, 12, 53, 12, 15, 12, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 55, 12, 15, 12, 4, 13}, + {8153, 12, 1, 7, 2, 12, 12, 56, 12, 15, 12, 4, 13}, + {8041, 12, 1, 7, 2, 13, 12, 58, 12, 15, 12, 4, 13}, + {7934, 11, 1, 7, 2, 12, 12, 57, 12, 15, 12, 4, 13}, + {7831, 11, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 56, 12, 15, 12, 4, 13}, + {7638, 10, 1, 7, 2, 12, 12, 58, 12, 15, 12, 4, 13}, + {7547, 10, 1, 7, 2, 12, 12, 59, 12, 15, 12, 4, 13}, + {7459, 10, 1, 7, 2, 12, 12, 61, 12, 15, 12, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 49, 12, 15, 12, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 50, 12, 15, 12, 4, 13}, + {7212, 10, 2, 7, 3, 14, 13, 51, 12, 15, 12, 4, 13}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 14, 12, 3, 13}, + {6918, 9, 2, 7, 3, 14, 13, 52, 12, 15, 12, 4, 13}, + {6850, 9, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6784, 9, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 53, 12, 15, 12, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 54, 12, 15, 12, 4, 13}, + {6539, 8, 2, 7, 2, 13, 13, 55, 12, 15, 12, 4, 13}, + {6482, 8, 2, 7, 2, 13, 13, 56, 12, 15, 12, 4, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 12, 4, 13}, + {6373, 7, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6270, 7, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6222, 7, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {6174, 6, 2, 7, 3, 15, 13, 54, 12, 15, 12, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 12, 4, 13}, + {6083, 6, 2, 7, 3, 15, 13, 56, 12, 15, 12, 4, 13}, + {6040, 6, 2, 7, 3, 15, 13, 57, 12, 15, 12, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 58, 12, 15, 12, 4, 13}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, /* 60 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 26, 11, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 26, 12, 15, 11, 4, 12}, + {11588, 13, 1, 4, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {11288, 13, 1, 4, 2, 15, 12, 32, 12, 15, 10, 4, 12}, + {11007, 13, 1, 4, 2, 15, 12, 31, 12, 15, 11, 4, 12}, + {10742, 13, 1, 4, 2, 15, 12, 33, 12, 15, 10, 4, 12}, + {10492, 13, 1, 6, 2, 15, 12, 37, 12, 15, 10, 4, 12}, + {10258, 13, 1, 6, 2, 15, 12, 38, 12, 15, 11, 4, 13}, + {10036, 13, 1, 6, 2, 15, 12, 38, 12, 15, 10, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 42, 12, 15, 11, 4, 12}, + {9631, 13, 1, 6, 2, 13, 12, 41, 12, 15, 11, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 47, 12, 15, 11, 4, 12}, + {9103, 13, 1, 6, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 48, 12, 15, 10, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 49, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 51, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 50, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 52, 12, 15, 10, 4, 12}, + {8269, 12, 1, 7, 2, 12, 12, 56, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 57, 12, 15, 10, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 55, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 57, 12, 15, 10, 4, 12}, + {7733, 10, 1, 7, 3, 13, 12, 55, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 59, 12, 15, 10, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 60, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 48, 12, 15, 11, 4, 12}, + {7374, 10, 2, 7, 3, 14, 13, 47, 12, 15, 11, 4, 13}, + {7291, 10, 2, 7, 3, 14, 13, 49, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 50, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 13}, + {7061, 10, 2, 7, 3, 14, 13, 52, 12, 15, 11, 4, 12}, + {6988, 10, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6918, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6850, 9, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6784, 9, 1, 7, 2, 11, 14, 63, 11, 15, 11, 4, 13}, + {6720, 9, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6658, 8, 1, 7, 3, 12, 14, 63, 11, 15, 11, 4, 13}, + {6597, 8, 1, 7, 2, 11, 14, 63, 11, 14, 11, 3, 13}, + {6539, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6482, 8, 1, 7, 2, 11, 14, 63, 10, 14, 11, 3, 13}, + {6427, 7, 2, 7, 3, 14, 13, 54, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6321, 7, 2, 7, 3, 15, 13, 54, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 56, 12, 15, 11, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 53, 12, 15, 11, 4, 12}, + {6128, 6, 2, 7, 3, 15, 13, 55, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 55, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 56, 12, 15, 10, 4, 12}, + {5997, 6, 2, 7, 3, 15, 13, 57, 12, 15, 10, 4, 12}, + }, { + {12605, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, /* 80 MHz */ + {12245, 13, 1, 4, 2, 15, 12, 21, 12, 15, 11, 4, 13}, + {11906, 13, 1, 4, 2, 15, 12, 20, 11, 15, 11, 4, 13}, + {11588, 13, 1, 4, 2, 15, 12, 22, 12, 15, 11, 4, 12}, + {11288, 13, 1, 5, 2, 15, 12, 23, 12, 15, 11, 4, 13}, + {11007, 13, 1, 5, 2, 15, 12, 25, 12, 15, 10, 4, 12}, + {10742, 13, 1, 5, 2, 15, 12, 26, 12, 15, 11, 4, 13}, + {10492, 13, 1, 6, 2, 15, 12, 27, 11, 15, 11, 4, 13}, + {10258, 13, 1, 6, 2, 15, 12, 29, 12, 15, 10, 4, 12}, + {10036, 13, 1, 6, 2, 15, 12, 30, 12, 15, 11, 4, 12}, + {9827, 13, 1, 6, 2, 14, 12, 31, 12, 15, 11, 4, 13}, + {9631, 13, 1, 6, 2, 13, 12, 33, 12, 15, 10, 4, 12}, + {9445, 13, 1, 6, 2, 12, 12, 34, 12, 15, 11, 4, 12}, + {9269, 13, 1, 6, 2, 12, 12, 35, 12, 15, 11, 4, 13}, + {9103, 13, 1, 6, 2, 12, 12, 37, 12, 15, 10, 4, 12}, + {8946, 13, 1, 6, 2, 12, 12, 38, 12, 15, 11, 4, 12}, + {8797, 12, 1, 7, 2, 12, 12, 37, 12, 15, 11, 4, 13}, + {8655, 12, 1, 7, 2, 12, 12, 39, 12, 15, 11, 4, 12}, + {8520, 12, 1, 7, 2, 12, 12, 40, 12, 15, 11, 4, 12}, + {8392, 12, 1, 7, 2, 12, 12, 41, 12, 15, 11, 4, 13}, + {8269, 12, 1, 7, 2, 12, 12, 43, 12, 15, 10, 4, 12}, + {8153, 12, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {8041, 12, 1, 7, 2, 13, 12, 45, 12, 15, 11, 4, 12}, + {7934, 11, 1, 7, 2, 12, 12, 44, 12, 15, 11, 4, 12}, + {7831, 11, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 13}, + {7733, 10, 1, 7, 3, 13, 12, 44, 12, 15, 11, 4, 12}, + {7638, 10, 1, 7, 2, 12, 12, 45, 12, 15, 11, 4, 12}, + {7547, 10, 1, 7, 2, 12, 12, 46, 12, 15, 11, 4, 12}, + {7459, 10, 1, 7, 2, 12, 12, 47, 12, 15, 11, 4, 13}, + {7374, 10, 2, 7, 3, 14, 13, 38, 12, 15, 11, 4, 12}, + {7291, 10, 2, 7, 3, 14, 13, 39, 12, 15, 10, 4, 12}, + {7212, 10, 2, 7, 3, 14, 13, 40, 12, 15, 10, 4, 12}, + {7135, 10, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {7061, 10, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6988, 10, 1, 7, 3, 12, 14, 54, 12, 15, 11, 4, 12}, + {6918, 9, 2, 7, 3, 14, 13, 41, 12, 15, 10, 4, 12}, + {6850, 9, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6784, 9, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 13}, + {6720, 9, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 13}, + {6658, 8, 2, 7, 3, 14, 13, 41, 12, 15, 11, 4, 13}, + {6597, 8, 2, 7, 2, 13, 13, 42, 12, 15, 11, 4, 12}, + {6539, 8, 2, 7, 2, 13, 13, 43, 12, 15, 11, 4, 12}, + {6482, 8, 2, 7, 2, 13, 13, 44, 12, 15, 11, 4, 12}, + {6427, 7, 2, 7, 3, 14, 13, 42, 12, 15, 10, 4, 12}, + {6373, 7, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6321, 7, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6270, 7, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 12}, + {6222, 7, 2, 7, 3, 15, 13, 45, 12, 15, 10, 4, 12}, + {6174, 6, 2, 7, 3, 15, 13, 42, 12, 15, 11, 4, 13}, + {6128, 6, 2, 7, 3, 15, 13, 43, 12, 15, 11, 4, 12}, + {6083, 6, 2, 7, 3, 15, 13, 44, 12, 15, 10, 4, 12}, + {6040, 6, 2, 7, 3, 15, 13, 44, 12, 15, 11, 4, 13}, + {5997, 6, 2, 7, 3, 15, 13, 45, 12, 15, 11, 4, 12}, + } +}; + +/* Rx Gain Tables */ + +#define SIZE_FULL_TABLE 77 + +static const uint8_t full_gain_table[RXGAIN_TBLS_END][SIZE_FULL_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x28, 0x20}, {0x04, 0x29, 0x00}, {0x04, 0x2A, 0x00}, + {0x04, 0x2B, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, {0x44, 0x22, 0x00}, + {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, {0x44, 0x25, 0x00}, + {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, {0x44, 0x28, 0x00}, + {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, {0x44, 0x2B, 0x00}, + {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, {0x44, 0x2E, 0x00}, + {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, {0x44, 0x31, 0x00}, + {0x44, 0x32, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + },{ /* 2300 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x01, 0x00}, {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, + {0x00, 0x04, 0x00}, {0x00, 0x05, 0x00}, {0x01, 0x03, 0x20}, + {0x01, 0x04, 0x00}, {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, + {0x01, 0x07, 0x00}, {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, + {0x01, 0x0A, 0x00}, {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, + {0x01, 0x0D, 0x00}, {0x01, 0x0E, 0x00}, {0x02, 0x09, 0x20}, + {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x00}, {0x02, 0x0C, 0x00}, + {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, {0x02, 0x0F, 0x00}, + {0x02, 0x10, 0x00}, {0x02, 0x2B, 0x20}, {0x02, 0x2C, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x24, 0x21, 0x20}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x44, 0x2F, 0x00}, {0x44, 0x30, 0x00}, + {0x44, 0x31, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x00, 0x20}, {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, + {0x00, 0x00, 0x00}, {0x00, 0x00, 0x00}, {0x00, 0x01, 0x00}, + {0x00, 0x02, 0x00}, {0x00, 0x03, 0x00}, {0x01, 0x01, 0x20}, + {0x01, 0x02, 0x00}, {0x01, 0x03, 0x00}, {0x01, 0x04, 0x20}, + {0x01, 0x05, 0x00}, {0x01, 0x06, 0x00}, {0x01, 0x07, 0x00}, + {0x01, 0x08, 0x00}, {0x01, 0x09, 0x00}, {0x01, 0x0A, 0x00}, + {0x01, 0x0B, 0x00}, {0x01, 0x0C, 0x00}, {0x02, 0x08, 0x20}, + {0x02, 0x09, 0x00}, {0x02, 0x0A, 0x00}, {0x02, 0x0B, 0x20}, + {0x02, 0x0C, 0x00}, {0x02, 0x0D, 0x00}, {0x02, 0x0E, 0x00}, + {0x02, 0x0F, 0x00}, {0x02, 0x2A, 0x20}, {0x02, 0x2B, 0x00}, + {0x04, 0x27, 0x20}, {0x04, 0x28, 0x00}, {0x04, 0x29, 0x00}, + {0x04, 0x2A, 0x00}, {0x04, 0x2B, 0x00}, {0x04, 0x2C, 0x00}, + {0x04, 0x2D, 0x00}, {0x24, 0x20, 0x20}, {0x24, 0x21, 0x00}, + {0x24, 0x22, 0x00}, {0x44, 0x20, 0x20}, {0x44, 0x21, 0x00}, + {0x44, 0x22, 0x00}, {0x44, 0x23, 0x00}, {0x44, 0x24, 0x00}, + {0x44, 0x25, 0x00}, {0x44, 0x26, 0x00}, {0x44, 0x27, 0x00}, + {0x44, 0x28, 0x00}, {0x44, 0x29, 0x00}, {0x44, 0x2A, 0x00}, + {0x44, 0x2B, 0x00}, {0x44, 0x2C, 0x00}, {0x44, 0x2D, 0x00}, + {0x44, 0x2E, 0x00}, {0x64, 0x2E, 0x20}, {0x64, 0x2F, 0x00}, + {0x64, 0x30, 0x00}, {0x64, 0x31, 0x00}, {0x64, 0x32, 0x00}, + {0x64, 0x33, 0x00}, {0x64, 0x34, 0x00}, {0x64, 0x35, 0x00}, + {0x64, 0x36, 0x00}, {0x64, 0x37, 0x00}, {0x64, 0x38, 0x00}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20} + } +}; + +static const int8_t full_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_FULL_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, 0, 1, 2, 3, 4, + 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, + 21, 22, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, + 37, 38, 39, 40, 41, 42, 43, 44, + 45, 46, 47, 48, 49, 50, 51, 52, + 53, 54, 55, 56, 57, 58, 59, 60, + 61, 62, 63, 64, 65, 66, 67, 68, + 69, 70, 71, 72, 73 + }, { /* 2300 MHz */ + -3, -3, -3, -2, -1, 0, 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 23, 24, 25, 26, + 27, 28, 29, 30, 31, 32, 33, 34, + 35, 36, 37, 38, 39, 40, 41, 42, + 43, 44, 45, 46, 47, 48, 49, 50, + 51, 52, 53, 54, 55, 56, 57, 58, + 59, 60, 61, 62, 63, 64, 65, 66, + 67, 68, 69, 70, 71 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -9, -8, -7, + -6, -5, -4, -3, -2, -1, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, + 42, 43, 44, 45, 46, 47, 48, 49, + 50, 51, 52, 53, 54, 55, 56, 57, + 58, 59, 60, 61, 62 + } +}; + +#define SIZE_SPLIT_TABLE 41 + +#if HAVE_SPLIT_GAIN_TABLE +static const uint8_t split_gain_table[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE][3] = { + { /* 800 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x24, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, {0x46, 0x38, 0x20}, + {0x47, 0x38, 0x20}, {0x48, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 2300 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x20}, {0x01, 0x18, 0x20}, + {0x02, 0x18, 0x20}, {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, + {0x05, 0x38, 0x20}, {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, + {0x08, 0x38, 0x20}, {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, + {0x0B, 0x38, 0x20}, {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, + {0x0E, 0x38, 0x20}, {0x0F, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x45, 0x38, 0x20}, + {0x46, 0x38, 0x20}, {0x47, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + },{ /* 5500 MHz */ + {0x00, 0x18, 0x20}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, {0x00, 0x18, 0x00}, + {0x00, 0x18, 0x00}, {0x01, 0x18, 0x20}, {0x02, 0x18, 0x20}, + {0x04, 0x18, 0x20}, {0x04, 0x38, 0x20}, {0x05, 0x38, 0x20}, + {0x06, 0x38, 0x20}, {0x07, 0x38, 0x20}, {0x08, 0x38, 0x20}, + {0x09, 0x38, 0x20}, {0x0A, 0x38, 0x20}, {0x0B, 0x38, 0x20}, + {0x0C, 0x38, 0x20}, {0x0D, 0x38, 0x20}, {0x0E, 0x38, 0x20}, + {0x0F, 0x38, 0x20}, {0x62, 0x38, 0x20}, {0x25, 0x38, 0x20}, + {0x26, 0x38, 0x20}, {0x44, 0x38, 0x20}, {0x64, 0x38, 0x20}, + {0x65, 0x38, 0x20}, {0x66, 0x38, 0x20}, {0x67, 0x38, 0x20}, + {0x68, 0x38, 0x20}, {0x69, 0x38, 0x20}, {0x6A, 0x38, 0x20}, + {0x6B, 0x38, 0x20}, {0x6C, 0x38, 0x20}, {0x6D, 0x38, 0x20}, + {0x6E, 0x38, 0x20}, {0x6F, 0x38, 0x20}, + } +}; + +static const uint8_t +split_gain_table_abs_gain[RXGAIN_TBLS_END][SIZE_SPLIT_TABLE] = { + { /* 800 MHz */ + -1, -1, -1, -1, -1, -1, -1, 2, + 8, 13, 19, 20, 21, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, + 49 + }, { /* 2300 MHz */ + -3, -3, -3, -3, -3, -3, -3, -3, + 0, 6, 12, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, + 47 + }, { /* 5500 MHz */ + -10, -10, -10, -10, -10, -10, -10, -10, + -10, -10, -7, -2, 3, 9, 10, 11, + 12, 13, 14, 15, 16, 17, 18, 19, + 20, 22, 24, 25, 26, 27, 28, 29, + 30, 31, 32, 33, 34, 35, 36, 37, + 38 + } +}; +#endif + +struct gain_table_info ad9361_adi_gt_info[] = { + { + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_FULL_TABLE, + .abs_gain_tbl = (int8_t *) &full_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) full_gain_table[TBL_4000_6000_MHZ], +#if HAVE_SPLIT_GAIN_TABLE + },{ + .start = 0, + .end = 1300000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_200_1300_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_200_1300_MHZ], + },{ + .start = 1300000000ULL, + .end = 4000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_1300_4000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_1300_4000_MHZ], + },{ + .start = 4000000000ULL, + .end = 6000000000ULL, + .max_index = SIZE_SPLIT_TABLE, + .split_table = 1, + .abs_gain_tbl = (int8_t *) &split_gain_table_abs_gain[TBL_4000_6000_MHZ], + .tab = (uint8_t (*)[3]) split_gain_table[TBL_4000_6000_MHZ], +#endif + },{ + .start = 0, + .end = 0, + .max_index = 0, + .split_table = 0, + .abs_gain_tbl = NULL, + .tab = NULL, + }, /* Don't Remove */ +}; + +/* Mixer GM Sub-table */ + +static const uint8_t gm_st_gain[16]= {0x78, 0x74, 0x70, 0x6C, 0x68, 0x64, 0x60, + 0x5C, 0x58, 0x54, 0x50, 0x4C, 0x48, 0x30, 0x18, 0x0}; +static const uint8_t gm_st_ctrl[16]= {0x0, 0xD, 0x15, 0x1B, 0x21, 0x25, 0x29, + 0x2C, 0x2F, 0x31, 0x33, 0x34, 0x35, 0x3A, 0x3D, 0x3E}; + + +static const int8_t lna_table[RXGAIN_TBLS_END][4] = { + {5, 17, 19, 24}, {3, 14, 17, 21}, {-4, 10, 13, 14}}; +static const int8_t tia_table[] = {-6, 0}; +static const int8_t mixer_table[RXGAIN_TBLS_END][16] = { + {0, 3, 9, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25}, + {0, 3, 9, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26}, + {0, 3, 8, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24} +}; + +static const uint32_t gain_step_calib_reg_val[4][5] = { + {0xC0, 0x2E, 0x10, 0x06, 0x00}, // LO Frequency Range: 600 to 1300 MHz + {0xC0, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 1300 to 3300 MHz + {0xB8, 0x2C, 0x10, 0x06, 0x00}, // LO Frequency Range: 2700 to 4100 MHz + {0xA0, 0x24, 0x10, 0x06, 0x00}, // LO Frequency Range: 4000 to 6000 MHz +}; + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +const char *ad9361_ensm_states[] = { + "sleep", "", "", "", "", "alert", "tx", "tx flush", + "rx", "rx_flush", "fdd", "fdd_flush" +}; + +/** + * SPI multiple bytes register read. + * @param spi + * @param reg The register address. + * @param rbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num) +{ + int32_t ret = 0; + uint16_t cmd; + uint8_t *rbuffer; + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_READ | AD_CNT(num) | AD_ADDR(reg); + rbuffer = malloc(num + 2); + if(!rbuffer) + return -ENOMEM; + rbuffer[0] = cmd >> 8; + rbuffer[1] = cmd & 0xFF; + ret = spi_write_and_read(spi, &rbuffer[0], 2 + num); + + if (ret < 0) + dev_err(&spi->dev, "Read Error %"PRId32, ret); + else + memcpy(rbuf, &rbuffer[2], num); + + free(rbuffer); +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", + __func__, reg--, rbuf[i]); + } +#endif + + return ret; +} + +/** + * SPI register read. + * @param spi + * @param reg The register address. + * @return The register value or negative error code in case of failure. + */ +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg) +{ + uint8_t buf; + int32_t ret; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @return The bits value or negative error code in case of failure. + */ +static int32_t __ad9361_spi_readf(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= mask; + buf >>= offset; + + return buf; +} + +/** + * SPI register bits read. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @return The bits value or negative error code in case of failure. + */ +#define ad9361_spi_readf(spi, reg, mask) \ + __ad9361_spi_readf(spi, reg, mask, find_first_bit(mask)) + +/** + * SPI register write. + * @param spi + * @param reg The register address. + * @param val The value of the register. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val) +{ + uint8_t buf[3]; + int32_t ret; + uint16_t cmd; + + cmd = AD_WRITE | AD_CNT(1) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + buf[2] = val; + + ret = spi_write_and_read(spi, buf, 3); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + dev_dbg(&spi->dev, "%s: reg 0x%"PRIX32" val 0x%X", __func__, reg, buf[2]); +#endif + + return 0; +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param offset The mask offset. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_spi_writef(struct spi_desc *spi, uint32_t reg, + uint32_t mask, uint32_t offset, uint32_t val) +{ + uint8_t buf; + int32_t ret; + + if (!mask) + return -EINVAL; + + ret = ad9361_spi_readm(spi, reg, &buf, 1); + if (ret < 0) + return ret; + + buf &= ~mask; + buf |= ((val << offset) & mask); + + return ad9361_spi_write(spi, reg, buf); +} + +/** + * SPI register bits write. + * @param spi + * @param reg The register address. + * @param mask The bits mask. + * @param val The bits value. + * @return 0 in case of success, negative error code otherwise. + */ +#define ad9361_spi_writef(spi, reg, mask, val) \ + __ad9361_spi_writef(spi, reg, mask, find_first_bit(mask), val) + +/** + * SPI multiple bytes register write. + * @param spi + * @param reg The register address. + * @param tbuf The data buffer. + * @param num The number of bytes to read. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_spi_writem(struct spi_desc *spi, + uint32_t reg, uint8_t *tbuf, uint32_t num) +{ + uint8_t buf[10]; + int32_t ret; + uint16_t cmd; + + if (num > MAX_MBYTE_SPI) + return -EINVAL; + + cmd = AD_WRITE | AD_CNT(num) | AD_ADDR(reg); + buf[0] = cmd >> 8; + buf[1] = cmd & 0xFF; + +#ifndef ALTERA_PLATFORM + memcpy(&buf[2], tbuf, num); +#else + int32_t i; + for (i = 0; i < num; i++) + buf[2 + i] = tbuf[i]; +#endif + ret = spi_write_and_read(spi, buf, num + 2); + if (ret < 0) { + dev_err(&spi->dev, "Write Error %"PRId32, ret); + return ret; + } + +#ifdef _DEBUG + { + int32_t i; + for (i = 0; i < num; i++) + dev_dbg(&spi->dev, "Reg 0x%"PRIX32" val 0x%X", reg--, tbuf[i]); + } +#endif + + return 0; +} + +/** + * Validate RF BW frequency. + * @param phy The AD9361 state structure. + * @param bw The RF BW frequency. + * @return The validated RF BW frequency. + */ +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + return clamp_t(uint32_t, bw, 200000UL, 20000000UL); + default: + return clamp_t(uint32_t, bw, 200000UL, 56000000UL); + } +} + +/** + * Validate RF PLL frequency. + * @param phy The AD9361 state structure. + * @param is_tx TX enabled. + * @param freq The RF PLL frequency. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_rfpll(struct ad9361_rf_phy *phy, bool is_tx, + uint64_t freq) +{ + switch (phy->dev_sel) { + case ID_AD9363A: + if (freq > AD9363A_MAX_CARRIER_FREQ_HZ || + freq < AD9363A_MIN_CARRIER_FREQ_HZ) + return -EINVAL; + break; + default: + if (freq > MAX_CARRIER_FREQ_HZ || freq < (is_tx ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + } + + return 0; +} + +/** + * Find optimal value. + * @param field + * @param size + * @param ret_start + * @return The optimal delay in case of success, negative error code otherwise. + */ +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start) +{ + int32_t i, cnt = 0, max_cnt = 0, start, max_start = 0; + + for(i = 0, start = -1; i < (int64_t)size; i++) { + if (field[i] == 0) { + if (start == -1) + start = i; + cnt++; + } else { + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + start = -1; + cnt = 0; + } + } + + if (cnt > max_cnt) { + max_cnt = cnt; + max_start = start; + } + + *ret_start = max_start; + + return max_cnt; +} + +/** + * Select the channel mapping in 1rx1tx mode. + * @param phy The AD9361 state structure. + * @param tx TX + * @param channel Channel + * @return The channel number. + */ +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel) +{ + uint32_t map; + + if (phy->pdata->rx2tx2) + return channel; + + if (tx) + map = phy->pdata->rx1tx1_mode_use_tx_num; + else + map = phy->pdata->rx1tx1_mode_use_rx_num; + + if (map == 2) + return channel + 1; + + return channel; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reset(struct ad9361_rf_phy *phy) +{ + if (phy->gpio_desc_resetb) { + gpio_set_value(phy->gpio_desc_resetb, 0); + mdelay(1); + gpio_set_value(phy->gpio_desc_resetb, 1); + mdelay(1); + dev_dbg(&phy->spi->dev, "%s: by GPIO", __func__); + return 0; + } + + /* SPI Soft Reset was removed from the register map, since it doesn't + * work reliably. Without a prober HW reset randomness may happen. + * Please specify a RESET GPIO. + */ + + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + dev_err(&phy->spi->dev, + "%s: by SPI, this may cause unpredicted behavior!", __func__); + + return -ENODEV; +} + +/** + * Enable/disable the desired TX channel. + * @param phy The AD9361 state structure. + * @param tx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable) +{ + if ((tx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_CHANNEL_ENABLE(tx_if), enable); +} + +/** + * Enable/disable the desired RX channel. + * @param phy The AD9361 state structure. + * @param rx_if The desired channel number [1, 2]. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable) +{ + if ((rx_if & enable) > 1 && AD9364_DEVICE && enable) + return -EINVAL; + + return ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_CHANNEL_ENABLE(rx_if), enable); +} + +/** + * Loopback works only TX1->RX1 or RX2->RX2. + * @param phy The AD9361 state structure. + * @param enable Enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_int_loopback_fix_ch_cross(struct ad9361_rf_phy *phy, + bool enable) +{ + /* Loopback works only TX1->RX1 or RX2->RX2 */ + if (!phy->pdata->rx2tx2 && phy->pdata->rx1tx1_mode_use_rx_num != + phy->pdata->rx1tx1_mode_use_tx_num) + return ad9361_en_dis_tx(phy, TX_1 | TX_2, + enable ? phy->pdata->rx1tx1_mode_use_rx_num : + phy->pdata->rx1tx1_mode_use_tx_num); + + return 0; +} + +/** + * BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode) +{ + uint32_t sp_hd, reg; + + dev_dbg(&phy->spi->dev, "%s: mode %"PRId32, __func__, mode); + + reg = ad9361_spi_read(phy->spi, REG_OBSERVE_CONFIG); + + phy->bist_loopback_mode = mode; + + switch (mode) { + case 0: + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 1: + /* loopback (AD9361 internal) TX->RX */ + ad9361_hdl_loopback(phy, false); + ad9361_int_loopback_fix_ch_cross(phy, true); + sp_hd = ad9361_spi_read(phy->spi, REG_PARALLEL_PORT_CONF_3); + if ((sp_hd & SINGLE_PORT_MODE) && (sp_hd & HALF_DUPLEX_MODE)) + reg |= DATA_PORT_SP_HD_LOOP_TEST_OE; + else + reg &= ~DATA_PORT_SP_HD_LOOP_TEST_OE; + + reg |= DATA_PORT_LOOP_TEST_ENABLE; + + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + case 2: + /* loopback (FPGA internal) RX->TX */ + ad9361_hdl_loopback(phy, true); + ad9361_int_loopback_fix_ch_cross(phy, false); + reg &= ~(DATA_PORT_SP_HD_LOOP_TEST_OE | + DATA_PORT_LOOP_TEST_ENABLE); + return ad9361_spi_write(phy->spi, REG_OBSERVE_CONFIG, reg); + default: + return -EINVAL; + } +} + +/** + * Get BIST loopback mode. + * @param phy The AD9361 state structure. + * @param mode BIST loopback mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode) +{ + *mode = phy->bist_loopback_mode; +} + +/** + * BIST mode. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode) +{ + uint32_t reg = 0; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_prbs_mode = mode; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST mode settings. + * @param phy The AD9361 state structure. + * @param mode Bist mode. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode) +{ + *mode = phy->bist_prbs_mode; +} + +/** + * BIST tone. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask) +{ + uint32_t clk = 0; + uint32_t reg = 0, reg1, reg_mask; + + dev_dbg(&phy->spi->dev, "%s: mode %d", __func__, mode); + + phy->bist_tone_mode = mode; + phy->bist_tone_freq_Hz = freq_Hz; + phy->bist_tone_level_dB = level_dB; + phy->bist_tone_mask = mask; + + switch (mode) { + case BIST_DISABLE: + reg = 0; + break; + case BIST_INJ_TX: + clk = clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(0) | BIST_ENABLE; + break; + case BIST_INJ_RX: + clk = clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]); + reg = BIST_CTRL_POINT(2) | BIST_ENABLE; + break; + }; + + reg |= TONE_PRBS; + reg |= TONE_LEVEL(level_dB / 6); + + if (freq_Hz < 4) { + reg |= TONE_FREQ(freq_Hz); + } else { + if (clk) + reg |= TONE_FREQ(DIV_ROUND_CLOSEST(freq_Hz * 32, clk) - 1); + } + + reg_mask = BIST_MASK_CHANNEL_1_I_DATA | BIST_MASK_CHANNEL_1_Q_DATA | + BIST_MASK_CHANNEL_2_I_DATA | BIST_MASK_CHANNEL_2_Q_DATA; + + reg1 = ((mask << 2) & reg_mask); + ad9361_spi_write(phy->spi, REG_BIST_AND_DATA_PORT_TEST_CONFIG, reg1); + + phy->bist_config = reg; + + return ad9361_spi_write(phy->spi, REG_BIST_CONFIG, reg); +} + +/** + * Get BIST tone settings. + * @param phy The AD9361 state structure. + * @param mode Bist tone mode. + * @param freq_Hz Bist tone frequency. + * @param level_dB Bist tone level. + * @param mask Bist reg mask. + * @return 0 in case of success, negative error code otherwise. + */ +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask) +{ + *mode = phy->bist_tone_mode; + *freq_Hz = phy->bist_tone_freq_Hz; + *level_dB = phy->bist_tone_level_dB; + *mask = phy->bist_tone_mask; +} + +/** + * Check the calibration done bit. + * @param phy The AD9361 state structure. + * @param reg The register address. + * @param mask The bit mask. + * @param done_state The done state [0,1]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_check_cal_done(struct ad9361_rf_phy *phy, uint32_t reg, + uint32_t mask, uint32_t done_state) +{ + uint32_t timeout = 20000; /* RFDC_CAL can take long */ + uint32_t state; + + do { + state = ad9361_spi_readf(phy->spi, reg, mask); + if (state == done_state) + return 0; + + if (reg == REG_CALIBRATION_CTRL) + udelay(1200); + else + udelay(120); + } while (timeout--); + + dev_err(&phy->spi->dev, "Calibration TIMEOUT (0x%"PRIX32", 0x%"PRIX32")", reg, + mask); + + return -ETIMEDOUT; +} + +/** + * Run an AD9361 calibration and check the calibration done bit. + * @param phy The AD9361 state structure. + * @param mask The calibration bit mask[RX_BB_TUNE_CAL, TX_BB_TUNE_CAL, + * RX_QUAD_CAL, TX_QUAD_CAL, RX_GAIN_STEP_CAL, TXMON_CAL, + * RFDC_CAL, BBDC_CAL]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_run_calibration(struct ad9361_rf_phy *phy, uint32_t mask) +{ + int32_t ret = ad9361_spi_write(phy->spi, REG_CALIBRATION_CTRL, mask); + if (ret < 0) + return ret; + + dev_dbg(&phy->spi->dev, "%s: CAL Mask 0x%"PRIx32, __func__, mask); + + return ad9361_check_cal_done(phy, REG_CALIBRATION_CTRL, mask, 0); +} + +/** + * Choose the right RX gain table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index to the RX gain table. + */ +static int32_t ad9361_gt_tableindex(struct ad9361_rf_phy *phy, uint64_t freq) +{ + int32_t i; + + for (i = 0; phy->gt_info[i].tab != NULL; i++) { + if ((phy->pdata->split_gt == phy->gt_info[i].split_table) && + (phy->gt_info[i].start < freq) && + (freq <= phy->gt_info[i].end)) { + return i; + } + } + + dev_err(&phy->spi->dev, + "%s: Failed to find suitable gain table (%"PRIu64")", __func__, freq); + + return 0; +} + +/** + * Return the current gain table index. + * @param phy The AD9361 state structure. + * @return The current gain table index or 0 if the table was not chosen. + */ +uint32_t ad9361_gt(struct ad9361_rf_phy *phy) +{ + if (phy->current_table == NO_GAIN_TABLE) { + dev_err(&phy->spi->dev, "%s: ERROR", __func__); + return 0; + } + + return phy->current_table; +} + +/** + * Shift the real frequency value, so it fits type unsigned long + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint32_t ad9361_to_clk(uint64_t freq) +{ + return (uint32_t)(freq >> 1); +} + +/** + * Shift back the frequency value, so it reflects the real value. + * Note: PLL operates between 47 .. 6000 MHz which is > 2^32. + * @param freq The frequency value [Hz]. + * @return The shifted frequency value. + */ +uint64_t ad9361_from_clk(uint32_t freq) +{ + return ((uint64_t)freq << 1); +} + +/** + * Find the corresponding table index for a specific gain value. + * @param phy The AD9361 state structure. + * @param gain The gain value. + * @return The table index. + */ +static int find_table_index(struct ad9361_rf_phy *phy, int gain) +{ + uint32_t i, nm1, n; + + for (i = 0; i < phy->gt_info[ad9361_gt(phy)].max_index; i++) { + if (phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] >= gain) { + nm1 = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[ + (i > 0) ? i - 1 : i] - gain); + n = abs(phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[i] + - gain); + if (nm1 < n) + return (i > 0) ? i - 1 : i; + else + return i; + } + } + + return -EINVAL; +} + +/** + * Load the gain table for the selected frequency range and receiver. + * @param phy The AD9361 state structure. + * @param freq The frequency value [Hz]. + * @param dest The destination [GT_RX1, GT_RX2]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_gt(struct ad9361_rf_phy *phy, uint64_t freq, + uint32_t dest) +{ + struct spi_desc *spi = phy->spi; + uint8_t (*tab)[3]; + uint32_t band, index_max, i, lna, lpf_tia_mask, set_gain; + int32_t ret, rx1_gain, rx2_gain; + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64, __func__, freq); + + band = ad9361_gt_tableindex(phy, freq); + + dev_dbg(&phy->spi->dev, "%s: frequency %"PRIu64" (band %"PRIu32")", + __func__, freq, band); + + /* check if table is present */ + if (phy->current_table == band) + return 0; + + tab = phy->gt_info[band].tab; + index_max = phy->gt_info[band].max_index; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_USE_FULL_GAIN_TABLE, !phy->pdata->split_gt); + + ad9361_spi_write(spi, REG_MAX_LMT_FULL_GAIN, + index_max - 1); /* Max Full/LMT Gain Table Index */ + + set_gain = ad9361_spi_readf(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx1_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx1_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + set_gain = ad9361_spi_readf(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK); + + if (phy->current_table != NO_GAIN_TABLE) { + rx2_gain = phy->gt_info[phy->current_table].abs_gain_tbl[set_gain]; + } else { + if (set_gain > (index_max - 1)) + set_gain = index_max - 1; + + rx2_gain = phy->gt_info[band].abs_gain_tbl[set_gain]; + } + + lna = phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en ? + EXT_LNA_CTRL : 0; + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Start Gain Table Clock */ + + /* TX QUAD Calibration */ + if (phy->pdata->split_gt) + lpf_tia_mask = 0x20; + else + lpf_tia_mask = 0x3F; + + phy->tx_quad_lpf_tia_match = -EINVAL; + + for (i = 0; i < index_max; i++) { + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, i); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA1, + tab[i][0] | lna); /* Ext LNA, Int LNA, & Mixer Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA2, + tab[i][1]); /* TIA & LPF Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_WRITE_DATA3, + tab[i][2]); /* DC Cal bit & Dig Gain Word */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, + START_GAIN_TABLE_CLOCK | + WRITE_GAIN_TABLE | + RECEIVER_SELECT(dest)); /* Gain Table Index */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay 3 ADCCLK/16 cycles */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + + if ((tab[i][1] & lpf_tia_mask) == 0x20) + phy->tx_quad_lpf_tia_match = i; + + } + + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, START_GAIN_TABLE_CLOCK | + RECEIVER_SELECT(dest)); /* Clear Write Bit */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_READ_DATA1, + 0); /* Dummy Write to delay ~1u */ + ad9361_spi_write(spi, REG_GAIN_TABLE_CONFIG, 0); /* Stop Gain Table Clock */ + + phy->current_table = band; + + ret = find_table_index(phy, rx1_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + RX_FULL_TBL_IDX_MASK, ret); /* Rx1 Full/LMT Gain Index */ + + ret = find_table_index(phy, rx2_gain); + if (ret < 0) + ret = phy->gt_info[band].max_index - 1; + + ad9361_spi_write(spi, REG_RX2_MANUAL_LMT_FULL_GAIN, + ret); /* Rx2 Full/LMT Gain Index */ + + return 0; +} + +/** + * Setup the external low-noise amplifier (LNA). + * @param phy The AD9361 state structure. + * @param ctrl Pointer to eLNA control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_setup_ext_lna(struct ad9361_rf_phy *phy, + struct elna_control *ctrl) +{ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA1_CTRL, + ctrl->elna_1_control_en); + + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, EXTERNAL_LNA2_CTRL, + ctrl->elna_2_control_en); + + ad9361_spi_write(phy->spi, REG_EXT_LNA_HIGH_GAIN, + EXT_LNA_HIGH_GAIN(ctrl->gain_mdB / 500)); + + return ad9361_spi_write(phy->spi, REG_EXT_LNA_LOW_GAIN, + EXT_LNA_LOW_GAIN(ctrl->bypass_loss_mdB / 500)); +} + +/** + * Set the clock output mode. + * @param phy The AD9361 state structure. + * @param mode The clock output mode []. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_clkout_control(struct ad9361_rf_phy *phy, + enum ad9361_clkout mode) +{ + if (mode == CLKOUT_DISABLE) + return ad9361_spi_writef(phy->spi, REG_BBPLL, CLKOUT_ENABLE, 0); + + return ad9361_spi_writef(phy->spi, REG_BBPLL, + CLKOUT_ENABLE | CLKOUT_SELECT(~0), + ((mode - 1) << 1) | 0x1); +} + +/** + * Load the Gm Sub Table. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_load_mixer_gm_subtable(struct ad9361_rf_phy *phy) +{ + int32_t i, addr; + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Start Clock */ + + for (i = 0, addr = ARRAY_SIZE(gm_st_ctrl); i < (int64_t)ARRAY_SIZE(gm_st_ctrl); + i++) { + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_ADDRESS, + --addr); /* Gain Table Index */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_BIAS_WRITE, 0); /* Bias */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_WRITE, + gm_st_gain[i]); /* Gain */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CTRL_WRITE, + gm_st_ctrl[i]); /* Control */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + WRITE_GM_SUB_TABLE | START_GM_SUB_TABLE_CLOCK); /* Write Words */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + } + + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, + START_GM_SUB_TABLE_CLOCK); /* Clear Write */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_GAIN_READ, 0); /* Dummy Delay */ + ad9361_spi_write(phy->spi, REG_GM_SUB_TABLE_CONFIG, 0); /* Stop Clock */ + + return 0; +} + +/** + * Set the attenuation for the selected TX channels. + * @param phy The AD9361 state structure. + * @param atten_mdb Attenuation value [mdB]. + * @param tx1 Set true, the attenuation of the TX1 will be affected. + * @param tx2 Set true, the attenuation of the TX2 will be affected. + * @param immed Set true, an immediate update will take place. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed) +{ + uint8_t buf[2]; + int32_t ret = 0; + + dev_dbg(&phy->spi->dev, "%s : attenuation %"PRIu32" mdB tx1=%d tx2=%d", + __func__, atten_mdb, tx1, tx2); + + if (atten_mdb > MAX_TX_ATTENUATION_DB) /* 89.75 dB */ + return -EINVAL; + + atten_mdb /= 250; /* Scale to 0.25dB / LSB */ + + buf[0] = atten_mdb >> 8; + buf[1] = atten_mdb & 0xFF; + + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 0); + + if (tx1) + ret = ad9361_spi_writem(phy->spi, REG_TX1_ATTEN_1, buf, 2); + + if (tx2) + ret = ad9361_spi_writem(phy->spi, REG_TX2_ATTEN_1, buf, 2); + + if (immed) + ad9361_spi_writef(phy->spi, REG_TX2_DIG_ATTEN, + IMMEDIATELY_UPDATE_TPC_ATTEN, 1); + + return ret; +} + +/** + * Get the attenuation for the selected TX channel. + * @param phy The AD9361 state structure. + * @param tx_num The selected channel [1, 2]. + * @return The attenuation value [mdB] or negative error code in case of failure. + */ +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num) +{ + uint8_t buf[2]; + int32_t ret = 0; + uint32_t code; + + ret = ad9361_spi_readm(phy->spi, (tx_num == 1) ? + REG_TX1_ATTEN_1 : REG_TX2_ATTEN_1, buf, 2); + + if (ret < 0) + return ret; + + code = (buf[0] << 8) | buf[1]; + + code *= 250; + + return code; +} + +/** + * Mute TX. + * @param phy The AD9361 state structure. + * @param state The state - 0 mute; 1 - unmute. + * @return 0 in case of success + */ +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state) +{ + int32_t ret; + + if (state) { + phy->tx1_atten_cached = ad9361_get_tx_atten(phy, 1); + phy->tx2_atten_cached = ad9361_get_tx_atten(phy, 2); + + return ad9361_set_tx_atten(phy, 89750, true, true, true); + } else { + if (phy->tx1_atten_cached == phy->tx2_atten_cached) + return ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, true, true); + + ret = ad9361_set_tx_atten(phy, phy->tx1_atten_cached, + true, false, true); + ret |= ad9361_set_tx_atten(phy, phy->tx2_atten_cached, + false, true, true); + + return ret; + } +} + +/** + * Choose the right RF VCO table index for the selected frequency. + * @param freq The frequency value [Hz]. + * @return The index from the RF VCO table. + */ +static uint32_t ad9361_rfvco_tableindex(uint32_t freq) +{ + if (freq < 50000000UL) + return LUT_FTDD_40; + + if (freq <= 70000000UL) + return LUT_FTDD_60; + + return LUT_FTDD_80; +} + +/** + * Initialize the RFPLL VCO. + * @param phy The AD9361 state structure. + * @param tx Set true for TX_RFPLL. + * @param vco_freq The VCO frequency [Hz]. + * @param ref_clk The reference clock frequency [Hz]. + * @return 0 in case of success + */ +static int32_t ad9361_rfpll_vco_init(struct ad9361_rf_phy *phy, + bool tx, uint64_t vco_freq, + uint32_t ref_clk) +{ + struct spi_desc *spi = phy->spi; + const struct SynthLUT(*tab); + int32_t i = 0; + uint32_t range, offs = 0; + + range = ad9361_rfvco_tableindex(ref_clk); + + dev_dbg(&phy->spi->dev, + "%s : vco_freq %"PRIu64" : ref_clk %"PRIu32" : range %"PRIu32, + __func__, vco_freq, ref_clk, range); + + do_div(&vco_freq, 1000000UL); /* vco_freq in MHz */ + + if ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) + && (phy->current_tx_lo_freq != phy->current_rx_lo_freq)) { + tab = &SynthLUT_FDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = false; + else + phy->current_rx_use_tdd_table = false; + } else { + if (have_tdd_tables) { + tab = &SynthLUT_TDD[range][0]; + if (tx) + phy->current_tx_use_tdd_table = true; + else + phy->current_rx_use_tdd_table = true; + } + } + + if (tx) + offs = REG_TX_VCO_OUTPUT - REG_RX_VCO_OUTPUT; + + while (i < SYNTH_LUT_SIZE && tab[i].VCO_MHz > vco_freq) + i++; + + dev_dbg(&phy->spi->dev, "%s : freq %d MHz : index %"PRId32, + __func__, tab[i].VCO_MHz, i); + + ad9361_spi_write(spi, REG_RX_VCO_OUTPUT + offs, + VCO_OUTPUT_LEVEL(tab[i].VCO_Output_Level) | + PORB_VCO_LOGIC); + ad9361_spi_writef(spi, REG_RX_ALC_VARACTOR + offs, + VCO_VARACTOR(~0), tab[i].VCO_Varactor); + ad9361_spi_write(spi, REG_RX_VCO_BIAS_1 + offs, + VCO_BIAS_REF(tab[i].VCO_Bias_Ref) | + VCO_BIAS_TCF(tab[i].VCO_Bias_Tcf)); + + ad9361_spi_write(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, + VCO_CAL_OFFSET(tab[i].VCO_Cal_Offset)); + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE( + tab[i].VCO_Varactor_Reference)); + + ad9361_spi_write(spi, REG_RX_VCO_CAL_REF + offs, VCO_CAL_REF_TCF(0)); + + ad9361_spi_write(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_OFFSET(0) | + VCO_VARACTOR_REFERENCE_TCF(7)); + + ad9361_spi_writef(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0), + tab[i].Charge_Pump_Current); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_1 + offs, + LOOP_FILTER_C2(tab[i].LF_C2) | + LOOP_FILTER_C1(tab[i].LF_C1)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_2 + offs, + LOOP_FILTER_R1(tab[i].LF_R1) | + LOOP_FILTER_C3(tab[i].LF_C3)); + ad9361_spi_write(spi, REG_RX_LOOP_FILTER_3 + offs, + LOOP_FILTER_R3(tab[i].LF_R3)); + + return 0; +} + +/** + * Get the current gain in Split Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, + */ +static int32_t ad9361_get_split_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tbl_addr; + int32_t rc = 0; + + + rx_gain->fgt_lmt_index = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + tbl_addr = ad9361_spi_read(spi, REG_GAIN_TABLE_ADDRESS); + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, rx_gain->fgt_lmt_index); + + val = ad9361_spi_read(spi, REG_GAIN_TABLE_READ_DATA1); + rx_gain->lna_index = TO_LNA_GAIN(val); + rx_gain->mixer_index = TO_MIXER_GM_GAIN(val); + + rx_gain->tia_index = ad9361_spi_readf(spi, REG_GAIN_TABLE_READ_DATA2, TIA_GAIN); + + rx_gain->lmt_gain = lna_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->lna_index] + + mixer_table[ad9361_gt(phy) - RXGAIN_TBLS_END][rx_gain->mixer_index] + + tia_table[rx_gain->tia_index]; + + ad9361_spi_write(spi, REG_GAIN_TABLE_ADDRESS, tbl_addr); + + /* Read LPF Index */ + rx_gain->lpf_gain = ad9361_spi_readf(spi, idx_reg + 1, LPF_GAIN_RX(~0)); + + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = rx_gain->lmt_gain + rx_gain->lpf_gain + + rx_gain->digital_gain; + return rc; +} + +/** + * Get the current gain in Full Gain Table Mode + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success + */ +static int32_t ad9361_get_full_table_gain(struct ad9361_rf_phy *phy, + uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + rx_gain->fgt_lmt_index = val = ad9361_spi_readf(spi, idx_reg, + FULL_TABLE_GAIN_INDEX(~0)); + /* Read Digital Gain */ + rx_gain->digital_gain = ad9361_spi_readf(spi, idx_reg + 2, + DIGITAL_GAIN_RX(~0)); + + rx_gain->gain_db = phy->gt_info[ad9361_gt(phy)].abs_gain_tbl[val]; + + return 0; +} + +/** + * Get current RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain A rf_rx_gain struct to store the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift, rx_enable_mask; + uint8_t fast_atk_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX1; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_1); + fast_atk_shift = RX1_FAST_ATK_SHIFT; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_GAIN_RX2; + rx_enable_mask = RX_CHANNEL_ENABLE(RX_2); + fast_atk_shift = RX2_FAST_ATK_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + } + + val = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, rx_enable_mask); + + if (!val) { + dev_dbg(dev, "Rx%"PRIu32" is not enabled", rx_gain->ant); + rc = -EAGAIN; + goto out; + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val == RX_GAIN_CTL_AGC_FAST_ATK) { + /* In fast attack mode check whether Fast attack state machine + * has locked gain, if not then we can not read gain. + */ + val = ad9361_spi_read(spi, REG_FAST_ATTACK_STATE); + val = (val >> fast_atk_shift) & FAST_ATK_MASK; + if (val != FAST_ATK_GAIN_LOCKED) { + dev_warn(dev, "Failed to read gain, state m/c at %"PRIx32, + val); + rc = -EAGAIN; + goto out; + } + } + + if (has_split_gt && phy->pdata->split_gt) + rc = ad9361_get_split_table_gain(phy, idx_reg, rx_gain); + else + rc = ad9361_get_full_table_gain(phy, idx_reg, rx_gain); + +out: + return rc; +} + +/** + * Get Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return The state. + */ +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy) +{ + return ad9361_spi_readf(phy->spi, REG_STATE, ENSM_STATE(~0)); +} + +/** + * Force Enable State Machine (ENSM) to the desired state (internally used only). + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @return None. + */ +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + uint8_t dev_ensm_state; + int32_t rc, timeout = 10; + uint32_t val; + + dev_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + + phy->prev_ensm_state = dev_ensm_state; + + if (dev_ensm_state == ensm_state) { + dev_dbg(dev, "Nothing to do, device is already in %d state", + ensm_state); + goto out; + } + + dev_dbg(dev, "Device is in %x state, forcing to %x", dev_ensm_state, + ensm_state); + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* Enable control through SPI writes, and take out from + * Alert + */ + if (val & ENABLE_ENSM_PIN_CTRL) { + val &= ~ENABLE_ENSM_PIN_CTRL; + phy->ensm_pin_ctl_en = true; + } else { + phy->ensm_pin_ctl_en = false; + } + + if (dev_ensm_state) + val &= ~(TO_ALERT); + + switch (ensm_state) { + + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1\n"); + goto out; + } + + while (ad9361_ensm_get_state(phy) != ensm_state && --timeout) { + mdelay(1); + } + + if (timeout == 0) + dev_err(dev, "Failed to restore state"); + +out: + return; + +} + +/** + * Restore an Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The state. + * @return None. + */ +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state) +{ + struct spi_desc *spi = phy->spi; + int32_t rc; + uint32_t val; + + val = ad9361_spi_read(spi, REG_ENSM_CONFIG_1); + + /* We are restoring state only, so clear State bits first + * which might have set while forcing a particular state + */ + val &= ~(FORCE_TX_ON | FORCE_RX_ON | FORCE_ALERT_STATE); + val |= TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + break; + case ENSM_STATE_ALERT: + val |= TO_ALERT; + break; + case ENSM_STATE_INVALID: + dev_dbg(dev, "No need to restore, ENSM state wasn't saved"); + return; + default: + dev_dbg(dev, "Could not restore to %d ENSM state", + ensm_state); + return; + } + + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) { + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + return; + } + + if (phy->ensm_pin_ctl_en) { + val |= ENABLE_ENSM_PIN_CTRL; + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to write ENSM_CONFIG_1"); + } +} + +/** + * Restore the previous Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy) +{ + return ad9361_ensm_restore_state(phy, phy->prev_ensm_state); +} + +/** + * Set gain in Split Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_split_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + + if ((rx_gain->fgt_lmt_index > MAX_LMT_INDEX) || + (rx_gain->lpf_gain > MAX_LPF_GAIN) || + (rx_gain->digital_gain > MAX_DIG_GAIN)) { + dev_err(dev, "LMT_INDEX missing or greater than max value %d", + MAX_LMT_INDEX); + dev_err(dev, "LPF_GAIN missing or greater than max value %d", + MAX_LPF_GAIN); + dev_err(dev, "DIGITAL_GAIN cannot be more than %d", + MAX_DIG_GAIN); + rc = -EINVAL; + goto out; + } + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rx_gain->fgt_lmt_index = rc; + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, + rx_gain->fgt_lmt_index); + if (rc < 0) + goto out; + rc = ad9361_spi_writef(spi, idx_reg + 1, RX_LPF_IDX_MASK, rx_gain->lpf_gain); + if (rc < 0) + goto out; + if (phy->pdata->gain_ctrl.dig_gain_en) { + rc = ad9361_spi_writef(spi, idx_reg + 2, RX_DIGITAL_IDX_MASK, + rx_gain->digital_gain); + } else if (rx_gain->digital_gain > 0) { + dev_err(dev, "Digital gain is disabled and cannot be set"); + } +out: + return rc; +} + +/** + * Set gain in Full Gain Table Mode (used only in Manual Gain Control Mode). + * @param phy The AD9361 state structure. + * @param idx_reg Register base address for the selected receiver + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t set_full_table_gain(struct ad9361_rf_phy *phy, uint32_t idx_reg, + struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + int rc = 0; + + if (rx_gain->fgt_lmt_index != ((uint32_t)~0) || + rx_gain->lpf_gain != ((uint32_t)~0) || + rx_gain->digital_gain > 0) + dev_dbg(dev, + "Ignoring lmt/lpf/digital gains in Single Table mode"); + + rc = find_table_index(phy, rx_gain->gain_db); + if (rc < 0) { + dev_err(dev, "Invalid gain %"PRId32", supported range [%d - %d]\n", + rx_gain->gain_db, phy->gt_info[ad9361_gt(phy)]. + abs_gain_tbl[0], + phy->gt_info[ad9361_gt(phy)].abs_gain_tbl + [phy->gt_info[ad9361_gt(phy)].max_index - 1]); + goto out; + } + + rc = ad9361_spi_writef(spi, idx_reg, RX_FULL_TBL_IDX_MASK, rc); +out: + return rc; +} + +/** + * Set the RX gain for the selected channel. + * @param phy The AD9361 state structure. + * @param rx_id The desired channel number (0, 1). + * @param rx_gain The rf_rx_gain struct containing the RF gain. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, idx_reg; + uint8_t gain_ctl_shift; + int32_t rc = 0; + + if (rx_id == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + idx_reg = REG_RX1_MANUAL_LMT_FULL_GAIN; + + } else if (rx_id == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + idx_reg = REG_RX2_MANUAL_LMT_FULL_GAIN; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, rx_id); + rc = -EINVAL; + goto out; + + } + + val = ad9361_spi_read(spi, REG_AGC_CONFIG_1); + val = (val >> gain_ctl_shift) & RX_GAIN_CTL_MASK; + + if (val != RX_GAIN_CTL_MGC) { + dev_dbg(dev, "Rx gain can be set in MGC mode only"); + rc = -EOPNOTSUPP; + goto out; + } + + if (has_split_gt && phy->pdata->split_gt) + rc = set_split_table_gain(phy, idx_reg, rx_gain); + else + rc = set_full_table_gain(phy, idx_reg, rx_gain); + + if (rc) { + dev_err(dev, "Unable to write gain tbl idx reg: %"PRIu32, idx_reg); + goto out; + } + +out: + return rc; + +} + +/** + * Update the Gain Control. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_update(struct ad9361_rf_phy *phy) +{ + struct spi_desc *spi = phy->spi; + uint32_t clkrf; + uint32_t reg, delay_lna, settling_delay, dec_pow_meas_dur; + int32_t ret; + uint32_t fir_div; + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + delay_lna = phy->pdata->elna_ctrl.settling_delay_ns; + + /* + * AGC Attack Delay (us)=ceiling((((0.2+Delay_LNA)*ClkRF+14))/(2*ClkRF))+1 + * ClkRF in MHz, delay in us + */ + + reg = (200 + delay_lna) / 2 + (14000000UL / (clkrf / 500U)); + reg = DIV_ROUND_UP(reg, 1000UL) + + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret = ad9361_spi_writef(spi, REG_AGC_ATTACK_DELAY, + AGC_ATTACK_DELAY(~0), reg); + + /* + * Peak Overload Wait Time (ClkRF cycles)=ceiling((0.1+Delay_LNA) *clkRF+1) + */ + + reg = (delay_lna + 100UL) * (clkrf / 1000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 1; + reg = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_PEAK_WAIT_TIME, + PEAK_OVERLOAD_WAIT_TIME(~0), reg); + + /* + * Settling Delay in 0x111. Applies to all gain control modes: + * 0x111[D4:D0]= ceiling(((0.2+Delay_LNA)*clkRF + dodebug = false;+14)/2) + */ + + reg = (delay_lna + 200UL) * (clkrf / 2000UL); + reg = DIV_ROUND_UP(reg, 1000000UL) + 7; + reg = settling_delay = clamp_t(uint8_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + SETTLING_DELAY(~0), reg); + + /* + * Gain Update Counter [15:0]= round((((time*ClkRF-0x111[D4:D0]*2)-2))/2) + */ + reg = phy->pdata->gain_ctrl.gain_update_interval_us * (clkrf / 1000UL) - + settling_delay * 2000UL - 2000UL; + + reg = DIV_ROUND_CLOSEST(reg, 2000UL); + reg = clamp_t(uint32_t, reg, 0U, 131071UL); + + if (phy->agc_mode[0] == RF_GAIN_FASTATTACK_AGC || + phy->agc_mode[1] == RF_GAIN_FASTATTACK_AGC) { + dec_pow_meas_dur = + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration; + } else { + fir_div = DIV_ROUND_CLOSEST(clkrf, + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK])); + dec_pow_meas_dur = phy->pdata->gain_ctrl.dec_pow_measuremnt_duration; + + if (((reg * 2 / fir_div) / dec_pow_meas_dur) < 2) { + dec_pow_meas_dur = reg / fir_div; + } + } + + /* Power Measurement Duration */ + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), + ilog2(dec_pow_meas_dur / 16)); + + + ret |= ad9361_spi_writef(spi, REG_DIGITAL_SAT_COUNTER, + DOUBLE_GAIN_COUNTER, reg > 65535); + + if (reg > 65535) + reg /= 2; + + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER1, reg & 0xFF); + ret |= ad9361_spi_write(spi, REG_GAIN_UPDATE_COUNTER2, reg >> 8); + + /* + * Fast AGC State Wait Time - Energy Detect Count + */ + + reg = DIV_ROUND_CLOSEST(phy->pdata->gain_ctrl.f_agc_state_wait_time_ns * + (clkrf / 1000UL), 1000000UL); + reg = clamp_t(uint32_t, reg, 0U, 31U); + ret |= ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + ENERGY_DETECT_COUNT(~0), reg); + + return ret; +} + +/** + * Set the gain control mode. + * @param phy The AD9361 state structure. + * @param gain_ctrl A rf_gain_ctrl struct that contains the the desired + * channel information and the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t gain_ctl_shift, mode; + uint8_t val; + + rc = ad9361_spi_readm(spi, REG_AGC_CONFIG_1, &val, 1); + if (rc) { + dev_err(dev, "Unable to read AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + switch (gain_ctrl->mode) { + case RF_GAIN_MGC: + mode = RX_GAIN_CTL_MGC; + break; + case RF_GAIN_FASTATTACK_AGC: + mode = RX_GAIN_CTL_AGC_FAST_ATK; + break; + case RF_GAIN_SLOWATTACK_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK; + break; + case RF_GAIN_HYBRID_AGC: + mode = RX_GAIN_CTL_AGC_SLOW_ATK_HYBD; + break; + default: + rc = -EINVAL; + goto out; + } + + if (gain_ctrl->ant == 1) { + gain_ctl_shift = RX1_GAIN_CTRL_SHIFT; + } else if (gain_ctrl->ant == 2) { + gain_ctl_shift = RX2_GAIN_CTRL_SHIFT; + } else { + dev_err(dev, "Unknown Rx path %"PRIu32, gain_ctrl->ant); + rc = -EINVAL; + goto out; + } + + rc = ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_DISABLE); + if (rc) { + dev_err(dev, "Unable to disable rx%"PRIu32, gain_ctrl->ant); + goto out; + } + + val &= ~(RX_GAIN_CTL_MASK << gain_ctl_shift); + val |= mode << gain_ctl_shift; + if (mode == RX_GAIN_CTL_AGC_SLOW_ATK_HYBD) + val |= SLOW_ATTACK_HYBRID_MODE; + else + val &= ~SLOW_ATTACK_HYBRID_MODE; + + rc = ad9361_spi_write(spi, REG_AGC_CONFIG_1, val); + if (rc) { + dev_err(dev, "Unable to write AGC config1 register: %x", + REG_AGC_CONFIG_1); + goto out; + } + + ad9361_en_dis_rx(phy, gain_ctrl->ant, RX_ENABLE); + rc = ad9361_gc_update(phy); +out: + return rc; +} + +/** + * Get the RSSI. + * @param phy The AD9361 state structure. + * @param rssi A rf_rssi struct to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi) +{ + struct spi_desc *spi = phy->spi; + uint8_t reg_val_buf[6]; + int32_t rc; + + rc = ad9361_spi_readm(spi, REG_PREAMBLE_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (rssi->ant == 1) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[5] << RSSI_LSB_SHIFT) + + (reg_val_buf[1] & RSSI_LSB_MASK1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[4] << RSSI_LSB_SHIFT) + + (reg_val_buf[0] & RSSI_LSB_MASK1)); + } else if (rssi->ant == 2) { + rssi->symbol = RSSI_RESOLUTION * + ((reg_val_buf[3] << RSSI_LSB_SHIFT) + + ((reg_val_buf[1] & RSSI_LSB_MASK2) >> 1)); + rssi->preamble = RSSI_RESOLUTION * + ((reg_val_buf[2] << RSSI_LSB_SHIFT) + + ((reg_val_buf[0] & RSSI_LSB_MASK2) >> 1)); + } else + rc = -EFAULT; + + rssi->multiplier = RSSI_MULTIPLIER; + + return rc; +} + +/** + * Setup the RX ADC. + * @param phy The AD9361 state structure. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @param adc_sampl_freq_Hz The ADC sampling frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_adc_setup(struct ad9361_rf_phy *phy, + uint32_t bbpll_freq, + uint32_t adc_sampl_freq_Hz) +{ + + uint32_t scale_snr_1e3, maxsnr, sqrt_inv_rc_tconst_1e3, tmp_1e3, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3, sqrt_term_1e3, + min_sqrt_term_1e3, bb_bw_Hz; + uint64_t tmp, invrc_tconst_1e6; + uint8_t data[40]; + uint32_t i; + int32_t ret; + + uint8_t c3_msb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t c3_lsb = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t r2346 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + + /* + * BBBW = (BBPLL / RxTuneDiv) * ln(2) / (1.4 * 2PI ) + * We assume ad9361_rx_bb_analog_filter_calib() is always run prior + */ + + tmp = bbpll_freq * 10000ULL; + do_div(&tmp, 126906UL * phy->rxbbf_div); + bb_bw_Hz = tmp; + + dev_dbg(&phy->spi->dev, "%s : BBBW %"PRIu32" : ADCfreq %"PRIu32, + __func__, bb_bw_Hz, adc_sampl_freq_Hz); + + dev_dbg(&phy->spi->dev, "c3_msb 0x%X : c3_lsb 0x%X : r2346 0x%X : ", + c3_msb, c3_lsb, r2346); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 28000000UL); + + if (adc_sampl_freq_Hz < 80000000) + scale_snr_1e3 = 1000; + else + scale_snr_1e3 = 1585; /* pow(10, scale_snr_dB/10); */ + + if (bb_bw_Hz >= 18000000) { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)* (1000 + (10 * (bb_bw_Hz - 18000000) / 1000000))); + + do_div(&invrc_tconst_1e6, 1000UL); + + } else { + invrc_tconst_1e6 = (160975ULL * r2346 * + (160 * c3_msb + 10 * c3_lsb + 140) * + (bb_bw_Hz)); + } + + do_div(&invrc_tconst_1e6, 1000000000UL); + + if (invrc_tconst_1e6 > ULONG_MAX) + dev_err(&phy->spi->dev, "invrc_tconst_1e6 > ULONG_MAX"); + + sqrt_inv_rc_tconst_1e3 = int_sqrt((uint32_t)invrc_tconst_1e6); + maxsnr = 640 / 160; + scaled_adc_clk_1e6 = DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 640); + inv_scaled_adc_clk_1e3 = DIV_ROUND_CLOSEST(640000000, + DIV_ROUND_CLOSEST(adc_sampl_freq_Hz, 1000)); + tmp_1e3 = DIV_ROUND_CLOSEST(980000 + 20 * max_t(uint32_t, 1000U, + DIV_ROUND_CLOSEST(inv_scaled_adc_clk_1e3, maxsnr)), 1000); + sqrt_term_1e3 = int_sqrt(scaled_adc_clk_1e6); + min_sqrt_term_1e3 = min_t(uint32_t, 1000U, + int_sqrt(maxsnr * scaled_adc_clk_1e6)); + + dev_dbg(&phy->spi->dev, + "invrc_tconst_1e6 %"PRIu64", sqrt_inv_rc_tconst_1e3 %"PRIu32, + invrc_tconst_1e6, sqrt_inv_rc_tconst_1e3); + dev_dbg(&phy->spi->dev, + "scaled_adc_clk_1e6 %"PRIu32", inv_scaled_adc_clk_1e3 %"PRIu32, + scaled_adc_clk_1e6, inv_scaled_adc_clk_1e3); + dev_dbg(&phy->spi->dev, + "tmp_1e3 %"PRIu32", sqrt_term_1e3 %"PRIu32", min_sqrt_term_1e3 %"PRIu32, + tmp_1e3, sqrt_term_1e3, min_sqrt_term_1e3); + + data[0] = 0; + data[1] = 0; + data[2] = 0; + data[3] = 0x24; + data[4] = 0x24; + data[5] = 0; + data[6] = 0; + + tmp = -50000000 + 8ULL * scale_snr_1e3 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3; + do_div(&tmp, 100000000UL); + data[7] = min_t(uint64_t, 124U, tmp); + + tmp = (invrc_tconst_1e6 >> 1) + 20 * inv_scaled_adc_clk_1e3 * + data[7] / 80 * 1000ULL; + do_div(&tmp, invrc_tconst_1e6); + data[8] = min_t(uint64_t, 255U, tmp); + + tmp = (-500000 + 77ULL * sqrt_inv_rc_tconst_1e3 * min_sqrt_term_1e3); + do_div(&tmp, 1000000UL); + data[10] = min_t(uint64_t, 127U, tmp); + + data[9] = min_t(uint32_t, 127U, ((800 * data[10]) / 1000)); + tmp = ((invrc_tconst_1e6 >> 1) + (20 * inv_scaled_adc_clk_1e3 * + data[10] * 1000ULL)); + do_div(&tmp, invrc_tconst_1e6 * 77); + data[11] = min_t(uint64_t, 255U, tmp); + data[12] = min_t(uint32_t, 127U, (-500000 + 80 * sqrt_inv_rc_tconst_1e3 * + min_sqrt_term_1e3) / 1000000UL); + + tmp = -3 * (long)(invrc_tconst_1e6 >> 1) + inv_scaled_adc_clk_1e3 * + data[12] * (1000ULL * 20 / 80); + do_div(&tmp, invrc_tconst_1e6); + data[13] = min_t(uint64_t, 255, tmp); + + data[14] = 21 * (inv_scaled_adc_clk_1e3 / 10000); + data[15] = min_t(uint32_t, 127U, (500 + 1025 * data[7]) / 1000); + data[16] = min_t(uint32_t, 127U, (data[15] * tmp_1e3) / 1000); + data[17] = data[15]; + data[18] = min_t(uint32_t, 127U, (500 + 975 * data[10]) / 1000); + data[19] = min_t(uint32_t, 127U, (data[18] * tmp_1e3) / 1000); + data[20] = data[18]; + data[21] = min_t(uint32_t, 127U, (500 + 975 * data[12]) / 1000); + data[22] = min_t(uint32_t, 127, (data[21] * tmp_1e3) / 1000); + data[23] = data[21]; + data[24] = 0x2E; + data[25] = (128 + min_t(uint32_t, 63000U, DIV_ROUND_CLOSEST(63 * + scaled_adc_clk_1e6, 1000)) / 1000); + data[26] = min_t(uint32_t, 63U, 63 * scaled_adc_clk_1e6 / 1000000 * + (920 + 80 * inv_scaled_adc_clk_1e3 / 1000) / 1000); + data[27] = min_t(uint32_t, 63, (32 * sqrt_term_1e3) / 1000); + data[28] = data[25]; + data[29] = data[26]; + data[30] = data[27]; + data[31] = data[25]; + data[32] = data[26]; + data[33] = min_t(uint32_t, 63U, 63 * sqrt_term_1e3 / 1000); + data[34] = min_t(uint32_t, 127U, 64 * sqrt_term_1e3 / 1000); + data[35] = 0x40; + data[36] = 0x40; + data[37] = 0x2C; + data[38] = 0x00; + data[39] = 0x00; + + for (i = 0; i < 40; i++) { + ret = ad9361_spi_write(phy->spi, 0x200 + i, data[i]); + if (ret < 0) + return ret; + } + + return 0; +} + +/** + * Perform a RX TIA calibration. + * @param phy The AD9361 state structure. + * @param bb_bw_Hz The baseband bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_tia_calib(struct ad9361_rf_phy *phy, uint32_t bb_bw_Hz) +{ + uint32_t Cbbf, R2346; + uint64_t CTIA_fF; + + uint8_t reg1EB = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_MSB); + uint8_t reg1EC = ad9361_spi_read(phy->spi, REG_RX_BBF_C3_LSB); + uint8_t reg1E6 = ad9361_spi_read(phy->spi, REG_RX_BBF_R2346); + uint8_t reg1DB, reg1DF, reg1DD, reg1DC, reg1DE, temp; + + dev_dbg(&phy->spi->dev, "%s : bb_bw_Hz %"PRIu32, + __func__, bb_bw_Hz); + + bb_bw_Hz = clamp(bb_bw_Hz, 200000UL, 20000000UL); + + Cbbf = (reg1EB * 160) + (reg1EC * 10) + 140; /* fF */ + R2346 = 18300 * RX_BBF_R2346(reg1E6); + + CTIA_fF = Cbbf * R2346 * 560ULL; + do_div(&CTIA_fF, 3500000UL); + + if (bb_bw_Hz <= 3000000UL) + reg1DB = 0xE0; + else if (bb_bw_Hz <= 10000000UL) + reg1DB = 0x60; + else + reg1DB = 0x20; + + if (CTIA_fF > 2920ULL) { + reg1DC = 0x40; + reg1DE = 0x40; + temp = min(127U, DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 320U)); + reg1DD = temp; + reg1DF = temp; + } else { + temp = DIV_ROUND_CLOSEST((uint32_t)CTIA_fF - 400, 40U) + 0x40; + reg1DC = temp; + reg1DE = temp; + reg1DD = 0; + reg1DF = 0; + } + + ad9361_spi_write(phy->spi, REG_RX_TIA_CONFIG, reg1DB); + ad9361_spi_write(phy->spi, REG_TIA1_C_LSB, reg1DC); + ad9361_spi_write(phy->spi, REG_TIA1_C_MSB, reg1DD); + ad9361_spi_write(phy->spi, REG_TIA2_C_LSB, reg1DE); + ad9361_spi_write(phy->spi, REG_TIA2_C_MSB, reg1DF); + + return 0; +} + +/** + * Perform a baseband RX analog filter calibration. + * @param phy The AD9361 state structure. + * @param rx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t rx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target; + uint8_t tmp; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : rx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, rx_bb_bw, bbpll_freq); + + rx_bb_bw = clamp(rx_bb_bw, 200000UL, 28000000UL); + + /* 1.4 * BBBW * 2PI / ln(2) */ + target = 126906UL * (rx_bb_bw / 10000UL); + phy->rxbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set RX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_RX_BBF_TUNE_DIVIDE, phy->rxbbf_div); + ad9361_spi_writef(phy->spi, REG_RX_BBF_TUNE_CONFIG, BIT(0), + phy->rxbbf_div >> 8); + + /* Write the BBBW into registers 0x1FB and 0x1FC */ + ad9361_spi_write(phy->spi, REG_RX_BBBW_MHZ, rx_bb_bw / 1000000UL); + + tmp = DIV_ROUND_CLOSEST((rx_bb_bw % 1000000UL) * 128, 1000000UL); + ad9361_spi_write(phy->spi, REG_RX_BBBW_KHZ, min_t(uint8_t, 127, tmp)); + + ad9361_spi_write(phy->spi, REG_RX_MIX_LO_CM, + RX_MIX_LO_CM(0x3F)); /* Set Rx Mix LO CM */ + ad9361_spi_write(phy->spi, REG_RX_MIX_GM_CONFIG, + RX_MIX_GM_PLOAD(3)); /* Set GM common mode */ + + /* Enable the RX BBF tune circuit by writing 0x1E2=0x02 and 0x1E3=0x02 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, RX1_TUNE_RESAMPLE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, RX2_TUNE_RESAMPLE); + + /* Start the RX Baseband Filter calibration in register 0x016[7] */ + /* Calibration is complete when register 0x016[7] self clears */ + ret = ad9361_run_calibration(phy, RX_BB_TUNE_CAL); + + /* Disable the RX baseband filter tune circuit, write 0x1E2=3, 0x1E3=3 */ + ad9361_spi_write(phy->spi, REG_RX1_TUNE_CTRL, + RX1_TUNE_RESAMPLE | RX1_PD_TUNE); + ad9361_spi_write(phy->spi, REG_RX2_TUNE_CTRL, + RX2_TUNE_RESAMPLE | RX2_PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX analog filter calibration. + * @param phy The AD9361 state structure. + * @param tx_bb_bw The baseband bandwidth [Hz]. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_analog_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw, + uint32_t bbpll_freq) +{ + uint32_t target, txbbf_div; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32" bbpll_freq %"PRIu32, + __func__, tx_bb_bw, bbpll_freq); + + tx_bb_bw = clamp(tx_bb_bw, 625000UL, 20000000UL); + + /* 1.6 * BBBW * 2PI / ln(2) */ + target = 145036 * (tx_bb_bw / 10000UL); + txbbf_div = min_t(uint32_t, 511UL, DIV_ROUND_UP(bbpll_freq, target)); + + /* Set TX baseband filter divide value */ + ad9361_spi_write(phy->spi, REG_TX_BBF_TUNE_DIVIDER, txbbf_div); + ad9361_spi_writef(phy->spi, REG_TX_BBF_TUNE_MODE, + TX_BBF_TUNE_DIVIDER, txbbf_div >> 8); + + /* Enable the TX baseband filter tune circuit by setting 0x0CA=0x22. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, TUNER_RESAMPLE | TUNE_CTRL(1)); + + /* Start the TX Baseband Filter calibration in register 0x016[6] */ + /* Calibration is complete when register 0x016[] self clears */ + ret = ad9361_run_calibration(phy, TX_BB_TUNE_CAL); + + /* Disable the TX baseband filter tune circuit by writing 0x0CA=0x26. */ + ad9361_spi_write(phy->spi, REG_TX_TUNE_CTRL, + TUNER_RESAMPLE | TUNE_CTRL(1) | PD_TUNE); + + return ret; +} + +/** + * Perform a baseband TX secondary filter calibration. + * @param phy The AD9361 state structure. + * @param tx_rf_bw The RF bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_bb_second_filter_calib(struct ad9361_rf_phy *phy, + uint32_t tx_bb_bw) +{ + uint64_t cap; + uint32_t corner, res, div; + uint32_t reg_conf, reg_res; + int32_t ret, i; + + dev_dbg(&phy->spi->dev, "%s : tx_bb_bw %"PRIu32, + __func__, tx_bb_bw); + + tx_bb_bw = clamp(tx_bb_bw, 530000UL, 20000000UL); + + /* BBBW * 5PI */ + corner = 15708 * (tx_bb_bw / 10000UL); + + for (i = 0, res = 1; i < 4; i++) { + div = corner * res; + cap = (500000000ULL) + (div >> 1); + do_div(&cap, div); + cap -= 12ULL; + if (cap < 64ULL) + break; + + res <<= 1; + } + + if (cap > 63ULL) + cap = 63ULL; + + if (tx_bb_bw <= 4500000UL) + reg_conf = 0x59; + else if (tx_bb_bw <= 12000000UL) + reg_conf = 0x56; + else + reg_conf = 0x57; + + switch (res) { + case 1: + reg_res = 0x0C; + break; + case 2: + reg_res = 0x04; + break; + case 4: + reg_res = 0x03; + break; + case 8: + reg_res = 0x01; + break; + default: + reg_res = 0x01; + } + + ret = ad9361_spi_write(phy->spi, REG_CONFIG0, reg_conf); + ret |= ad9361_spi_write(phy->spi, REG_RESISTOR, reg_res); + ret |= ad9361_spi_write(phy->spi, REG_CAPACITOR, (uint8_t)cap); + + return ret; +} + +/** + * Perform a RF synthesizer charge pump calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock rate [Hz]. + * @param tx The Synthesizer TX = 1, RX = 0. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txrx_synth_cp_calib(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz, bool tx) +{ + uint32_t offs = tx ? 0x40 : 0; + uint32_t vco_cal_cnt; + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32" : is_tx %d", + __func__, ref_clk_hz, tx); + + /* REVIST: */ + ad9361_spi_write(phy->spi, REG_RX_CP_LEVEL_DETECT + offs, 0x17); + + ad9361_spi_write(phy->spi, REG_RX_DSM_SETUP_1 + offs, 0x0); + + ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE + offs, 0x00); + ad9361_spi_write(phy->spi, REG_RX_VCO_LDO + offs, 0x0B); + ad9361_spi_write(phy->spi, REG_RX_VCO_PD_OVERRIDES + offs, 0x02); + ad9361_spi_write(phy->spi, REG_RX_CP_CURRENT + offs, 0x80); + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, CP_OFFSET_OFF); + + /* see Table 70 Example Calibration Times for RF VCO Cal */ + if (phy->pdata->fdd) { + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(3) | FB_CLOCK_ADV(2); + } else { + if (ref_clk_hz > 40000000UL) + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(1) | + FB_CLOCK_ADV(2); + else + vco_cal_cnt = VCO_CAL_EN | VCO_CAL_COUNT(0) | + FB_CLOCK_ADV(2); + } + + ad9361_spi_write(phy->spi, REG_RX_VCO_CAL + offs, vco_cal_cnt); + + /* Enable FDD mode during calibrations */ + + if (!phy->pdata->fdd) { + ad9361_spi_writef(phy->spi, REG_PARALLEL_PORT_CONF_3, + HALF_DUPLEX_MODE, 0); + } + + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, DUAL_SYNTH_MODE); + ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_1, + FORCE_ALERT_STATE | + TO_ALERT); + ad9361_spi_write(phy->spi, REG_ENSM_MODE, FDD_MODE); + + ad9361_spi_write(phy->spi, REG_RX_CP_CONFIG + offs, + CP_OFFSET_OFF | CP_CAL_ENABLE); + + return ad9361_check_cal_done(phy, REG_RX_CAL_STATUS + offs, + CP_CAL_VALID, 1); +} + +/** + * Perform a baseband DC offset calibration. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_dc_offset_calib(struct ad9361_rf_phy *phy) +{ + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_COUNT, 0x3F); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_SHIFT, BB_DC_M_SHIFT(0xF)); + ad9361_spi_write(phy->spi, REG_BB_DC_OFFSET_ATTEN, BB_DC_OFFSET_ATTEN(1)); + + return ad9361_run_calibration(phy, BBDC_CAL); +} + +/** + * Perform a RF DC offset calibration. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The RX LO frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rf_dc_offset_calib(struct ad9361_rf_phy *phy, + uint64_t rx_freq) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s : rx_freq %"PRIu64, + __func__, rx_freq); + + ad9361_spi_write(spi, REG_WAIT_COUNT, 0x20); + + if (rx_freq <= 4000000000ULL) { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_low); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(2)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_low)); + } else { + ad9361_spi_write(spi, REG_RF_DC_OFFSET_COUNT, + phy->pdata->rf_dc_offset_count_high); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_CONFIG_1, + RF_DC_CALIBRATION_COUNT(4) | DAC_FS(3)); + ad9361_spi_write(spi, REG_RF_DC_OFFSET_ATTEN, + RF_DC_OFFSET_ATTEN( + phy->pdata->dc_offset_attenuation_high)); + } + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(3)); + + if (phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2)) { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD); + } else { + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + return ad9361_run_calibration(phy, RFDC_CAL); +} + +/** + * Update RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw RF RX bandwidth [Hz]. + * @param rf_tx_bw RF TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + uint32_t real_rx_bandwidth = rf_rx_bw / 2; + uint32_t real_tx_bandwidth = rf_tx_bw / 2; + uint32_t bbpll_freq; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: %"PRIu32" %"PRIu32, + __func__, rf_rx_bw, rf_tx_bw); + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + return 0; +} + +/** + * TX Quad Calib. + * @param phy The AD9361 state structure. + * @param phase phase + * @param rxnco_word Rx NCO word. + * @param decim decim + * @param res res + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t __ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, uint32_t phase, + uint32_t rxnco_word, uint32_t decim, uint8_t *res) +{ + int32_t ret; + + ad9361_spi_write(phy->spi, REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET, + RX_NCO_FREQ(rxnco_word) | RX_NCO_PHASE_OFFSET(phase)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | QUAD_CAL_SOFT_RESET | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + ad9361_spi_write(phy->spi, REG_QUAD_CAL_CTRL, + SETTLE_MAIN_ENABLE | DC_OFFSET_ENABLE | + GAIN_ENABLE | PHASE_ENABLE | M_DECIM(decim)); + + ret = ad9361_run_calibration(phy, TX_QUAD_CAL); + if (ret < 0) + return ret; + + if (res) { + *res = ad9361_spi_read(phy->spi, + (phy->pdata->rx1tx1_mode_use_tx_num == 2) ? + REG_QUAD_CAL_STATUS_TX2 : REG_QUAD_CAL_STATUS_TX1) & + (TX1_LO_CONV | TX1_SSB_CONV); + if (phy->pdata->rx2tx2) + *res &= ad9361_spi_read(phy->spi, REG_QUAD_CAL_STATUS_TX2) & + (TX2_LO_CONV | TX2_SSB_CONV); + } + + return 0; +} + +/** + * Loop through all possible phase offsets in case the QUAD CAL doesn't converge. + * @param phy The AD9361 state structure. + * @param rxnco_word Rx NCO word. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_tx_quad_phase_search(struct ad9361_rf_phy *phy, + uint32_t rxnco_word, uint8_t decim) +{ + int32_t i, ret; + uint8_t field[64], val; + uint32_t start; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + for (i = 0; i < (int64_t)(ARRAY_SIZE(field) / 2); i++) { + ret = __ad9361_tx_quad_calib(phy, i, rxnco_word, decim, &val); + if (ret < 0) + return ret; + + /* Handle 360/0 wrap around */ + field[i] = field[i + 32] = !((val & TX1_LO_CONV) && (val & TX1_SSB_CONV)); + } + + ret = ad9361_find_opt(field, ARRAY_SIZE(field), &start); + + phy->last_tx_quad_cal_phase = (start + ret / 2) & 0x1F; + +#ifdef _DEBUG + for (i = 0; i < 64; i++) { + printk("%c", (field[i] ? '#' : 'o')); + } +#ifdef WIN32 + printk(" RX_NCO_PHASE_OFFSET(%d, 0x%X) \n", phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#else + printk(" RX_NCO_PHASE_OFFSET(%"PRIu32", 0x%"PRIX32") \n", + phy->last_tx_quad_cal_phase, + phy->last_tx_quad_cal_phase); +#endif +#endif + + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, rxnco_word, + decim, NULL); + if (ret < 0) + return ret; + + return 0; +} + +/** + * Perform a TX quadrature calibration. + * @param phy The AD9361 state structure. + * @param bw The bandwidth [Hz]. + * @param rx_phase The optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + */ + +static int ad9361_tx_quad_calib(struct ad9361_rf_phy *phy, + uint32_t bw_rx, uint32_t bw_tx, + int32_t rx_phase) +{ + struct spi_desc *spi = phy->spi; + uint32_t clktf, clkrf; + int32_t txnco_word, rxnco_word, txnco_freq, ret; + uint8_t __rx_phase = 0, reg_inv_bits = 0, val, decim; + bool phase_inversion_en; + + ret = 0; + if (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) { + if (phy->pdata->lo_powerdown_managed_en) { + ad9361_spi_writef(spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + TX_LO_POWER_DOWN, 0); + } else { + dev_err(dev, + "%s : Tx QUAD Cal abort due to TX LO in powerdown\n", + __func__); + return -EFAULT; + } + } + /* + * Find NCO frequency that matches this equation: + * BW / 4 = Rx NCO freq = Tx NCO freq: + * Rx NCO = ClkRF * (rxNCO <1:0> + 1) / 32 + * Tx NCO = ClkTF * (txNCO <1:0> + 1) / 32 + */ + + clkrf = clk_get_rate(phy, phy->ref_clk_scale[CLKRF_CLK]); + clktf = clk_get_rate(phy, phy->ref_clk_scale[CLKTF_CLK]); + + dev_dbg(&phy->spi->dev, "%s : bw_tx %"PRIu32" clkrf %"PRIu32" clktf %"PRIu32, + __func__, bw_tx, clkrf, clktf); + + txnco_word = DIV_ROUND_CLOSEST(bw_tx * 8, clktf) - 1; + txnco_word = clamp_t(int, txnco_word, 0, 3); + rxnco_word = txnco_word; + + dev_dbg(dev, "Tx NCO frequency: %"PRIu32" (BW/4: %"PRIu32") txnco_word %"PRId32, + clktf * (txnco_word + 1) / 32, bw_tx / 4, txnco_word); + + if (clktf <= 4000000UL) + decim = 2; + else + decim = 3; + + if (clkrf == (2 * clktf)) { + __rx_phase = 0x0E; + switch (txnco_word) { + case 0: + txnco_word++; + break; + case 1: + rxnco_word--; + break; + case 2: + rxnco_word -= 2; + txnco_word--; + break; + case 3: + rxnco_word -= 2; /* REVISIT */ + __rx_phase = 0x08; + break; + } + } else if (clkrf == clktf) { + switch (txnco_word) { + case 0: + case 3: + __rx_phase = 0x15; + break; + case 2: + __rx_phase = 0x1F; + break; + case 1: + if (ad9361_spi_readf(spi, + REG_TX_ENABLE_FILTER_CTRL, 0x3F) == 0x22) + __rx_phase = 0x15; /* REVISIT */ + else + __rx_phase = 0x1A; + break; + } + } else + dev_err(dev, "Unhandled case in %s line %d clkrf %"PRIu32" clktf %"PRIu32, + __func__, __LINE__, clkrf, clktf); + + if (rx_phase >= 0) + __rx_phase = rx_phase; + + txnco_freq = clktf * (txnco_word + 1) / 32; + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + /* Make sure the BW during calibration is wide enough */ + ret = __ad9361_update_rf_bandwidth(phy, txnco_freq * 8, txnco_freq * 8); + if (ret < 0) + goto out_restore; + } + + phase_inversion_en = phy->pdata->rx1rx2_phase_inversion_en || + (phy->pdata->port_ctrl.pp_conf[1] & INVERT_RX2); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 0); + + reg_inv_bits = ad9361_spi_read(spi, REG_INVERT_BITS); + + ad9361_spi_write(spi, REG_INVERT_BITS, + INVERT_RX1_RF_DC_CGOUT_WORD | + INVERT_RX2_RF_DC_CGOUT_WORD); + } + + ad9361_spi_writef(spi, REG_KEXP_2, TX_NCO_FREQ(~0), txnco_word); + ad9361_spi_write(spi, REG_QUAD_CAL_COUNT, 0xFF); + ad9361_spi_write(spi, REG_KEXP_1, KEXP_TX(1) | KEXP_TX_COMP(3) | + KEXP_DC_I(3) | KEXP_DC_Q(3)); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH, 0x03); + ad9361_spi_write(spi, REG_MAG_FTEST_THRESH_2, 0x03); + + if (phy->tx_quad_lpf_tia_match < 0) /* set in ad9361_load_gt() */ + dev_err(dev, "failed to find suitable LPF TIA value in gain table\n"); + else + ad9361_spi_write(spi, REG_TX_QUAD_FULL_LMT_GAIN, + phy->tx_quad_lpf_tia_match); + + ad9361_spi_write(spi, REG_QUAD_SETTLE_COUNT, 0xF0); + ad9361_spi_write(spi, REG_TX_QUAD_LPF_GAIN, 0x00); + + if (rx_phase != -2) { + ret = __ad9361_tx_quad_calib(phy, __rx_phase, rxnco_word, decim, &val); + + dev_dbg(dev, "LO leakage: %d Quadrature Calibration: %d : rx_phase %d\n", + !!(val & TX1_LO_CONV), !!(val & TX1_SSB_CONV), __rx_phase); + + /* Calibration failed -> try last phase offset */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) { + if (phy->last_tx_quad_cal_phase < 31) + ret = __ad9361_tx_quad_calib(phy, phy->last_tx_quad_cal_phase, + rxnco_word, decim, &val); + } else { + phy->last_tx_quad_cal_phase = __rx_phase; + } + } else { + /* force phase search */ + val = 0; + } + /* Calibration failed -> loop through all 32 phase offsets */ + if (val != (TX1_LO_CONV | TX1_SSB_CONV)) + ret = ad9361_tx_quad_phase_search(phy, rxnco_word, decim); + + if (phase_inversion_en) { + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_write(spi, REG_INVERT_BITS, reg_inv_bits); + } + + if (txnco_freq > (int64_t)(bw_rx / 4) || txnco_freq > (int64_t)(bw_tx / 4)) { + __ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + } + +out_restore: + /* Restore synthesizer powerdown configuration */ + if (phy->pdata->lo_powerdown_managed_en && + (phy->cached_synth_pd[0] & TX_LO_POWER_DOWN)) + ad9361_synth_lo_powerdown(phy, LO_DONTCARE, LO_DONTCARE); + + return ret; +} + +/** + * Setup RX tracking calibrations. + * @param phy The AD9361 state structure. + * @param bbdc_track Set true, will enable the BBDC tracking. + * @param rfdc_track Set true, will enable the RFDC tracking. + * @param rxquad_track Set true, will enable the RXQUAD tracking. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track) +{ + struct spi_desc *spi = phy->spi; + uint32_t qtrack = 0; + + dev_dbg(&spi->dev, "%s : bbdc_track=%d, rfdc_track=%d, rxquad_track=%d", + __func__, bbdc_track, rfdc_track, rxquad_track); + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_2, + CALIBRATION_CONFIG2_DFLT | K_EXP_PHASE(0x15)); + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_3, + PREVENT_POS_LOOP_GAIN | K_EXP_AMPLITUDE(0x15)); + + ad9361_spi_write(spi, REG_DC_OFFSET_CONFIG2, + USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL | + DC_OFFSET_UPDATE(phy->pdata->dc_offset_update_events) | + (bbdc_track ? ENABLE_BB_DC_OFFSET_TRACKING : 0) | + (rfdc_track ? ENABLE_RF_OFFSET_TRACKING : 0)); + + ad9361_spi_writef(spi, REG_RX_QUAD_GAIN2, + CORRECTION_WORD_DECIMATION_M(~0), + phy->pdata->qec_tracking_slow_mode_en ? 4 : 0); + + if (rxquad_track) { + if (phy->pdata->rx2tx2) + qtrack = ENABLE_TRACKING_MODE_CH1 | ENABLE_TRACKING_MODE_CH2; + else + qtrack = (phy->pdata->rx1tx1_mode_use_rx_num == 1) ? + ENABLE_TRACKING_MODE_CH1 : ENABLE_TRACKING_MODE_CH2; + } + + ad9361_spi_write(spi, REG_CALIBRATION_CONFIG_1, + ENABLE_PHASE_CORR | ENABLE_GAIN_CORR | + FREE_RUN_MODE | ENABLE_CORR_WORD_DECIMATION | + qtrack); + + return 0; +} + +/** + * Enable/disable the VCO cal. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_vco_cal_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + dev_dbg(&phy->spi->dev, "%s : state %d", + __func__, enable); + + return ad9361_spi_writef(phy->spi, + tx ? REG_TX_PFD_CONFIG : REG_RX_PFD_CONFIG, + BYPASS_LD_SYNTH, !enable); +} + +/** + * Enable/disable the ext. LO. + * @param phy The AD9361 state structure. + * @param rx Set true for rx. + * @param enable Set true to enable. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_trx_ext_lo_control(struct ad9361_rf_phy *phy, + bool tx, bool enable) +{ + uint32_t val = enable ? ~0 : 0; + int32_t ret; + + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + + bool mcs_rf_enable = ad9361_spi_readf(phy->spi, + REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + MCS_RF_ENABLE); + + dev_dbg(&phy->spi->dev, "%s : %s state %d", __func__, + tx ? "TX" : "RX", enable); + + if (tx) { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + TX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_tx_rfpll_div); + + if (enable) + phy->cached_synth_pd[0] |= TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[0] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + TX_SYNTH_PTAT_POWER_DOWN | + TX_SYNTH_VCO_POWER_DOWN); + + + ret |= ad9361_spi_write(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[0]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_TX_LO_GEN_POWER_MODE, + TX_LO_GEN_POWER_MODE(val)); + } else { + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_RX_SYNTH, mcs_rf_enable ? 0 : enable); + + ret = ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + RX_SYNTH_READY_MASK, enable); + + ret |= ad9361_spi_writef(phy->spi, REG_RFPLL_DIVIDERS, + RX_VCO_DIVIDER(~0), enable ? 7 : + phy->cached_rx_rfpll_div); + + if (enable) + phy->cached_synth_pd[1] |= RX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN; + else + phy->cached_synth_pd[1] &= ~(TX_SYNTH_VCO_ALC_POWER_DOWN | + RX_SYNTH_PTAT_POWER_DOWN | + RX_SYNTH_VCO_POWER_DOWN); + + ret |= ad9361_spi_write(phy->spi, REG_RX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd[1]); + + ret |= ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + RX_EXT_VCO_BUFFER_POWER_DOWN, !enable); + + ret |= ad9361_spi_write(phy->spi, REG_RX_LO_GEN_POWER_MODE, + RX_LO_GEN_POWER_MODE(val)); + } + + return ret; +} + +/** + * Power down the TX and/or RX Local Oscillators. + * @param phy The AD9361 state structure. + * @param rx The RX LO setting. + * @param tx The TX LO setting. + * @return 0 in case of success, negative error code otherwise. + */ +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx) +{ + dev_dbg(&phy->spi->dev, "%s : RX(%d) TX(%d)", __func__, rx, tx); + + switch (rx) { + case LO_OFF: + phy->cached_synth_pd[1] |= RX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[1] &= ~RX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + switch (tx) { + case LO_OFF: + phy->cached_synth_pd[0] |= TX_LO_POWER_DOWN; + break; + case LO_ON: + phy->cached_synth_pd[0] &= ~TX_LO_POWER_DOWN; + break; + case LO_DONTCARE: + break; + } + + return ad9361_spi_writem(phy->spi, REG_TX_SYNTH_POWER_DOWN_OVERRIDE, + phy->cached_synth_pd, 2); +} + +/** + * Setup the reference clock delay unit counter register. + * @param phy The AD9361 state structure. + * @param ref_clk_hz The reference clock frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_ref_clk_cycles(struct ad9361_rf_phy *phy, + uint32_t ref_clk_hz) +{ + dev_dbg(&phy->spi->dev, "%s : ref_clk_hz %"PRIu32, + __func__, ref_clk_hz); + + return ad9361_spi_write(phy->spi, REG_REFERENCE_CLOCK_CYCLES, + REFERENCE_CLOCK_CYCLES_PER_US((ref_clk_hz / 1000000UL) - 1)); +} + +/** + * Setup the DCXO tune. + * @param phy The AD9361 state structure. + * @param coarse The DCXO tune coarse. + * @param fine The DCXO tune fine. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine) +{ + dev_dbg(&phy->spi->dev, "%s : coarse %"PRIu32" fine %"PRIu32, + __func__, coarse, fine); + + if (phy->pdata->use_extclk) + return -ENODEV; + + ad9361_spi_write(phy->spi, REG_DCXO_COARSE_TUNE, + DCXO_TUNE_COARSE(coarse)); + ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_LOW, + DCXO_TUNE_FINE_LOW(fine)); + return ad9361_spi_write(phy->spi, REG_DCXO_FINE_TUNE_HIGH, + DCXO_TUNE_FINE_HIGH(fine)); +} + +/** + * Setup TXMON. + * @param phy The AD9361 state structure. + * @param ctrl The TXMON settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_setup(struct ad9361_rf_phy *phy, + struct tx_monitor_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_TPM_MODE_ENABLE, + (ctrl->one_shot_mode_en ? ONE_SHOT_MODE : 0) | + TX_MON_DURATION(ilog2(ctrl->tx_mon_duration / 16))); + + ad9361_spi_write(spi, REG_TX_MON_DELAY, ctrl->tx_mon_delay & 0xFF); + ad9361_spi_writef(spi, REG_TX_LEVEL_THRESH, + TX_MON_DELAY_COUNTER(~0), ctrl->tx_mon_delay >> 8); + + ad9361_spi_write(spi, REG_TX_MON_1_CONFIG, + TX_MON_1_LO_CM(ctrl->tx1_mon_lo_cm) | + TX_MON_1_GAIN(ctrl->tx1_mon_front_end_gain)); + ad9361_spi_write(spi, REG_TX_MON_2_CONFIG, + TX_MON_2_LO_CM(ctrl->tx2_mon_lo_cm) | + TX_MON_2_GAIN(ctrl->tx2_mon_front_end_gain)); + + ad9361_spi_write(spi, REG_TX_ATTEN_THRESH, + ctrl->low_high_gain_threshold_mdB / 250); + + ad9361_spi_write(spi, REG_TX_MON_HIGH_GAIN, + TX_MON_HIGH_GAIN(ctrl->high_gain_dB)); + + ad9361_spi_write(spi, REG_TX_MON_LOW_GAIN, + (ctrl->tx_mon_track_en ? TX_MON_TRACK : 0) | + TX_MON_LOW_GAIN(ctrl->low_gain_dB)); + + return 0; +} + +/** + * Enable TXMON. + * @param phy The AD9361 state structure. + * @param en_mask The enable mask. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_txmon_control(struct ad9361_rf_phy *phy, + int32_t en_mask) +{ + dev_dbg(&phy->spi->dev, "%s: mask 0x%"PRIx32, __func__, en_mask); + +#if 0 + if (!phy->pdata->fdd && en_mask) { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 1); + phy->txmon_tdd_en = true; + } else { + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_1, + ENABLE_RX_DATA_PORT_FOR_CAL, 0); + phy->txmon_tdd_en = false; + } +#endif + + ad9361_spi_writef(phy->spi, REG_ANALOG_POWER_DOWN_OVERRIDE, + TX_MONITOR_POWER_DOWN(~0), ~en_mask); + + ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX1_MON_ENABLE, !!(en_mask & TX_1)); + + return ad9361_spi_writef(phy->spi, REG_TPM_MODE_ENABLE, + TX2_MON_ENABLE, !!(en_mask & TX_2)); +} + +/** +* Setup the RF port. +* Note: +* val +* 0 (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced +* 1 (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced +* 2 (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced +* +* 3 RX1A_N and RX2A_N enabled; unbalanced +* 4 RX1A_P and RX2A_P enabled; unbalanced +* 5 RX1B_N and RX2B_N enabled; unbalanced +* 6 RX1B_P and RX2B_P enabled; unbalanced +* 7 RX1C_N and RX2C_N enabled; unbalanced +* 8 RX1C_P and RX2C_P enabled; unbalanced +* 9 TX_MON1 +* 10 TX_MON2 +* 11 TX_MON1 & TX_MON2 +* @param phy The AD9361 state structure. +* @param is_out TX RF output port enabled. +* @param rx_inputs RX input option identifier +* @param txb TX output option identifier +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb) +{ + uint32_t val; + + if (rx_inputs > 11) + return -EINVAL; + + if (!is_out) { + if (rx_inputs > 8) + return ad9361_txmon_control(phy, rx_inputs & (TX_1 | TX_2)); + else + ad9361_txmon_control(phy, 0); + } + + if (rx_inputs < 3) + val = 3 << (rx_inputs * 2); + else + val = 1 << (rx_inputs - 3); + + if (txb) + val |= TX_OUTPUT; /* Select TX1B, TX2B */ + + dev_dbg(&phy->spi->dev, "%s : INPUT_SELECT 0x%"PRIx32, + __func__, val); + + return ad9361_spi_write(phy->spi, REG_INPUT_SELECT, val); +} + +/** + * Setup the Parallel Port (Digital Data Interface). + * @param phy The AD9361 state structure. + * @param restore_c3 Set true, will restore the Parallel Port Configuration 3 + * register. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_pp_port_setup(struct ad9361_rf_phy *phy, bool restore_c3) +{ + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (restore_c3) { + return ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, + pd->port_ctrl.pp_conf[2]); + } + + /* Sanity check */ + if (pd->port_ctrl.pp_conf[2] & LVDS_MODE) + pd->port_ctrl.pp_conf[2] &= + ~(HALF_DUPLEX_MODE | SINGLE_DATA_RATE | SINGLE_PORT_MODE); + + if (pd->port_ctrl.pp_conf[2] & FULL_PORT) + pd->port_ctrl.pp_conf[2] &= ~(HALF_DUPLEX_MODE | SINGLE_PORT_MODE); + + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_1, pd->port_ctrl.pp_conf[0]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_2, pd->port_ctrl.pp_conf[1]); + ad9361_spi_write(spi, REG_PARALLEL_PORT_CONF_3, pd->port_ctrl.pp_conf[2]); + ad9361_spi_write(spi, REG_RX_CLOCK_DATA_DELAY, pd->port_ctrl.rx_clk_data_delay); + ad9361_spi_write(spi, REG_TX_CLOCK_DATA_DELAY, pd->port_ctrl.tx_clk_data_delay); + + ad9361_spi_write(spi, REG_LVDS_BIAS_CTRL, pd->port_ctrl.lvds_bias_ctrl); + // ad9361_spi_write(spi, REG_DIGITAL_IO_CTRL, pd->port_ctrl.digital_io_ctrl); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL1, pd->port_ctrl.lvds_invert[0]); + ad9361_spi_write(spi, REG_LVDS_INVERT_CTRL2, pd->port_ctrl.lvds_invert[1]); + + if (pd->rx1rx2_phase_inversion_en || + (pd->port_ctrl.pp_conf[1] & INVERT_RX2)) { + + ad9361_spi_writef(spi, REG_PARALLEL_PORT_CONF_2, INVERT_RX2, 1); + ad9361_spi_writef(spi, REG_INVERT_BITS, + INVERT_RX2_RF_DC_CGOUT_WORD, 0); + } + + return 0; +} + +/** + * Setup the Gain Control Blocks (common function for MGC, AGC modes) + * @param phy The AD9361 state structure. + * @param ctrl The gain control settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gc_setup(struct ad9361_rf_phy *phy, + struct gain_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint32_t reg, tmp1, tmp2; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + reg = DEC_PWR_FOR_GAIN_LOCK_EXIT | DEC_PWR_FOR_LOCK_LEVEL | + DEC_PWR_FOR_LOW_PWR; + + if (ctrl->rx1_mode == RF_GAIN_HYBRID_AGC || + ctrl->rx2_mode == RF_GAIN_HYBRID_AGC) + reg |= SLOW_ATTACK_HYBRID_MODE; + + reg |= RX1_GAIN_CTRL_SETUP(ctrl->rx1_mode) | + RX2_GAIN_CTRL_SETUP(ctrl->rx2_mode); + + phy->agc_mode[0] = ctrl->rx1_mode; + phy->agc_mode[1] = ctrl->rx2_mode; + + ad9361_spi_write(spi, REG_AGC_CONFIG_1, reg); // Gain Control Mode Select + + /* AGC_USE_FULL_GAIN_TABLE handled in ad9361_load_gt() */ + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX1, + ctrl->mgc_rx1_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, MAN_GAIN_CTRL_RX2, + ctrl->mgc_rx2_ctrl_inp_en); + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, DIG_GAIN_EN, + ctrl->dig_gain_en); + + ctrl->adc_ovr_sample_size = clamp_t(uint8_t, ctrl->adc_ovr_sample_size, 1U, 8U); + reg = ADC_OVERRANGE_SAMPLE_SIZE(ctrl->adc_ovr_sample_size - 1); + + if (has_split_gt && phy->pdata->split_gt && + (ctrl->mgc_rx1_ctrl_inp_en || ctrl->mgc_rx2_ctrl_inp_en)) { + switch (ctrl->mgc_split_table_ctrl_inp_gain_mode) { + case 1: + reg &= ~INCDEC_LMT_GAIN; + break; + case 2: + reg |= INCDEC_LMT_GAIN; + break; + default: + case 0: + reg |= USE_AGC_FOR_LMTLPF_GAIN; + break; + } + } + + ctrl->mgc_inc_gain_step = clamp_t(uint8_t, ctrl->mgc_inc_gain_step, 1U, 8U); + reg |= MANUAL_INCR_STEP_SIZE(ctrl->mgc_inc_gain_step - 1); + ad9361_spi_write(spi, REG_AGC_CONFIG_3, + reg); // Incr Step Size, ADC Overrange Size + + ctrl->mgc_dec_gain_step = clamp_t(uint8_t, ctrl->mgc_dec_gain_step, 1U, 8U); + reg = MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(ctrl->mgc_dec_gain_step - 1); + ad9361_spi_write(spi, REG_PEAK_WAIT_TIME, + reg); // Decr Step Size, Peak Overload Time + + if (ctrl->dig_gain_en) + ad9361_spi_write(spi, REG_DIGITAL_GAIN, + MAXIMUM_DIGITAL_GAIN(ctrl->max_dig_gain) | + DIG_GAIN_STP_SIZE(ctrl->dig_gain_step_size)); + + if (ctrl->adc_large_overload_thresh >= ctrl->adc_small_overload_thresh) { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Large Overload Threshold + } else { + ad9361_spi_write(spi, REG_ADC_SMALL_OVERLOAD_THRESH, + ctrl->adc_large_overload_thresh); // ADC Small Overload Threshold + ad9361_spi_write(spi, REG_ADC_LARGE_OVERLOAD_THRESH, + ctrl->adc_small_overload_thresh); // ADC Large Overload Threshold + } + + reg = (ctrl->lmt_overload_high_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_write(spi, REG_LARGE_LMT_OVERLOAD_THRESH, reg); + reg = (ctrl->lmt_overload_low_thresh / 16) - 1; + reg = clamp(reg, 0U, 63U); + ad9361_spi_writef(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + SMALL_LMT_OVERLOAD_THRESH(~0), reg); + + if (has_split_gt && phy->pdata->split_gt) { + /* REVIST */ + ad9361_spi_write(spi, REG_RX1_MANUAL_LPF_GAIN, 0x58); // Rx1 LPF Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_LPF_GAIN, 0x18); // Rx2 LPF Gain Index + ad9361_spi_write(spi, REG_FAST_INITIAL_LMT_GAIN_LIMIT, + 0x27); // Initial LMT Gain Limit + } + + ad9361_spi_write(spi, REG_RX1_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx1 Digital Gain Index + ad9361_spi_write(spi, REG_RX2_MANUAL_DIGITALFORCED_GAIN, + 0x00); // Rx2 Digital Gain Index + + reg = clamp_t(uint8_t, ctrl->low_power_thresh, 0U, 64U) * 2; + ad9361_spi_write(spi, REG_FAST_LOW_POWER_THRESH, reg); // Low Power Threshold + ad9361_spi_write(spi, REG_TX_SYMBOL_ATTEN_CONFIG, + 0x00); // Tx Symbol Gain Control + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + USE_HB1_OUT_FOR_DEC_PWR_MEAS, + !ctrl->use_rx_fir_out_for_dec_pwr_meas); // USE HB1 or FIR output for power measurements + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + ENABLE_DEC_PWR_MEAS, 1); // Power Measurement Duration + + if (ctrl->rx1_mode == RF_GAIN_FASTATTACK_AGC || + ctrl->rx2_mode == RF_GAIN_FASTATTACK_AGC) + reg = ilog2(ctrl->f_agc_dec_pow_measuremnt_duration / 16); + else + reg = ilog2(ctrl->dec_pow_measuremnt_duration / 16); + + ad9361_spi_writef(spi, REG_DEC_POWER_MEASURE_DURATION_0, + DEC_POWER_MEASUREMENT_DURATION(~0), reg); // Power Measurement Duration + + /* AGC */ + + tmp1 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_high, 0U, 127U); + ad9361_spi_writef(spi, REG_AGC_LOCK_LEVEL, + AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(~0), + reg); + + tmp2 = reg = clamp_t(uint8_t, ctrl->agc_inner_thresh_low, 0U, 127U); + reg |= (ctrl->adc_lmt_small_overload_prevent_gain_inc ? + PREVENT_GAIN_INC : 0); + ad9361_spi_write(spi, REG_AGC_INNER_LOW_THRESH, reg); + + reg = AGC_OUTER_HIGH_THRESH(tmp1 - ctrl->agc_outer_thresh_high) | + AGC_OUTER_LOW_THRESH(ctrl->agc_outer_thresh_low - tmp2); + ad9361_spi_write(spi, REG_OUTER_POWER_THRESHS, reg); + + reg = AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_high_dec_steps) + | + AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_outer_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_2, reg); + + reg = ((ctrl->immed_gain_change_if_large_adc_overload) ? + IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD : 0) | + ((ctrl->immed_gain_change_if_large_lmt_overload) ? + IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD : 0) | + AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_high_dec_steps) | + AGC_INNER_LOW_THRESH_EXED_STP_SIZE(ctrl->agc_inner_thresh_low_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP1, reg); + + reg = LARGE_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_large_overload_exceed_counter) | + SMALL_ADC_OVERLOAD_EXED_COUNTER(ctrl->adc_small_overload_exceed_counter); + ad9361_spi_write(spi, REG_ADC_OVERLOAD_COUNTERS, reg); + + reg = DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE( + ctrl->f_agc_large_overload_inc_steps) | + LARGE_LPF_GAIN_STEP(ctrl->adc_large_overload_inc_steps); + ad9361_spi_write(spi, REG_GAIN_STP_CONFIG_2, reg); + + reg = LARGE_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_large_exceed_counter) | + SMALL_LMT_OVERLOAD_EXED_COUNTER(ctrl->lmt_overload_small_exceed_counter); + ad9361_spi_write(spi, REG_LMT_OVERLOAD_COUNTERS, reg); + + ad9361_spi_writef(spi, REG_GAIN_STP_CONFIG1, + DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(~0), + ctrl->lmt_overload_large_inc_steps); + + reg = DIG_SATURATION_EXED_COUNTER(ctrl->dig_saturation_exceed_counter) | + (ctrl->sync_for_gain_counter_en ? + ENABLE_SYNC_FOR_GAIN_COUNTER : 0); + ad9361_spi_write(spi, REG_DIGITAL_SAT_COUNTER, reg); + + /* + * Fast AGC + */ + + /* Fast AGC - Low Power */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_INCR_GAIN, + ctrl->f_agc_allow_agc_gain_increase); + + ad9361_spi_write(spi, REG_FAST_INCREMENT_TIME, + ctrl->f_agc_lp_thresh_increment_time); + + reg = ctrl->f_agc_lp_thresh_increment_steps - 1; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_DETECT_COUNT, + INCREMENT_GAIN_STP_LPFLMT(~0), reg); + + /* Fast AGC - Lock Level */ + /* Dual use see also agc_inner_thresh_high */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL, + ctrl->f_agc_lock_level_lmt_gain_increase_en); + + reg = ctrl->f_agc_lock_level_gain_increase_upper_limit; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_AGCLL_UPPER_LIMIT, + AGCLL_MAX_INCREASE(~0), reg); + + /* Fast AGC - Peak Detectors and Final Settling */ + reg = ctrl->f_agc_lpf_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(~0), + reg); + + reg = ctrl->f_agc_lmt_final_settling_steps; + reg = clamp_t(uint32_t, reg, 0U, 3U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(~0), reg); + + reg = ctrl->f_agc_final_overrange_count; + reg = clamp_t(uint32_t, reg, 0U, 7U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + FINAL_OVER_RANGE_COUNT(~0), reg); + + /* Fast AGC - Final Power Test */ + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + ENABLE_GAIN_INC_AFTER_GAIN_LOCK, + ctrl->f_agc_gain_increase_after_gain_lock_en); + + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Optimized Gain, 2 = Set Gain */ + + reg = ctrl->f_agc_gain_index_type_after_exit_rx_mode; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EXIT_RX_STATE, reg == SET_GAIN); + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE, + reg == OPTIMIZED_GAIN); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + USE_LAST_LOCK_LEVEL_FOR_SET_GAIN, + ctrl->f_agc_use_last_lock_level_for_set_gain_en); + + reg = ctrl->f_agc_optimized_gain_offset; + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN, + OPTIMIZE_GAIN_OFFSET(~0), reg); + + tmp1 = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en || + !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en || + ctrl->f_agc_rst_gla_en_agc_pulled_high_en; + + ad9361_spi_writef(spi, REG_AGC_CONFIG_2, + AGC_GAIN_UNLOCK_CTRL, tmp1); + + reg = !ctrl->f_agc_rst_gla_stronger_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_STRONG_SIGNAL_FREEZE, + DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL, reg); + + reg = ctrl->f_agc_rst_gla_stronger_sig_thresh_above_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_STRONGER_SIGNAL_THRESH, + STRONGER_SIGNAL_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_ENERGY_LOST_THRESH, + ENERGY_LOST_THRESH(~0), reg); + + reg = ctrl->f_agc_rst_gla_engergy_lost_goto_optim_gain_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, reg); + + reg = !ctrl->f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_ENERGY_LOST, reg); + + reg = ctrl->f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; + reg = clamp_t(uint32_t, reg, 0U, 63U); + ad9361_spi_writef(spi, REG_FAST_GAIN_LOCK_EXIT_COUNT, + GAIN_LOCK_EXIT_COUNT(~0), reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en || + !ctrl->f_agc_rst_gla_large_lmt_overload_en; + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG, reg); + + reg = !ctrl->f_agc_rst_gla_large_adc_overload_en; + ad9361_spi_writef(spi, REG_FAST_LOW_POWER_THRESH, + DONT_UNLOCK_GAIN_IF_ADC_OVRG, reg); + + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + if (ctrl->f_agc_rst_gla_en_agc_pulled_high_en) { + switch (ctrl->f_agc_rst_gla_if_en_agc_pulled_high_mode) { + case MAX_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 0); + break; + case SET_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 1); + break; + case OPTIMIZED_GAIN: + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 1); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH, 1); + break; + case NO_GAIN_CHANGE: + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + break; + } + } else { + ad9361_spi_writef(spi, REG_FAST_CONFIG_1, + GOTO_SET_GAIN_IF_EN_AGC_HIGH, 0); + ad9361_spi_writef(spi, REG_FAST_CONFIG_2_SETTLING_DELAY, + GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH, 0); + } + + reg = ilog2(ctrl->f_agc_power_measurement_duration_in_state5 / 16); + reg = clamp_t(uint32_t, reg, 0U, 15U); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LPF_GAIN, + POWER_MEAS_IN_STATE_5(~0), reg); + ad9361_spi_writef(spi, REG_RX1_MANUAL_LMT_FULL_GAIN, + POWER_MEAS_IN_STATE_5_MSB, reg >> 3); + + return ad9361_gc_update(phy); +} + +/** + * Set the Aux DAC. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @param val_mV The value. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_set(struct ad9361_rf_phy *phy, int32_t dac, + int32_t val_mV) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, tmp; + + dev_dbg(&phy->spi->dev, "%s DAC%"PRId32" = %"PRId32" mV", __func__, dac, + val_mV); + + /* Disable DAC if val == 0, Ignored in ENSM Auto Mode */ + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_MANUAL_BAR(dac), val_mV ? 0 : 1); + + if (val_mV < 306) + val_mV = 306; + + if (val_mV < 1888) { + val = ((val_mV - 306) * 1000) / 1469; /* Vref = 1V, Step = 2 */ + tmp = AUXDAC_1_VREF(0); + } else { + val = ((val_mV - 1761) * 1000) / 1512; /* Vref = 2.5V, Step = 2 */ + tmp = AUXDAC_1_VREF(3); + } + + val = clamp_t(uint32_t, val, 0, 1023); + + switch (dac) { + case 1: + ad9361_spi_write(spi, REG_AUXDAC_1_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_1_CONFIG, AUXDAC_1_WORD_LSB(val) | tmp); + phy->auxdac1_value = val_mV; + break; + case 2: + ad9361_spi_write(spi, REG_AUXDAC_2_WORD, val >> 2); + ad9361_spi_write(spi, REG_AUXDAC_2_CONFIG, AUXDAC_2_WORD_LSB(val) | tmp); + phy->auxdac2_value = val_mV; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Get the Aux DAC value. + * @param phy The AD9361 state structure. + * @param dac The DAC. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_auxdac_get(struct ad9361_rf_phy *phy, int32_t dac) +{ + + switch (dac) { + case 1: + return phy->auxdac1_value; + case 2: + return phy->auxdac2_value; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Setup the AuxDAC. + * @param phy The AD9361 state structure. + * @param ctrl Pointer to auxdac_control structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxdac_setup(struct ad9361_rf_phy *phy, + struct auxdac_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + uint8_t tmp; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_auxdac_set(phy, 1, ctrl->dac1_default_value); + ad9361_auxdac_set(phy, 2, ctrl->dac2_default_value); + + tmp = ~(AUXDAC_AUTO_TX_BAR(ctrl->dac2_in_tx_en << 1 | ctrl->dac1_in_tx_en) | + AUXDAC_AUTO_RX_BAR(ctrl->dac2_in_rx_en << 1 | ctrl->dac1_in_rx_en) | + AUXDAC_INIT_BAR(ctrl->dac2_in_alert_en << 1 | ctrl->dac1_in_alert_en)); + + ad9361_spi_writef(spi, REG_AUXDAC_ENABLE_CTRL, + AUXDAC_AUTO_TX_BAR(~0) | + AUXDAC_AUTO_RX_BAR(~0) | + AUXDAC_INIT_BAR(~0), + tmp); /* Auto Control */ + + ad9361_spi_writef(spi, REG_EXTERNAL_LNA_CTRL, + AUXDAC_MANUAL_SELECT, ctrl->auxdac_manual_mode_en); + ad9361_spi_write(spi, REG_AUXDAC1_RX_DELAY, ctrl->dac1_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC1_TX_DELAY, ctrl->dac1_tx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_RX_DELAY, ctrl->dac2_rx_delay_us); + ad9361_spi_write(spi, REG_AUXDAC2_TX_DELAY, ctrl->dac2_tx_delay_us); + + return 0; +} + +/** + * Setup the AuxADC. + * @param phy The AD9361 state structure. + * @param ctrl The AuxADC settings. + * @param bbpll_freq The BBPLL frequency [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_auxadc_setup(struct ad9361_rf_phy *phy, + struct auxadc_control *ctrl, + uint32_t bbpll_freq) +{ + struct spi_desc *spi = phy->spi; + uint32_t val; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + val = DIV_ROUND_CLOSEST(ctrl->temp_time_inteval_ms * + (bbpll_freq / 1000UL), (1 << 29)); + + ad9361_spi_write(spi, REG_TEMP_OFFSET, ctrl->offset); + ad9361_spi_write(spi, REG_START_TEMP_READING, 0x00); + ad9361_spi_write(spi, REG_TEMP_SENSE2, + MEASUREMENT_TIME_INTERVAL(val) | + (ctrl->periodic_temp_measuremnt ? + TEMP_SENSE_PERIODIC_ENABLE : 0)); + ad9361_spi_write(spi, REG_TEMP_SENSOR_CONFIG, + TEMP_SENSOR_DECIMATION( + ilog2(ctrl->temp_sensor_decimation) - 8)); + ad9361_spi_write(spi, REG_AUXADC_CLOCK_DIVIDER, + bbpll_freq / ctrl->auxadc_clock_rate); + ad9361_spi_write(spi, REG_AUXADC_CONFIG, + AUX_ADC_DECIMATION( + ilog2(ctrl->auxadc_decimation) - 8)); + + return 0; +} + +/** + * Get the measured temperature of the device. + * @param phy The AD9361 state structure. + * @return The measured temperature of the device. + */ +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy) +{ + uint32_t val; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + val = ad9361_spi_read(phy->spi, REG_TEMPERATURE); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return DIV_ROUND_CLOSEST(val * 1000000, 1140); +} + +/** + * Get the Aux ADC value. + * @param phy The AD9361 state structure. + * @return The value in case of success, negative error code otherwise. + */ +int32_t ad9361_get_auxadc(struct ad9361_rf_phy *phy) +{ + uint8_t buf[2]; + + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 1); + ad9361_spi_readm(phy->spi, REG_AUXADC_LSB, buf, 2); + ad9361_spi_writef(phy->spi, REG_AUXADC_CONFIG, AUXADC_POWER_DOWN, 0); + + return (buf[1] << 4) | AUXADC_WORD_LSB(buf[0]); +} + +/** + * Setup the Control Output pins. + * @param phy The AD9361 state structure. + * @param ctrl The Control Output pins settings. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_ctrl_outs_setup(struct ad9361_rf_phy *phy, + struct ctrl_outs_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_CTRL_OUTPUT_POINTER, ctrl->index); // Ctrl Out index + return ad9361_spi_write(spi, REG_CTRL_OUTPUT_ENABLE, + ctrl->en_mask); // Ctrl Out [7:0] output enable +} + +/** + * Setup the GPO pins. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_gpo_setup(struct ad9361_rf_phy *phy, + struct gpo_control *ctrl) +{ + struct spi_desc *spi = phy->spi; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + ad9361_spi_write(spi, REG_AUTO_GPO, + GPO_ENABLE_AUTO_RX(ctrl->gpo0_slave_rx_en | + (ctrl->gpo1_slave_rx_en << 1) | + (ctrl->gpo2_slave_rx_en << 2) | + (ctrl->gpo3_slave_rx_en << 3)) | + GPO_ENABLE_AUTO_TX(ctrl->gpo0_slave_tx_en | + (ctrl->gpo1_slave_tx_en << 1) | + (ctrl->gpo2_slave_tx_en << 2) | + (ctrl->gpo3_slave_tx_en << 3))); + + ad9361_spi_write(spi, REG_GPO_FORCE_AND_INIT, + GPO_MANUAL_CTRL(ctrl->gpo_manual_mode_enable_mask) | + GPO_INIT_STATE(ctrl->gpo0_inactive_state_high_en | + (ctrl->gpo1_inactive_state_high_en << 1) | + (ctrl->gpo2_inactive_state_high_en << 2) | + (ctrl->gpo3_inactive_state_high_en << 3))); + + ad9361_spi_write(spi, REG_GPO0_RX_DELAY, ctrl->gpo0_rx_delay_us); + ad9361_spi_write(spi, REG_GPO0_TX_DELAY, ctrl->gpo0_tx_delay_us); + ad9361_spi_write(spi, REG_GPO1_RX_DELAY, ctrl->gpo1_rx_delay_us); + ad9361_spi_write(spi, REG_GPO1_TX_DELAY, ctrl->gpo1_tx_delay_us); + ad9361_spi_write(spi, REG_GPO2_RX_DELAY, ctrl->gpo2_rx_delay_us); + ad9361_spi_write(spi, REG_GPO2_TX_DELAY, ctrl->gpo2_tx_delay_us); + ad9361_spi_write(spi, REG_GPO3_RX_DELAY, ctrl->gpo3_rx_delay_us); + ad9361_spi_write(spi, REG_GPO3_TX_DELAY, ctrl->gpo3_tx_delay_us); + + /* + * GPO manual mode conflicts with automatic ENSM slave and eLNA mode + */ + ad9361_spi_writef(phy->spi, REG_EXTERNAL_LNA_CTRL, GPO_MANUAL_SELECT, + ctrl->gpo_manual_mode_en); + + return 0; +} + +/** + * Setup the RSSI. + * @param phy The AD9361 state structure. + * @param ctrl The RSSI settings. + * @param is_update True if update + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_rssi_setup(struct ad9361_rf_phy *phy, + struct rssi_control *ctrl, + bool is_update) +{ + struct spi_desc *spi = phy->spi; + uint32_t total_weight, weight[4], total_dur = 0, temp; + uint8_t dur_buf[4] = { 0 }; + int32_t val, ret, i, j = 0; + uint32_t rssi_delay; + uint32_t rssi_wait; + int32_t rssi_duration; + uint32_t rate; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (ctrl->rssi_unit_is_rx_samples) { + if (is_update) + return 0; /* no update required */ + + rssi_delay = ctrl->rssi_delay; + rssi_wait = ctrl->rssi_wait; + rssi_duration = ctrl->rssi_duration; + } else { + /* update sample based on RX rate */ + rate = DIV_ROUND_CLOSEST( + clk_get_rate(phy, phy->ref_clk_scale[RX_SAMPL_CLK]), 1000); + /* units are in us */ + rssi_delay = DIV_ROUND_CLOSEST(ctrl->rssi_delay * rate, 1000); + rssi_wait = DIV_ROUND_CLOSEST(ctrl->rssi_wait * rate, 1000); + rssi_duration = DIV_ROUND_CLOSEST( + ctrl->rssi_duration * rate, 1000); + } + + if (ctrl->restart_mode == EN_AGC_PIN_IS_PULLED_HIGH) + rssi_delay = 0; + + rssi_delay = clamp(rssi_delay / 8, 0U, 255U); + rssi_wait = clamp(rssi_wait / 4, 0U, 255U); + + do { + for (i = 14; rssi_duration > 0 && i >= 0; i--) { + val = 1 << i; + if ((int64_t)rssi_duration >= val) { + dur_buf[j++] = i; + total_dur += val; + rssi_duration -= val; + break; + } + } + + } while (j < 4 && rssi_duration > 0); + + for (i = 0, total_weight = 0; i < 4; i++) { + if (i < j) + total_weight += weight[i] = + DIV_ROUND_CLOSEST(RSSI_MAX_WEIGHT * + (1 << dur_buf[i]), total_dur); + else + total_weight += weight[i] = 0; + } + + /* total of all weights must be 0xFF */ + val = total_weight - 0xFF; + weight[j - 1] -= val; + + ad9361_spi_write(spi, REG_MEASURE_DURATION_01, + (dur_buf[1] << 4) | dur_buf[0]); // RSSI Measurement Duration 0, 1 + ad9361_spi_write(spi, REG_MEASURE_DURATION_23, + (dur_buf[3] << 4) | dur_buf[2]); // RSSI Measurement Duration 2, 3 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_0, + weight[0]); // RSSI Weighted Multiplier 0 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_1, + weight[1]); // RSSI Weighted Multiplier 1 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_2, + weight[2]); // RSSI Weighted Multiplier 2 + ad9361_spi_write(spi, REG_RSSI_WEIGHT_3, + weight[3]); // RSSI Weighted Multiplier 3 + ad9361_spi_write(spi, REG_RSSI_DELAY, rssi_delay); // RSSI Delay + ad9361_spi_write(spi, REG_RSSI_WAIT_TIME, rssi_wait); // RSSI Wait + + temp = RSSI_MODE_SELECT(ctrl->restart_mode); + if (ctrl->restart_mode == SPI_WRITE_TO_REGISTER) + temp |= START_RSSI_MEAS; + + if (rssi_duration == 0 && j == 1) /* Power of two */ + temp |= DEFAULT_RSSI_MEAS_MODE; + + ret = ad9361_spi_write(spi, REG_RSSI_CONFIG, temp); // RSSI Mode Select + + if (ret < 0) + dev_err(&phy->spi->dev, "Unable to write rssi config"); + + return 0; +} + +/** + * This function needs to be called whenever BBPLL changes. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_bb_clk_change_handler(struct ad9361_rf_phy *phy) +{ + int32_t ret; + + ret = ad9361_gc_update(phy); + ret |= ad9361_rssi_setup(phy, &phy->pdata->rssi_ctrl, true); + ret |= ad9361_auxadc_setup(phy, &phy->pdata->auxadc_ctrl, + clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK])); + + return ret; +} + +/** + * Set the desired Enable State Machine (ENSM) state. + * @param phy The AD9361 state structure. + * @param ensm_state The ENSM state [ENSM_STATE_SLEEP_WAIT, ENSM_STATE_ALERT, + * ENSM_STATE_TX, ENSM_STATE_TX_FLUSH, ENSM_STATE_RX, + * ENSM_STATE_RX_FLUSH, ENSM_STATE_FDD, ENSM_STATE_FDD_FLUSH]. + * @param pinctrl Set true, will enable the ENSM pin control. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl) +{ + struct spi_desc *spi = phy->spi; + int32_t rc = 0; + uint32_t val; + uint32_t tmp; + + dev_dbg(dev, "Device is in %x state, moving to %x", phy->curr_ensm_state, + ensm_state); + + + if (phy->curr_ensm_state == ENSM_STATE_SLEEP) { + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + udelay(20); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, TO_ALERT | FORCE_ALERT_STATE); + ad9361_trx_vco_cal_control(phy, false, true); /* Enable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, true); + } + + val = (phy->pdata->ensm_pin_pulse_mode ? 0 : LEVEL_MODE) | + (pinctrl ? ENABLE_ENSM_PIN_CTRL : 0) | + (phy->txmon_tdd_en ? ENABLE_RX_DATA_PORT_FOR_CAL : 0) | + TO_ALERT; + + switch (ensm_state) { + case ENSM_STATE_TX: + val |= FORCE_TX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_RX: + val |= FORCE_RX_ON; + if (phy->pdata->fdd) + rc = -EINVAL; + else if (phy->curr_ensm_state != ENSM_STATE_ALERT) + rc = -EINVAL; + break; + case ENSM_STATE_FDD: + val |= FORCE_TX_ON; + if (!phy->pdata->fdd) + rc = -EINVAL; + break; + case ENSM_STATE_ALERT: + val &= ~(FORCE_TX_ON | FORCE_RX_ON); + val |= TO_ALERT | FORCE_ALERT_STATE; + break; + case ENSM_STATE_SLEEP_WAIT: + break; + case ENSM_STATE_SLEEP: + ad9361_trx_vco_cal_control(phy, false, false); /* Disable VCO Cal */ + ad9361_trx_vco_cal_control(phy, true, false); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Clear To Alert */ + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, + phy->pdata->fdd ? FORCE_TX_ON : FORCE_RX_ON); + /* Delay Flush Time 384 ADC clock cycles */ + udelay(384000000UL / clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, 0); /* Move to Wait*/ + udelay(1); /* Wait for ENSM settle */ + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + (phy->pdata->use_extclk ? XO_BYPASS : 0)); /* Turn off all clocks */ + phy->curr_ensm_state = ensm_state; + return 0; + + default: + dev_err(dev, "No handling for forcing %d ensm state", + ensm_state); + goto out; + } + + if (rc) { + if ((phy->curr_ensm_state != ENSM_STATE_ALERT) + && (val & (FORCE_RX_ON | FORCE_TX_ON))) { + uint32_t val2 = val; + + val2 &= ~(FORCE_TX_ON | FORCE_RX_ON); + val2 |= TO_ALERT | FORCE_ALERT_STATE; + ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val2); + + ad9361_check_cal_done(phy, REG_STATE, ENSM_STATE(~0), ENSM_STATE_ALERT); + } else { + dev_err(dev, "Invalid ENSM state transition in %s mode", + phy->pdata->fdd ? "FDD" : "TDD"); + goto out; + } + } + + if (!phy->pdata->fdd && !pinctrl && !phy->pdata->tdd_use_dual_synth && + (ensm_state == ENSM_STATE_TX || ensm_state == ENSM_STATE_RX)) { + uint32_t reg, check; + + if (ensm_state == ENSM_STATE_TX) { + reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[0] & + TX_SYNTH_VCO_POWER_DOWN); + } else { + reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + check = !(phy->cached_synth_pd[1] & + RX_SYNTH_VCO_POWER_DOWN); + } + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + TXNRX_SPI_CTRL, ensm_state == ENSM_STATE_TX); + + if (check) + ad9361_check_cal_done(phy, reg, VCO_LOCK, 1); + } + + rc = ad9361_spi_write(spi, REG_ENSM_CONFIG_1, val); + if (rc) + dev_err(dev, "Failed to restore state"); + + if ((val & FORCE_RX_ON) && + (phy->agc_mode[0] == RF_GAIN_MGC || + phy->agc_mode[1] == RF_GAIN_MGC)) { + tmp = ad9361_spi_read(spi, REG_SMALL_LMT_OVERLOAD_THRESH); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + (tmp & SMALL_LMT_OVERLOAD_THRESH(~0)) | + (phy->agc_mode[0] == RF_GAIN_MGC ? FORCE_PD_RESET_RX1 : 0) | + (phy->agc_mode[1] == RF_GAIN_MGC ? FORCE_PD_RESET_RX2 : 0)); + ad9361_spi_write(spi, REG_SMALL_LMT_OVERLOAD_THRESH, + tmp & SMALL_LMT_OVERLOAD_THRESH(~0)); + } + + phy->curr_ensm_state = ensm_state; + +out: + return rc; + +} + +/** + * Check if at least one of the clock rates is equal to the DATA_CLK (lvds) rate. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_validate_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks) +{ + static const uint32_t max_rx_rates[] = {MAX_BBPLL_FREQ, MAX_ADC_CLK, + MAX_RX_HB3, MAX_RX_HB2, MAX_RX_HB1, MAX_BASEBAND_RATE + }; + static const uint32_t max_tx_rates[] = {MAX_BBPLL_FREQ, MAX_DAC_CLK, + MAX_TX_HB3, MAX_TX_HB2, MAX_TX_HB1, MAX_BASEBAND_RATE + }; + uint32_t i; + uint32_t data_clk; + + data_clk = (phy->pdata->rx2tx2 ? 4 : 2) / + ((phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) ? 1 : 2) * + rx_path_clks[RX_SAMPL_FREQ]; + + /* CMOS Mode */ + if (!(phy->pdata->port_ctrl.pp_conf[2] & LVDS_MODE) && + (data_clk > MAX_BASEBAND_RATE)) { + dev_err(&phy->spi->dev, + "%s: Failed CMOS MODE DATA_CLK > 61.44MSPS", __func__); + return -EINVAL; + } + + /* Validate MAX PLL, ADC, DAC and HB filter rates */ + for (i = 0; i < ARRAY_SIZE(max_rx_rates); i++) { + if (rx_path_clks[i] > max_rx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed RX max rate check (%"PRIu32" > %"PRIu32")", + __func__, rx_path_clks[i], max_rx_rates[i]); + return -EINVAL; + } + + if (tx_path_clks[i] > max_tx_rates[i]) { + dev_err(&phy->spi->dev, + "%s: Failed TX max rate check (%"PRIu32" > %"PRIu32")", + __func__, tx_path_clks[i], max_tx_rates[i]); + return -EINVAL; + } + } + + /* Validate that DATA_CLK exist within the clock chain */ + for (i = 1; i <= 3; i++) { + if (diff_abs(rx_path_clks[ADC_FREQ] / i, data_clk) < 4) + return 0; + } + + for (i = 1; i <= 4; i++) { + if (diff_abs((rx_path_clks[R2_FREQ] >> i), data_clk) < 4) + return 0; + } + + dev_err(&phy->spi->dev, "%s: Failed - at least one of the clock rates" + " must be equal to the DATA_CLK (lvds) rate", __func__); + + return -EINVAL; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret, i, j, n; + + dev_dbg(&phy->spi->dev, "%s", __func__); + + if (!rx_path_clks || !tx_path_clks) + return -EINVAL; + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx_path_clks[BBPLL_FREQ], rx_path_clks[ADC_FREQ], + rx_path_clks[R2_FREQ], rx_path_clks[R1_FREQ], + rx_path_clks[CLKRF_FREQ], rx_path_clks[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s: %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx_path_clks[BBPLL_FREQ], tx_path_clks[ADC_FREQ], + tx_path_clks[R2_FREQ], tx_path_clks[R1_FREQ], + tx_path_clks[CLKRF_FREQ], tx_path_clks[RX_SAMPL_FREQ]); + + ret = ad9361_validate_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[BBPLL_CLK], + rx_path_clks[BBPLL_FREQ]); + if (ret < 0) + return ret; + + phy->current_rx_path_clks[BBPLL_FREQ] = rx_path_clks[BBPLL_FREQ]; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + ret = clk_set_rate(phy, phy->ref_clk_scale[i], rx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_rx_path_clks[n] = rx_path_clks[n]; + ret = clk_set_rate(phy, phy->ref_clk_scale[j], tx_path_clks[n]); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + phy->current_tx_path_clks[n] = tx_path_clks[n]; + } + + /* + * Workaround for clock framework since clocks don't change we + * manually need to enable the filter + */ + + if (phy->rx_fir_dec == 1 || phy->bypass_rx_fir) { + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), !phy->bypass_rx_fir); + } + + if (phy->tx_fir_int == 1 || phy->bypass_tx_fir) { + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), !phy->bypass_tx_fir); + } + + /* The FIR filter once enabled causes the interface timing to change. + * It's typically not a problem if the timing margin is big enough. + * However at 61.44 MSPS it causes problems on some systems. + * So we always run the digital tune in case the filter is enabled. + * If it is disabled we restore the values from the initial calibration. + */ + + if (!phy->pdata->dig_interface_tune_fir_disable && + !(phy->bypass_tx_fir && phy->bypass_rx_fir)) + ret = ad9361_dig_tune(phy, 0, SKIP_STORE_RESULT); + + return ad9361_bb_clk_change_handler(phy); +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t i, j, n; + uint32_t bbpll_freq; + + if (!rx_path_clks && !tx_path_clks) + return -EINVAL; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + + if (rx_path_clks) + rx_path_clks[BBPLL_FREQ] = bbpll_freq; + + if (tx_path_clks) + tx_path_clks[BBPLL_FREQ] = bbpll_freq; + + for (i = ADC_CLK, j = DAC_CLK, n = ADC_FREQ; + i <= RX_SAMPL_CLK; i++, j++, n++) { + if (rx_path_clks) + rx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[i]); + if (tx_path_clks) + tx_path_clks[n] = clk_get_rate(phy, phy->ref_clk_scale[j]); + } + + return 0; +} + +/** + * Calculate the RX and TX path rates to obtain the desired sample rate. + * @param phy The AD9361 state structure. + * @param tx_sample_rate The desired sample rate. + * @param rate_gov The rate governor option. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + uint32_t clktf, clkrf, adc_rate = 0, dac_rate = 0; + uint64_t bbpll_rate; + int32_t i, index_rx = -1, index_tx = -1, tmp; + uint32_t div, tx_intdec, rx_intdec, recursion = 1; + const int8_t clk_dividers[][4] = { + { 12, 3, 2, 2 }, + { 8, 2, 2, 2 }, + { 6, 3, 1, 2 }, + { 4, 2, 2, 1 }, + { 3, 3, 1, 1 }, + { 2, 2, 1, 1 }, + { 1, 1, 1, 1 }, + }; + + if (phy->bypass_rx_fir) + rx_intdec = 1; + else + rx_intdec = phy->rx_fir_dec; + + if (phy->bypass_tx_fir) + tx_intdec = 1; + else + tx_intdec = phy->tx_fir_int; + + if ((rate_gov == 1) && ((rx_intdec * tx_sample_rate * 8) < MIN_ADC_CLK)) { + recursion = 0; + rate_gov = 0; + } + + dev_dbg(&phy->spi->dev, + "%s: requested rate %"PRIu32" TXFIR int %"PRIu32" RXFIR dec %"PRIu32" mode %s", + __func__, tx_sample_rate, tx_intdec, rx_intdec, + rate_gov ? "Nominal" : "Highest OSR"); + + if (tx_sample_rate > MAX_BASEBAND_RATE) + return -EINVAL; + + clktf = tx_sample_rate * tx_intdec; + clkrf = tx_sample_rate * rx_intdec * (phy->rx_eq_2tx ? 2 : 1); + + for (i = rate_gov; i < 7; i++) { + adc_rate = clkrf * clk_dividers[i][0]; + dac_rate = clktf * clk_dividers[i][0]; + + if ((adc_rate <= MAX_ADC_CLK) && (adc_rate >= MIN_ADC_CLK)) { + + + if (dac_rate > adc_rate) + tmp = (dac_rate / adc_rate) * -1; + else + tmp = adc_rate / dac_rate; + + if (adc_rate <= MAX_DAC_CLK) { + index_rx = i; + index_tx = i - ((tmp == 1) ? 0 : tmp); + dac_rate = adc_rate; /* ADC_CLK */ + break; + } else { + dac_rate = adc_rate / 2; /* ADC_CLK/2 */ + index_rx = i; + + if (i == 4 && tmp >= 0) + index_tx = 7; /* STOP: 3/2 != 1 */ + else + index_tx = i + ((i == 5 && tmp >= 0) ? 1 : 2) - + ((tmp == 1) ? 0 : tmp); + + break; + } + } + } + + if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6) + && rate_gov < 7 && recursion) { + return ad9361_calculate_rf_clock_chain(phy, tx_sample_rate, + ++rate_gov, rx_path_clks, tx_path_clks); + } else if ((index_tx < 0 || index_tx > 6 || index_rx < 0 || index_rx > 6)) { + dev_err(&phy->spi->dev, "%s: Failed to find suitable dividers: %s", + __func__, (adc_rate < MIN_ADC_CLK) ? "ADC clock below limit" : + "BBPLL rate above limit"); + + return -EINVAL; + } + + /* Calculate target BBPLL rate */ + div = MAX_BBPLL_DIV; + + do { + bbpll_rate = (uint64_t)adc_rate * div; + div >>= 1; + + } while ((bbpll_rate > MAX_BBPLL_FREQ) && (div >= MIN_BBPLL_DIV)); + + rx_path_clks[BBPLL_FREQ] = bbpll_rate; + rx_path_clks[ADC_FREQ] = adc_rate; + rx_path_clks[R2_FREQ] = rx_path_clks[ADC_FREQ] / clk_dividers[index_rx][1]; + rx_path_clks[R1_FREQ] = rx_path_clks[R2_FREQ] / clk_dividers[index_rx][2]; + rx_path_clks[CLKRF_FREQ] = rx_path_clks[R1_FREQ] / clk_dividers[index_rx][3]; + rx_path_clks[RX_SAMPL_FREQ] = rx_path_clks[CLKRF_FREQ] / rx_intdec; + + tx_path_clks[BBPLL_FREQ] = bbpll_rate; + tx_path_clks[DAC_FREQ] = dac_rate; + tx_path_clks[T2_FREQ] = tx_path_clks[DAC_FREQ] / clk_dividers[index_tx][1]; + tx_path_clks[T1_FREQ] = tx_path_clks[T2_FREQ] / clk_dividers[index_tx][2]; + tx_path_clks[CLKTF_FREQ] = tx_path_clks[T1_FREQ] / clk_dividers[index_tx][3]; + tx_path_clks[TX_SAMPL_FREQ] = tx_path_clks[CLKTF_FREQ] / tx_intdec; + + return 0; +} + +/** + * Set the desired sample rate. + * @param phy The AD9361 state structure. + * @param freq The desired sample rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq) +{ + uint32_t rx[6], tx[6]; + int32_t ret; + + ret = ad9361_calculate_rf_clock_chain(phy, freq, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + return ad9361_set_trx_clock_chain(phy, rx, tx); +} + +/** + * Internal ENSM mode options helper function. + * @param phy The AD9361 state structure. + * @param fdd + * @param pinctrl + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl) +{ + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t val = 0; + + ad9361_spi_write(phy->spi, REG_ENSM_MODE, fdd ? FDD_MODE : 0); + + val = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_2); + val &= POWER_DOWN_RX_SYNTH | POWER_DOWN_TX_SYNTH | + RX_SYNTH_READY_MASK | TX_SYNTH_READY_MASK; + + if (fdd) + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, + val | DUAL_SYNTH_MODE | + (pd->fdd_independent_mode ? FDD_EXTERNAL_CTRL_ENABLE : 0)); + else + ret = ad9361_spi_write(phy->spi, REG_ENSM_CONFIG_2, val | + (pd->tdd_use_dual_synth ? DUAL_SYNTH_MODE : 0) | + (pd->tdd_use_dual_synth ? 0 : + (pinctrl ? SYNTH_ENABLE_PIN_CTRL_MODE : 0))); + + return ret; +} + +/** + * Fastlock read value. + * @param spi + * @param tx + * @param profile + * @param word + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_readval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word) +{ + uint32_t offs = 0; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + + return ad9361_spi_read(spi, REG_RX_FAST_LOCK_PROGRAM_READ + offs); +} + +/** + * Fastlock write value. + * @param spi + * @param tx + * @param profile + * @param word + * @param val + * @param last + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_writeval(struct spi_desc *spi, bool tx, + uint32_t profile, uint32_t word, uint8_t val, bool last) +{ + uint32_t offs = 0; + int32_t ret; + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + ret = ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_ADDR + offs, + RX_FAST_LOCK_PROFILE_ADDR(profile) | + RX_FAST_LOCK_PROFILE_WORD(word)); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, val); + ret |= ad9361_spi_write(spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | + RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + + if (last) /* Stop Clocks */ + ret |= ad9361_spi_write(spi, + REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + return ret; +} + +/** + * Fastlock load values. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + uint32_t offs = 0; + int32_t i, ret = 0; + uint8_t buf[4]; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + buf[0] = values[0]; + buf[1] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(0); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_DATA + offs, buf, 2); + + for (i = 1; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) { + buf[0] = RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE; + buf[1] = 0; + buf[2] = values[i]; + buf[3] = RX_FAST_LOCK_PROFILE_ADDR(profile) | RX_FAST_LOCK_PROFILE_WORD(i); + ad9361_spi_writem(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, buf, 4); + } + + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + RX_FAST_LOCK_PROGRAM_WRITE | RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, 0); + + phy->fastlock.entry[tx][profile].flags = FASTLOOK_INIT; + phy->fastlock.entry[tx][profile].alc_orig = values[15]; + phy->fastlock.entry[tx][profile].alc_written = values[15]; + + return ret; +} + +/** + * Fastlock store. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + struct spi_desc *spi = phy->spi; + uint8_t val[16]; + uint32_t offs = 0, x, y; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + val[0] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_0 + offs); + val[1] = ad9361_spi_read(spi, REG_RX_INTEGER_BYTE_1 + offs); + val[2] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_0 + offs); + val[3] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_1 + offs); + val[4] = ad9361_spi_read(spi, REG_RX_FRACT_BYTE_2 + offs); + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_REF(~0)); + y = ad9361_spi_readf(spi, REG_RX_ALC_VARACTOR + offs, VCO_VARACTOR(~0)); + val[5] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_VCO_BIAS_1 + offs, VCO_BIAS_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RX_CP_CURRENT + offs, CHARGE_PUMP_CURRENT(~0)); + /* Wide BW option: N = 1 + * Set init and steady state values to the same - let user space handle it + */ + val[6] = (x << 3) | y; + val[7] = y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_3 + offs, LOOP_FILTER_R3(~0)); + val[8] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_C3(~0)); + val[9] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C1(~0)); + y = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_1 + offs, LOOP_FILTER_C2(~0)); + val[10] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_LOOP_FILTER_2 + offs, LOOP_FILTER_R1(~0)); + val[11] = (x << 4) | x; + + x = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_0 + offs, + VCO_VARACTOR_REFERENCE_TCF(~0)); + y = ad9361_spi_readf(spi, REG_RFPLL_DIVIDERS, + tx ? TX_VCO_DIVIDER(~0) : RX_VCO_DIVIDER(~0)); + val[12] = (x << 4) | y; + + x = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, VCO_CAL_OFFSET(~0)); + y = ad9361_spi_readf(spi, REG_RX_VCO_VARACTOR_CTRL_1 + offs, + VCO_VARACTOR_REFERENCE(~0)); + val[13] = (x << 4) | y; + + val[14] = ad9361_spi_read(spi, REG_RX_FORCE_VCO_TUNE_0 + offs); + + x = ad9361_spi_readf(spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_WORD(~0)); + y = ad9361_spi_readf(spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE); + val[15] = (x << 1) | y; + + return ad9361_fastlock_load(phy, tx, profile, val); +} + +/** + * Fastlock prepare. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param prepare + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_fastlock_prepare(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, bool prepare) +{ + uint32_t offs, ready_mask; + bool is_prepared; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32": %s", + __func__, tx ? "TX" : "RX", profile, + prepare ? "Prepare" : "Un-Prepare"); + + if (tx) { + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + ready_mask = TX_SYNTH_READY_MASK; + } else { + offs = 0; + ready_mask = RX_SYNTH_READY_MASK; + } + + is_prepared = !!phy->fastlock.current_profile[tx]; + + if (prepare && !is_prepared) { + ad9361_spi_write(phy->spi, + REG_RX_FAST_LOCK_SETUP_INIT_DELAY + offs, + (tx ? phy->pdata->tx_fastlock_delay_ns : + phy->pdata->rx_fastlock_delay_ns) / 250); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + RX_FAST_LOCK_MODE_ENABLE); + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_PROGRAM_CTRL + offs, + 0); + + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 1); + ad9361_trx_vco_cal_control(phy, tx, false); + } else if (!prepare && is_prepared) { + ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, 0); + + /* Workaround: Exiting Fastlock Mode */ + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 1); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_ALC + offs, FORCE_ALC_ENABLE, 0); + ad9361_spi_writef(phy->spi, REG_RX_FORCE_VCO_TUNE_1 + offs, FORCE_VCO_TUNE, 0); + + ad9361_trx_vco_cal_control(phy, tx, true); + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, ready_mask, 0); + + phy->fastlock.current_profile[tx] = 0; + } + + return 0; +} + +/** + * Fastlock recall. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile) +{ + uint32_t offs = 0; + uint8_t curr, _new, orig, current_profile; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + if (tx) + offs = REG_TX_FAST_LOCK_SETUP - REG_RX_FAST_LOCK_SETUP; + + if (phy->fastlock.entry[tx][profile].flags != FASTLOOK_INIT) + return -EINVAL; + + /* Workaround: Lock problem with same ALC word */ + + current_profile = phy->fastlock.current_profile[tx]; + _new = phy->fastlock.entry[tx][profile].alc_written; + + if (current_profile == 0) + curr = ad9361_spi_readf(phy->spi, REG_RX_FORCE_ALC + offs, + FORCE_ALC_WORD(~0)) << 1; + else + curr = phy->fastlock.entry[tx][current_profile - 1].alc_written; + + if ((curr >> 1) == (_new >> 1)) { + orig = phy->fastlock.entry[tx][profile].alc_orig; + + if ((orig >> 1) == (_new >> 1)) + phy->fastlock.entry[tx][profile].alc_written += 2; + else + phy->fastlock.entry[tx][profile].alc_written = orig; + + ad9361_fastlock_writeval(phy->spi, tx, profile, 0xF, + phy->fastlock.entry[tx][profile].alc_written, true); + } + + ad9361_fastlock_prepare(phy, tx, profile, true); + phy->fastlock.current_profile[tx] = profile + 1; + + return ad9361_spi_write(phy->spi, REG_RX_FAST_LOCK_SETUP + offs, + RX_FAST_LOCK_PROFILE(profile) | + (phy->pdata->trx_fastlock_pinctrl_en[tx] ? + RX_FAST_LOCK_PROFILE_PIN_SELECT : 0) | + RX_FAST_LOCK_MODE_ENABLE); +} + +/** + * Fastlock save. + * @param phy The AD9361 state structure. + * @param tx + * @param profile + * @param values + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values) +{ + int32_t i; + + dev_dbg(&phy->spi->dev, "%s: %s Profile %"PRIu32":", + __func__, tx ? "TX" : "RX", profile); + + for (i = 0; i < RX_FAST_LOCK_CONFIG_WORD_NUM; i++) + values[i] = ad9361_fastlock_readval(phy->spi, tx, profile, i); + + return 0; +} + +/** + * Multi Chip Sync (MCS) config. + * @param phy The AD9361 state structure. + * @param step MCS step. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step) +{ + int32_t mcs_mask = MCS_RF_ENABLE | MCS_BBPLL_ENABLE | + MCS_DIGITAL_CLK_ENABLE | MCS_BB_ENABLE; + + dev_dbg(&phy->spi->dev, "%s: MCS step %"PRId32, __func__, step); + + switch (step) { + case 1: + /* REVIST: + * POWER_DOWN_TRX_SYNTH and MCS_RF_ENABLE somehow conflict + */ + ad9361_spi_writef(phy->spi, REG_ENSM_CONFIG_2, + POWER_DOWN_TX_SYNTH | POWER_DOWN_RX_SYNTH, 0); + + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_BBPLL_ENABLE | MCS_RF_ENABLE); + ad9361_spi_writef(phy->spi, REG_CP_BLEED_CURRENT, + MCS_REFCLK_SCALE_EN, 1); + break; + case 2: + if(!phy->gpio_desc_sync) + break; + /* + * NOTE: This is not a regular GPIO - + * HDL ensures Multi-chip Synchronization SYNC_IN Pulse Timing + * relative to rising and falling edge of REF_CLK + */ + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 3: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_BB_ENABLE | MCS_DIGITAL_CLK_ENABLE | MCS_RF_ENABLE); + break; + case 4: + if(!phy->gpio_desc_sync) + break; + gpio_set_value(phy->gpio_desc_sync, 1); + gpio_set_value(phy->gpio_desc_sync, 0); + break; + case 5: + ad9361_spi_writef(phy->spi, REG_MULTICHIP_SYNC_AND_TX_MON_CTRL, + mcs_mask, MCS_RF_ENABLE); + break; + } + + return 0; +} + +/** + * Clear state. + * @param phy The AD9361 state structure. + * @return None. + */ +void ad9361_clear_state(struct ad9361_rf_phy *phy) +{ + phy->current_table = NO_GAIN_TABLE; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + phy->prev_ensm_state = 0; + phy->curr_ensm_state = 0; + phy->auto_cal_en = false; + phy->manual_tx_quad_cal_en = false; + phy->last_tx_quad_cal_freq = 0; + phy->flags = 0; + phy->current_rx_bw_Hz = 0; + phy->current_tx_bw_Hz = 0; + phy->rxbbf_div = 0; + phy->tx_fir_int = 0; + phy->tx_fir_ntaps = 0; + phy->rx_fir_dec = 0; + phy->rx_fir_ntaps = 0; + phy->ensm_pin_ctl_en = false; + phy->txmon_tdd_en = 0; + phy->current_tx_lo_freq = 0; + phy->current_rx_lo_freq = 0; + phy->current_tx_use_tdd_table = false; + phy->current_rx_use_tdd_table = false; + phy->cached_synth_pd[0] = 0; + phy->cached_synth_pd[1] = 0; + + memset(&phy->fastlock, 0, sizeof(phy->fastlock)); +} + +/** + * Determine the reference frequency value. + * @param refin_Hz Maximum allowed frequency. + * @param max Reference in frequency value. + * @return Reference frequency value. + */ +static uint32_t ad9361_ref_div_sel(uint32_t refin_Hz, uint32_t max) +{ + if (refin_Hz <= (max / 2)) + return 2 * refin_Hz; + else if (refin_Hz <= max) + return refin_Hz; + else if (refin_Hz <= (max * 2)) + return refin_Hz / 2; + else if (refin_Hz <= (max * 4)) + return refin_Hz / 4; + else + return 0; +} + +/** + * Setup the AD9361 device. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_setup(struct ad9361_rf_phy *phy) +{ + uint32_t refin_Hz, ref_freq, bbpll_freq; + struct spi_desc *spi = phy->spi; + struct ad9361_phy_platform_data *pd = phy->pdata; + int32_t ret; + uint32_t real_rx_bandwidth, real_tx_bandwidth; + bool tmp_use_ext_rx_lo = pd->use_ext_rx_lo; + bool tmp_use_ext_tx_lo = pd->use_ext_tx_lo; + + dev_dbg(dev, "%s", __func__); + + pd->rf_rx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_rx_bandwidth_Hz); + pd->rf_tx_bandwidth_Hz = ad9361_validate_rf_bw(phy, pd->rf_tx_bandwidth_Hz); + + real_rx_bandwidth = pd->rf_rx_bandwidth_Hz / 2; + real_tx_bandwidth = pd->rf_tx_bandwidth_Hz / 2; + + if (pd->fdd) { + pd->tdd_skip_vco_cal = false; + if (pd->ensm_pin_ctrl && pd->fdd_independent_mode) { + dev_warn(dev, + "%s: Either set ENSM PINCTRL or FDD Independent Mode", + __func__); + pd->ensm_pin_ctrl = false; + } + } + + ret = ad9361_auxdac_setup(phy, &pd->auxdac_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_gpo_setup(phy, &pd->gpo_ctrl); + if (ret < 0) + return ret; + + if (pd->port_ctrl.pp_conf[2] & FDD_RX_RATE_2TX_RATE) + phy->rx_eq_2tx = true; + + ad9361_spi_write(spi, REG_CTRL, CTRL_ENABLE); + ad9361_spi_write(spi, REG_BANDGAP_CONFIG0, + MASTER_BIAS_TRIM(0x0E)); /* Enable Master Bias */ + ad9361_spi_write(spi, REG_BANDGAP_CONFIG1, + BANDGAP_TEMP_TRIM(0x0E)); /* Set Bandgap Trim */ + + ad9361_set_dcxo_tune(phy, pd->dcxo_coarse, pd->dcxo_fine); + + refin_Hz = phy->clk_refin->rate; + + ref_freq = ad9361_ref_div_sel(refin_Hz, MAX_BBPLL_FREF); + if (!ref_freq) + return -EINVAL; + + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, RX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, TX_REF_RESET_BAR, 1); + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DOUBLER_FB_DELAY(~0), 3); /* FB DELAY */ + + ad9361_spi_write(spi, REG_CLOCK_ENABLE, + DIGITAL_POWER_UP | CLOCK_ENABLE_DFLT | BBPLL_ENABLE | + (pd->use_extclk ? XO_BYPASS : 0)); /* Enable Clocks */ + + ret = clk_set_rate(phy, phy->ref_clk_scale[BB_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[BB_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable BB ref clock rate (%"PRId32")", + ret); + return ret; + } + + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, 0x12); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, 0x34); + + ret = ad9361_set_trx_clock_chain(phy, pd->rx_path_clks, + pd->tx_path_clks); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + pd->rx1tx1_mode_use_tx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_tx_num, TX_1, TX_2); + pd->rx1tx1_mode_use_rx_num = + clamp_t(uint32_t, pd->rx1tx1_mode_use_rx_num, RX_1, RX_2); + + ad9361_en_dis_tx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_tx_num); + ad9361_en_dis_rx(phy, TX_1 | TX_2, pd->rx1tx1_mode_use_rx_num); + } else { + ad9361_en_dis_tx(phy, TX_1 | TX_2, TX_1 | TX_2); + ad9361_en_dis_rx(phy, RX_1 | RX_2, RX_1 | RX_2); + } + + ret = ad9361_rf_port_setup(phy, true, pd->rf_rx_input_sel, + pd->rf_tx_output_sel); + if (ret < 0) + return ret; + + ret = ad9361_pp_port_setup(phy, false); + if (ret < 0) + return ret; + + bbpll_freq = clk_get_rate(phy, phy->ref_clk_scale[BBPLL_CLK]); + ret = ad9361_auxadc_setup(phy, &pd->auxadc_ctrl, bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_ctrl_outs_setup(phy, &pd->ctrl_outs_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_set_ref_clk_cycles(phy, refin_Hz); + if (ret < 0) + return ret; + + ret = ad9361_setup_ext_lna(phy, &pd->elna_ctrl); + if (ret < 0) + return ret; + + /* + * This allows forcing a lower F_REF window + * (worse phase noise, better fractional spurs) + */ + pd->trx_synth_max_fref = clamp_t(uint32_t, pd->trx_synth_max_fref, + MIN_SYNTH_FREF, MAX_SYNTH_FREF); + + ref_freq = ad9361_ref_div_sel(refin_Hz, pd->trx_synth_max_fref); + if (!ref_freq) + return -EINVAL; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_REFCLK], ref_freq); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth ref clock rate (%"PRId32")", ret); + return ret; + } + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, false); /* RXCP */ + if (ret < 0) + return ret; + + ret = ad9361_txrx_synth_cp_calib(phy, ref_freq, true); /* TXCP */ + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = 0; + phy->pdata->use_ext_tx_lo = 0; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(pd->rx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set RX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable RX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[RX_RFPLL]); + if (ret < 0) + return ret; + + /* Skip quad cal here we do it later again */ + phy->last_tx_quad_cal_freq = pd->tx_synth_freq; + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(pd->tx_synth_freq)); + if (ret < 0) { + dev_err(dev, "Failed to set TX Synth rate (%"PRId32")", + ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_REFCLK]); + if (ret < 0) { + dev_err(dev, "Failed to enable TX Synth ref clock (%"PRId32")", ret); + return ret; + } + + ret = clk_prepare_enable(phy->clks[TX_RFPLL]); + if (ret < 0) + return ret; + + phy->pdata->use_ext_rx_lo = tmp_use_ext_rx_lo; + phy->pdata->use_ext_tx_lo = tmp_use_ext_tx_lo; + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], + pd->use_ext_rx_lo); + + ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], + pd->use_ext_tx_lo); + + ret = ad9361_load_mixer_gm_subtable(phy); + if (ret < 0) + return ret; + + ret = ad9361_gc_setup(phy, &pd->gain_ctrl); + if (ret < 0) + return ret; + + ret = ad9361_rx_bb_analog_filter_calib(phy, + real_rx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_analog_filter_calib(phy, + real_tx_bandwidth, + bbpll_freq); + if (ret < 0) + return ret; + + ret = ad9361_rx_tia_calib(phy, real_rx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_tx_bb_second_filter_calib(phy, real_tx_bandwidth); + if (ret < 0) + return ret; + + ret = ad9361_rx_adc_setup(phy, + bbpll_freq, + clk_get_rate(phy, phy->ref_clk_scale[ADC_CLK])); + if (ret < 0) + return ret; + + ret = ad9361_bb_dc_offset_calib(phy); + if (ret < 0) + return ret; + + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = pd->rf_rx_bandwidth_Hz; + phy->current_tx_bw_Hz = pd->rf_tx_bandwidth_Hz; + phy->last_tx_quad_cal_phase = ~0; + ret = ad9361_tx_quad_calib(phy, real_rx_bandwidth, real_tx_bandwidth, -1); + if (ret < 0) + return ret; + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_pp_port_setup(phy, true); + + ret = ad9361_set_ensm_mode(phy, pd->fdd, pd->ensm_pin_ctrl); + if (ret < 0) + return ret; + + ad9361_spi_writef(phy->spi, REG_TX_ATTEN_OFFSET, + MASK_CLR_ATTEN_UPDATE, 0); + + ret = ad9361_set_tx_atten(phy, pd->tx_atten, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 1, + pd->rx2tx2 ? true : pd->rx1tx1_mode_use_tx_num == 2, true); + if (ret < 0) + return ret; + + if (!pd->rx2tx2) { + ret = ad9361_set_tx_atten(phy, 89750, + pd->rx1tx1_mode_use_tx_num == 2, + pd->rx1tx1_mode_use_tx_num == 1, true); + if (ret < 0) + return ret; + } + + ret = ad9361_rssi_setup(phy, &pd->rssi_ctrl, false); + if (ret < 0) + return ret; + + ret = ad9361_clkout_control(phy, pd->ad9361_clkout_mode); + if (ret < 0) + return ret; + + ret = ad9361_txmon_setup(phy, &pd->txmon_ctrl); + if (ret < 0) + return ret; + + phy->curr_ensm_state = ad9361_spi_readf(spi, REG_STATE, ENSM_STATE(~0)); + ad9361_ensm_set_state(phy, pd->fdd ? ENSM_STATE_FDD : ENSM_STATE_RX, + pd->ensm_pin_ctrl); + + phy->auto_cal_en = true; + phy->cal_threshold_freq = 100000000ULL; /* 100 MHz */ + + return 0; + +} + +/** + * Perform the selected calibration + * @param phy The AD9361 state structure. + * @param cal The selected calibration. + * @param arg The argument of the calibration. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg) +{ + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: CAL %"PRIu32" ARG %"PRId32, __func__, cal, arg); + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + switch (cal) { + case TX_QUAD_CAL: + ret = ad9361_tx_quad_calib(phy, phy->current_rx_bw_Hz / 2, + phy->current_tx_bw_Hz / 2, arg); + break; + case RFDC_CAL: + ret = ad9361_rf_dc_offset_calib(phy, + ad9361_from_clk(clk_get_rate(phy, phy->ref_clk_scale[RX_RFPLL]))); + break; + default: + ret = -EINVAL; + break; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Set the RF bandwidth. + * @param phy The AD9361 state structure. + * @param rf_rx_bw The desired RX bandwidth [Hz]. + * @param rf_tx_bw The desired TX bandwidth [Hz]. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw) +{ + int32_t ret; + + ret = ad9361_tracking_control(phy, false, false, false); + if (ret < 0) + return ret; + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = __ad9361_update_rf_bandwidth(phy, rf_rx_bw, rf_tx_bw); + if (ret < 0) + return ret; + + phy->current_rx_bw_Hz = rf_rx_bw; + phy->current_tx_bw_Hz = rf_tx_bw; + + if (phy->manual_tx_quad_cal_en == false) { + ret = ad9361_tx_quad_calib(phy, rf_rx_bw / 2, rf_tx_bw / 2, -1); + if (ret < 0) + return ret; + } + + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + if (ret < 0) + return ret; + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} + +/** + * Verify the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_verify_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, + uint32_t ntaps, short *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, gain = 0, conf, sel, cnt; + int32_t ret = 0; + +#ifndef DEBUG + return 0; +#endif + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", dest %d", + __func__, ntaps, dest); + + if (dest & FIR_IS_RX) { + gain = ad9361_spi_read(spi, REG_RX_FILTER_GAIN); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, 0); + } + + conf = ad9361_spi_read(spi, REG_TX_FILTER_CONF + offs); + + if ((dest & 3) == 3) { + sel = 1; + cnt = 2; + } else { + sel = (dest & 3); + cnt = 1; + } + + for (; cnt > 0; cnt--, sel++) { + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + FIR_NUM_TAPS(ntaps / 16 - 1) | + FIR_SELECT(sel) | FIR_START_CLK); + for (val = 0; val < ntaps; val++) { + short tmp; + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + + tmp = (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_1 + offs) & 0xFF) | + (ad9361_spi_read(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs) << 8); + + if (tmp != coef[val]) { + dev_err(&phy->spi->dev,"%s%"PRIu32" read verify failed TAP%"PRIu32" %d =! %d", + (dest & FIR_IS_RX) ? "RX" : "TX", sel, + val, tmp, coef[val]); + ret = -EIO; + } + } + } + + if (dest & FIR_IS_RX) { + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, gain); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, conf); + + return ret; +} + +/** + * Load the FIR filter coefficients. + * @param phy The AD9361 state structure. + * @param dest Destination identifier (RX1,2 / TX1,2). + * @param gain_dB Gain option. + * @param ntaps Number of filter Taps. + * @param coef Pointer to filter coefficients. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, int16_t *coef) +{ + struct spi_desc *spi = phy->spi; + uint32_t val, offs = 0, fir_conf = 0, fir_enable = 0; + int32_t ret; + + dev_dbg(&phy->spi->dev, "%s: TAPS %"PRIu32", gain %"PRId32", dest %d", + __func__, ntaps, gain_dB, dest); + + if (coef == NULL || !ntaps || ntaps > 128 || ntaps % 16) { + dev_err(&phy->spi->dev, + "%s: Invalid parameters: TAPS %"PRIu32", gain %"PRId32", dest 0x%X", + __func__, ntaps, gain_dB, dest); + + return -EINVAL; + } + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + if (dest & FIR_IS_RX) { + val = 3 - (gain_dB + 12) / 6; + ad9361_spi_write(spi, REG_RX_FILTER_GAIN, val & 0x3); + offs = REG_RX_FILTER_COEF_ADDR - REG_TX_FILTER_COEF_ADDR; + phy->rx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_RX_ENABLE_FILTER_CTRL, RX_FIR_ENABLE_DECIMATION(~0)); + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), + (phy->rx_fir_dec == 4) ? 3 : phy->rx_fir_dec); + } else { + if (gain_dB == -6) + fir_conf = TX_FIR_GAIN_6DB; + phy->tx_fir_ntaps = ntaps; + fir_enable = ad9361_spi_readf(phy->spi, + REG_TX_ENABLE_FILTER_CTRL, TX_FIR_ENABLE_INTERPOLATION(~0)); + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), + (phy->tx_fir_int == 4) ? 3 : phy->tx_fir_int); + } + + val = ntaps / 16 - 1; + + fir_conf |= FIR_NUM_TAPS(val) | FIR_SELECT(dest) | FIR_START_CLK; + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + for (val = 0; val < ntaps; val++) { + ad9361_spi_write(spi, REG_TX_FILTER_COEF_ADDR + offs, val); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_1 + offs, + coef[val] & 0xFF); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_WRITE_DATA_2 + offs, + coef[val] >> 8); + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, + fir_conf | FIR_WRITE); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + ad9361_spi_write(spi, REG_TX_FILTER_COEF_READ_DATA_2 + offs, 0); + } + + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(spi, REG_TX_FILTER_CONF + offs, fir_conf); + + ret = ad9361_verify_fir_filter_coef(phy, dest, ntaps, coef); + + if (dest & FIR_IS_RX) + ad9361_spi_writef(phy->spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), fir_enable); + else + ad9361_spi_writef(phy->spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), fir_enable); + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Parse the FIR filter file/buffer. + * @param phy The AD9361 state structure. + * @param data Pointer to buffer. + * @param size Buffer size. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_parse_fir(struct ad9361_rf_phy *phy, + char *data, uint32_t size) +{ + char *line; + int32_t i = 0, ret, txc, rxc; + int32_t tx = -1, tx_gain = 0, tx_int = 0; + int32_t rx = -1, rx_gain = 0, rx_dec = 0; + int32_t rtx = -1, rrx = -1; + int16_t coef_tx[128]; + int16_t coef_rx[128]; + char *ptr = data; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + while ((line = strsep(&ptr, "\n"))) { + if (line >= data + size) { + break; + } + + if (line[0] == '#') + continue; + + if (tx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "TX %d GAIN %d INT %d", + &tx, &tx_gain, &tx_int); +#else + ret = sscanf(line, "TX %"PRId32" GAIN %"PRId32" INT %"PRId32, + &tx, &tx_gain, &tx_int); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + if (rx < 0) { +#ifdef WIN32 + ret = sscanf_s(line, "RX %d GAIN %d DEC %d", + &rx, &rx_gain, &rx_dec); +#else + ret = sscanf(line, "RX %"PRId32" GAIN %"PRId32" DEC %"PRId32, + &rx, &rx_gain, &rx_dec); +#endif + if (ret == 3) + continue; + else + tx = -1; + } + + if (rtx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RTX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RTX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_tx_path_clks[0], + &phy->filt_tx_path_clks[1], + &phy->filt_tx_path_clks[2], + &phy->filt_tx_path_clks[3], + &phy->filt_tx_path_clks[4], + &phy->filt_tx_path_clks[5]); + if (ret == 6) { + rtx = 0; + continue; + } else { + rtx = -1; + } + } + + if (rrx < 0) { +#ifdef WIN32 + ret = sscanf(line, "RRX %lu %lu %lu %lu %lu %lu", +#else + ret = sscanf(line, + "RRX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, +#endif + &phy->filt_rx_path_clks[0], + &phy->filt_rx_path_clks[1], + &phy->filt_rx_path_clks[2], + &phy->filt_rx_path_clks[3], + &phy->filt_rx_path_clks[4], + &phy->filt_rx_path_clks[5]); + if (ret == 6) { + rrx = 0; + continue; + } else { + rrx = -1; + } + } + + if (!phy->filt_rx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWRX %d", &phy->filt_rx_bw_Hz); +#else + ret = sscanf(line, "BWRX %"PRId32, &phy->filt_rx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_rx_bw_Hz = 0; + } + + if (!phy->filt_tx_bw_Hz) { +#ifdef WIN32 + ret = sscanf(line, "BWTX %d", &phy->filt_tx_bw_Hz); +#else + ret = sscanf(line, "BWTX %"PRId32, &phy->filt_tx_bw_Hz); +#endif + if (ret == 1) + continue; + else + phy->filt_tx_bw_Hz = 0; + } + +#ifdef WIN32 + ret = sscanf_s(line, "%d,%d", &txc, &rxc); +#else + ret = sscanf(line, "%"PRId32",%"PRId32, &txc, &rxc); +#endif + if (ret == 1) { + coef_tx[i] = coef_rx[i] = (int16_t)txc; + i++; + continue; + } else if (ret == 2) { + coef_tx[i] = (int16_t)txc; + coef_rx[i] = (int16_t)rxc; + i++; + continue; + } + } + + switch (tx) { + case FIR_TX1: + case FIR_TX2: + case FIR_TX1_TX2: + phy->tx_fir_int = tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)tx, tx_gain, i, coef_tx); + break; + default: + ret = -EINVAL; + } + + switch (rx | FIR_IS_RX) { + case FIR_RX1: + case FIR_RX2: + case FIR_RX1_RX2: + phy->rx_fir_dec = rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(rx | FIR_IS_RX), + rx_gain, i, coef_rx); + break; + default: + ret = -EINVAL; + } + + if (ret < 0) + return ret; + + if (!(rrx | rtx)) + phy->filt_valid = true; + + return size; +} + +/** + * Validate FIR filter configuration - on pass enable. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + uint32_t max, min, valid; + + dev_dbg(dev, "%s: TX FIR EN=%d/TAPS%d/INT%d, RX FIR EN=%d/TAPS%d/DEC%d", + __func__, !phy->bypass_tx_fir, phy->tx_fir_ntaps, phy->tx_fir_int, + !phy->bypass_rx_fir, phy->rx_fir_ntaps, phy->rx_fir_dec); + + if (!phy->bypass_tx_fir) { + if (!(phy->tx_fir_int == 1 || phy->tx_fir_int == 2 || + phy->tx_fir_int == 4)) { + dev_err(dev, + "%s: Invalid: Interpolation %d in filter config", + __func__, phy->tx_fir_int); + return -EINVAL; + } + + + if (phy->tx_fir_int == 1 && phy->tx_fir_ntaps > 64) { + dev_err(dev, + "%s: Invalid: TAPS > 64 and Interpolation = 1", + __func__); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + if (!(phy->rx_fir_dec == 1 || phy->rx_fir_dec == 2 || + phy->rx_fir_dec == 4)) { + dev_err(dev, + "%s: Invalid: Decimation %d in filter config", + __func__, phy->rx_fir_dec); + + return -EINVAL; + } + } + + if (!phy->filt_valid || phy->bypass_rx_fir || phy->bypass_tx_fir) { + ret = ad9361_calculate_rf_clock_chain(phy, + clk_get_rate(phy, phy->ref_clk_scale[TX_SAMPL_CLK]), + phy->rate_governor, rx, tx); + if (ret < 0) { + min = phy->rate_governor ? 1500000U : 1000000U; + dev_err(dev, + "%s: Calculating filter rates failed %"PRId32 + " using min frequency",__func__, ret); + ret = ad9361_calculate_rf_clock_chain(phy, min, + phy->rate_governor, rx, tx); + if (ret < 0) { + return ret; + } + } + valid = false; + } else { +#ifndef ALTERA_PLATFORM + memcpy(rx, phy->filt_rx_path_clks, sizeof(rx)); + memcpy(tx, phy->filt_tx_path_clks, sizeof(tx)); +#else + int32_t i; + uint32_t num; + num = sizeof(rx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + rx[i] = phy->filt_rx_path_clks[i]; + num = sizeof(tx) / sizeof(rx[0]); + for (i = 0; i < num; i++) + tx[i] = phy->filt_tx_path_clks[i]; +#endif + valid = true; + + } + +#ifdef _DEBUG + dev_dbg(&phy->spi->dev, + "%s:RX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, rx[BBPLL_FREQ], rx[ADC_FREQ], + rx[R2_FREQ], rx[R1_FREQ], + rx[CLKRF_FREQ], rx[RX_SAMPL_FREQ]); + + dev_dbg(&phy->spi->dev, + "%s:TX %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32" %"PRIu32, + __func__, tx[BBPLL_FREQ], tx[ADC_FREQ], + tx[R2_FREQ], tx[R1_FREQ], + tx[CLKRF_FREQ], tx[RX_SAMPL_FREQ]); +#endif + + if (!phy->bypass_tx_fir) { + max = (tx[DAC_FREQ] / tx[TX_SAMPL_FREQ]) * 16; + if (phy->tx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio DAC / TX_SAMPL * 16 > TAPS" + "(max %"PRIu32", adc %"PRIu32", tx %"PRIu32")", + __func__, max, tx[DAC_FREQ], tx[TX_SAMPL_FREQ]); + return -EINVAL; + } + } + + if (!phy->bypass_rx_fir) { + max = ((rx[ADC_FREQ] / ((rx[ADC_FREQ] == rx[R2_FREQ]) ? 1 : 2)) / + rx[RX_SAMPL_FREQ]) * 16; + if (phy->rx_fir_ntaps > max) { + dev_err(dev, + "%s: Invalid: ratio ADC/2 / RX_SAMPL * 16 > TAPS (max %"PRIu32")", + __func__, max); + return -EINVAL; + } + } + + ret = ad9361_set_trx_clock_chain(phy, rx, tx); + if (ret < 0) + return ret; + + /* See also: ad9361_set_trx_clock_chain() */ + if (!phy->pdata->dig_interface_tune_fir_disable && + phy->bypass_tx_fir && phy->bypass_rx_fir) + ad9361_dig_tune(phy, 0, RESTORE_DEFAULT); + + return ad9361_update_rf_bandwidth(phy, + valid ? phy->filt_rx_bw_Hz : phy->current_rx_bw_Hz, + valid ? phy->filt_tx_bw_Hz : phy->current_tx_bw_Hz); +} + +/* +* AD9361 Clocks +*/ + +/** +* Set the multiplier and the divider for the selected refclk_scale structure. +* @param priv The selected refclk_scale structure. +* @param mul The multiplier value. +* @param div The divider value. +* @return 0 in case of success, negative error code otherwise. +*/ +static inline int32_t ad9361_set_muldiv(struct refclk_scale *priv, uint32_t mul, + uint32_t div) +{ + priv->mult = mul; + priv->div = div; + return 0; +} + +/** + * Get the clk scaler for the selected refclk_scale structure. + * @param priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_get_clk_scaler(struct refclk_scale *clk_priv) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp, tmp1; + + switch (clk_priv->source) { + case BB_REFCLK: + tmp = ad9361_spi_read(spi, REG_CLOCK_CTRL); + tmp &= 0x3; + break; + case RX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB); + tmp1 = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB); + tmp = (tmp << 1) | tmp1; + break; + case TX_REFCLK: + tmp = ad9361_spi_readf(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0)); + break; + case ADC_CLK: + tmp = ad9361_spi_read(spi, REG_BBPLL); + return ad9361_set_muldiv(clk_priv, 1, 1 << (tmp & 0x7)); + case R2_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case R1_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKRF_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, RHB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case RX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + case DAC_CLK: + tmp = ad9361_spi_readf(spi, REG_BBPLL, BIT(3)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T2_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0)); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case T1_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB2_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case CLKTF_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, THB1_EN); + return ad9361_set_muldiv(clk_priv, 1, tmp + 1); + case TX_SAMPL_CLK: + tmp = ad9361_spi_readf(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0)); + + if (!tmp) + tmp = 1; /* bypass filter */ + else + tmp = (1 << (tmp - 1)); + + return ad9361_set_muldiv(clk_priv, 1, tmp); + default: + return -EINVAL; + } + + /* REFCLK Scaler */ + switch (tmp) { + case 0: + ad9361_set_muldiv(clk_priv, 1, 1); + break; + case 1: + ad9361_set_muldiv(clk_priv, 1, 2); + break; + case 2: + ad9361_set_muldiv(clk_priv, 1, 4); + break; + case 3: + ad9361_set_muldiv(clk_priv, 2, 1); + break; + default: + return -EINVAL; + + } + + return 0; +} + +/** + * Calculate the REFCLK Scaler for the selected refclk_scale structure. + * Note: REFCLK Scaler values - 00: x1; 01: x½; 10: x¼; 11: x2. + * @param clk_priv The selected refclk_scale structure. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_to_refclk_scaler(struct refclk_scale *clk_priv) +{ + /* REFCLK Scaler */ + switch (((clk_priv->mult & 0xF) << 4) | (clk_priv->div & 0xF)) { + case 0x11: + return 0; + case 0x12: + return 1; + case 0x14: + return 2; + case 0x21: + return 3; + default: + return -EINVAL; + } +}; + +/** + * Set clk scaler for the selected refclk_scale structure. + * @param clk_priv The selected refclk_scale structure. + * @param set Set true, the reference clock frequency will be scaled before + * it enters the BBPLL. + * @return 0 in case of success, negative error code otherwise. + */ +static int32_t ad9361_set_clk_scaler(struct refclk_scale *clk_priv, bool set) +{ + struct spi_desc *spi = clk_priv->spi; + uint32_t tmp; + int32_t ret; + + switch (clk_priv->source) { + case BB_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_CLOCK_CTRL, + REF_FREQ_SCALER(~0), ret); + break; + + case RX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) { + tmp = ret; + ret = ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_1, + RX_REF_DIVIDER_MSB, tmp >> 1); + ret |= ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + RX_REF_DIVIDER_LSB, tmp & 1); + return ret; + } + break; + case TX_REFCLK: + ret = ad9361_to_refclk_scaler(clk_priv); + if (ret < 0) + return ret; + if (set) + return ad9361_spi_writef(spi, REG_REF_DIVIDE_CONFIG_2, + TX_REF_DIVIDER(~0), ret); + break; + case ADC_CLK: + tmp = ilog2((uint8_t)clk_priv->div); + if (clk_priv->mult != 1 || tmp > 6 || tmp < 1) + return -EINVAL; + + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, 0x7, tmp); + break; + case R2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + DEC3_ENABLE_DECIMATION(~0), + clk_priv->div - 1); + break; + case R1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB2_EN, clk_priv->div - 1); + break; + case CLKRF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RHB1_EN, clk_priv->div - 1); + break; + case RX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_rx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_RX_ENABLE_FILTER_CTRL, + RX_FIR_ENABLE_DECIMATION(~0), tmp); + break; + case DAC_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_BBPLL, + BIT(3), clk_priv->div - 1); + break; + case T2_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 3 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB3_ENABLE_INTERP(~0), + clk_priv->div - 1); + break; + case T1_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB2_EN, clk_priv->div - 1); + break; + case CLKTF_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 2 || clk_priv->div < 1) + return -EINVAL; + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + THB1_EN, clk_priv->div - 1); + break; + case TX_SAMPL_CLK: + if (clk_priv->mult != 1 || clk_priv->div > 4 || + clk_priv->div < 1 || clk_priv->div == 3) + return -EINVAL; + + if (clk_priv->phy->bypass_tx_fir) + tmp = 0; + else + tmp = ilog2(clk_priv->div) + 1; + + if (set) + return ad9361_spi_writef(spi, REG_TX_ENABLE_FILTER_CTRL, + TX_FIR_ENABLE_INTERPOLATION(~0), tmp); + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + + ad9361_get_clk_scaler(clk_priv); + rate = (parent_rate * clk_priv->mult) / clk_priv->div; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + int32_t ret; + + if (rate >= *prate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, *prate); + clk_priv->div = 1; + + } else { + clk_priv->div = DIV_ROUND_CLOSEST(*prate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + ret = ad9361_set_clk_scaler(clk_priv, false); + if (ret < 0) + return ret; + + return (*prate / clk_priv->div) * clk_priv->mult; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + if (rate >= parent_rate) { + clk_priv->mult = DIV_ROUND_CLOSEST(rate, parent_rate); + clk_priv->div = 1; + } else { + clk_priv->div = DIV_ROUND_CLOSEST(parent_rate, rate); + clk_priv->mult = 1; + if (!clk_priv->div) { + dev_err(&clk_priv->spi->dev, "%s: divide by zero", + __func__); + clk_priv->div = 1; + } + } + + return ad9361_set_clk_scaler(clk_priv, true); +} + +/* + * BBPLL + */ +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + uint64_t rate; + uint32_t fract, integer; + uint8_t buf[4]; + + ad9361_spi_readm(clk_priv->spi, REG_INTEGER_BB_FREQ_WORD, &buf[0], + REG_INTEGER_BB_FREQ_WORD - REG_FRACT_BB_FREQ_WORD_1 + 1); + + fract = (buf[3] << 16) | (buf[2] << 8) | buf[1]; + integer = buf[0]; + + rate = ((uint64_t)parent_rate * fract); + do_div(&rate, BBPLL_MODULUS); + rate += (uint64_t)parent_rate * integer; + + return (uint32_t)rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate) +{ + uint64_t tmp; + uint32_t fract, integer; + uint64_t temp; + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (rate > MAX_BBPLL_FREQ) + return MAX_BBPLL_FREQ; + + if (rate < MIN_BBPLL_FREQ) + return MIN_BBPLL_FREQ; + + temp = rate; + tmp = do_div(&temp, *prate); + rate = temp; + tmp = tmp * BBPLL_MODULUS + (*prate >> 1); + do_div(&tmp, *prate); + + integer = rate; + fract = tmp; + + tmp = *prate * (uint64_t)fract; + do_div(&tmp, BBPLL_MODULUS); + tmp += *prate * integer; + + return tmp; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct spi_desc *spi = clk_priv->spi; + uint64_t tmp; + uint32_t fract, integer; + int32_t icp_val; + uint8_t lf_defaults[3] = { 0x35, 0x5B, 0xE8 }; + uint64_t temp; + + dev_dbg(&spi->dev, "%s: Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, rate, parent_rate); + + /* + * Setup Loop Filter and CP Current + * Scale is 150uA @ (1280MHz BBPLL, 40MHz REFCLK) + */ + tmp = (rate >> 7) * 150ULL; + do_div(&tmp, (parent_rate >> 7) * 32UL); + + /* 25uA/LSB, Offset 25uA */ + icp_val = DIV_ROUND_CLOSEST((uint32_t)tmp, 25U) - 1; + + icp_val = clamp(icp_val, 1, 64); + + ad9361_spi_write(spi, REG_CP_CURRENT, icp_val); + ad9361_spi_writem(spi, REG_LOOP_FILTER_3, lf_defaults, + ARRAY_SIZE(lf_defaults)); + + /* Allow calibration to occur and set cal count to 1024 for max accuracy */ + ad9361_spi_write(spi, REG_VCO_CTRL, + FREQ_CAL_ENABLE | FREQ_CAL_COUNT_LENGTH(3)); + /* Set calibration clock to REFCLK/4 for more accuracy */ + ad9361_spi_write(spi, REG_SDM_CTRL, 0x10); + + /* Calculate and set BBPLL frequency word */ + temp = rate; + tmp = do_div(&temp, parent_rate); + rate = temp; + tmp = tmp *(uint64_t)BBPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + + integer = rate; + fract = tmp; + + ad9361_spi_write(spi, REG_INTEGER_BB_FREQ_WORD, integer); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_3, fract); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_2, fract >> 8); + ad9361_spi_write(spi, REG_FRACT_BB_FREQ_WORD_1, fract >> 16); + + ad9361_spi_write(spi, REG_SDM_CTRL_1, + INIT_BB_FO_CAL | BBPLL_RESET_BAR); /* Start BBPLL Calibration */ + ad9361_spi_write(spi, REG_SDM_CTRL_1, + BBPLL_RESET_BAR); /* Clear BBPLL start calibration bit */ + + ad9361_spi_write(spi, REG_VCO_PROGRAM_1, + 0x86); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x01); /* Increase BBPLL KV and phase margin */ + ad9361_spi_write(spi, REG_VCO_PROGRAM_2, + 0x05); /* Increase BBPLL KV and phase margin */ + + return ad9361_check_cal_done(clk_priv->phy, REG_CH_1_OVERFLOW, + BBPLL_LOCK, 1); +} + +/* + * RFPLL + */ + +/** + * Calculate the RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @return The RFPLL frequency. + */ +static uint64_t ad9361_calc_rfpll_int_freq(uint64_t parent_rate, + uint64_t integer, + uint64_t fract, uint32_t vco_div) +{ + uint64_t rate; + + rate = parent_rate * fract; + do_div(&rate, RFPLL_MODULUS); + rate += parent_rate * integer; + + return rate >> (vco_div + 1); +} + +/** + * Calculate the RFPLL dividers. + * @param phy The AD9361 state structure. + * @param clk_priv The refclk_scale structure. + * @param freq The RFPLL frequency. + * @param parent_rate The parent clock rate. + * @param integer The integer value. + * @param fract The fractional value. + * @param vco_div The VCO divider. + * @param vco_freq The VCO frequency. + * @return The RFPLL frequency. + */ +static int32_t ad9361_calc_rfpll_int_divder(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, uint64_t freq, + uint64_t parent_rate, uint32_t *integer, + uint32_t *fract, int32_t *vco_div, uint64_t *vco_freq) +{ + uint64_t tmp; + int32_t div, ret; + + ret = ad9361_validate_rfpll(phy, clk_priv->source == TX_RFPLL_INT, freq); + if (ret) + return ret; + + div = -1; + + while (freq <= MIN_VCO_FREQ_HZ) { + freq <<= 1; + div++; + } + + *vco_div = div; + *vco_freq = freq; + tmp = do_div(&freq, parent_rate); + tmp = tmp * RFPLL_MODULUS + (parent_rate >> 1); + do_div(&tmp, parent_rate); + *integer = freq; + *fract = tmp; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @param parent_rate The parent clock rate. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t fract, integer; + uint8_t buf[5]; + uint32_t reg, div_mask, vco_div, profile; + + dev_dbg(&clk_priv->spi->dev, "%s: Parent Rate %"PRIu32" Hz", + __func__, parent_rate); + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + div_mask = RX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[0]; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + div_mask = TX_VCO_DIVIDER(~0); + profile = phy->fastlock.current_profile[1]; + break; + default: + return -EINVAL; + } + + if (profile) { + bool tx = clk_priv->source == TX_RFPLL_INT; + profile = profile - 1; + + buf[0] = ad9361_fastlock_readval(phy->spi, tx, profile, 4); + buf[1] = ad9361_fastlock_readval(phy->spi, tx, profile, 3); + buf[2] = ad9361_fastlock_readval(phy->spi, tx, profile, 2); + buf[3] = ad9361_fastlock_readval(phy->spi, tx, profile, 1); + buf[4] = ad9361_fastlock_readval(phy->spi, tx, profile, 0); + vco_div = ad9361_fastlock_readval(phy->spi, tx, profile, 12) & 0xF; + + } else { + ad9361_spi_readm(clk_priv->spi, reg, &buf[0], ARRAY_SIZE(buf)); + vco_div = ad9361_spi_readf(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask); + } + + fract = (SYNTH_FRACT_WORD(buf[0]) << 16) | (buf[1] << 8) | buf[2]; + integer = (SYNTH_INTEGER_WORD(buf[3]) << 8) | buf[4]; + + return ad9361_to_clk(ad9361_calc_rfpll_int_freq(parent_rate, integer, + fract, vco_div)); +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param prate The parent clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate) +{ + dev_dbg(&clk_priv->spi->dev, "%s: Rate %"PRIu32" Hz", __func__, rate); + + if (prate) { + // Unused variable - fix compiler warning + } + + if (clk_priv) { + // Unused variable - fix compiler warning + } + + if (ad9361_from_clk(rate) > MAX_CARRIER_FREQ_HZ || + ad9361_from_clk(rate) < ((clk_priv->source == TX_RFPLL_INT) ? + MIN_TX_CARRIER_FREQ_HZ : MIN_RX_CARRIER_FREQ_HZ)) + return -EINVAL; + + return rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @param parent_rate The parent clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint64_t vco = 0; + uint8_t buf[5]; + uint32_t reg, div_mask, lock_reg, fract = 0, integer = 0; + int32_t vco_div, ret, fixup_other; + + dev_dbg(&clk_priv->spi->dev, + "%s: %s Rate %"PRIu32" Hz Parent Rate %"PRIu32" Hz", + __func__, clk_priv->source == TX_RFPLL_INT ? "TX" : "RX", + rate, parent_rate); + + ad9361_fastlock_prepare(phy, clk_priv->source == TX_RFPLL_INT, 0, false); + + ret = ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(rate), + parent_rate, + &integer, &fract, &vco_div, &vco); + if (ret < 0) + return ret; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + phy->cached_rx_rfpll_div = vco_div; + phy->current_rx_lo_freq = rate; + break; + case TX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + phy->cached_tx_rfpll_div = vco_div; + phy->current_tx_lo_freq = rate; + break; + default: + return -EINVAL; + + } + + /* Option to skip VCO cal in TDD mode when moving from TX/RX to Alert */ + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + true); + + do { + fixup_other = 0; + ad9361_rfpll_vco_init(phy, div_mask == TX_VCO_DIVIDER(~0), + vco, parent_rate); + + buf[0] = SYNTH_FRACT_WORD(fract >> 16); + buf[1] = fract >> 8; + buf[2] = fract & 0xFF; + buf[3] = SYNTH_INTEGER_WORD(integer >> 8) | + (~SYNTH_INTEGER_WORD(~0) & + ad9361_spi_read(clk_priv->spi, reg - 3)); + buf[4] = integer & 0xFF; + + ad9361_spi_writem(clk_priv->spi, reg, buf, 5); + ad9361_spi_writef(clk_priv->spi, REG_RFPLL_DIVIDERS, div_mask, vco_div); + + ret = ad9361_check_cal_done(phy, lock_reg, VCO_LOCK, 1); + + /* In FDD mode with RX LO == TX LO frequency we use TDD tables to + * reduce VCO pulling + */ + + if (((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq == phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table != phy->current_rx_use_tdd_table)) || + ((phy->pdata->fdd && !phy->pdata->fdd_independent_mode) && + (phy->current_tx_lo_freq != phy->current_rx_lo_freq) && + (phy->current_tx_use_tdd_table || phy->current_rx_use_tdd_table))) { + unsigned long _rate; + + switch (clk_priv->source) { + case RX_RFPLL_INT: + reg = REG_TX_FRACT_BYTE_2; + lock_reg = REG_TX_CP_OVERRANGE_VCO_LOCK; + div_mask = TX_VCO_DIVIDER(~0); + _rate = phy->current_tx_lo_freq; + break; + case TX_RFPLL_INT: + reg = REG_RX_FRACT_BYTE_2; + lock_reg = REG_RX_CP_OVERRANGE_VCO_LOCK; + div_mask = RX_VCO_DIVIDER(~0); + _rate = phy->current_rx_lo_freq; + break; + default: + return -EINVAL; + + } + + if (phy->current_tx_lo_freq != phy->current_rx_lo_freq) { + ad9361_calc_rfpll_int_divder(phy, clk_priv, ad9361_from_clk(_rate), + parent_rate, &integer, &fract, &vco_div, &vco); + + ad9361_fastlock_prepare(phy, clk_priv->source == RX_RFPLL_INT, 0, false); + } + + fixup_other = 1; + } + + } while (fixup_other); + + if (phy->pdata->tdd_skip_vco_cal) + ad9361_trx_vco_cal_control(phy, clk_priv->source == TX_RFPLL_INT, + false); + + return ret; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + return phy->clks[clk_priv->source]->rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + + phy->clks[clk_priv->source]->rate = rate; + + return 0; +} + +/** + * Recalculate the clock rate. + * @param clk_priv The refclk_scale structure. + * @return The clock rate. + */ +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + uint32_t rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[RX_RFPLL_INT], + phy->clks[RX_REFCLK]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_recalc_rate) + rate = phy->ad9361_rfpll_ext_recalc_rate(clk_priv); + else + rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY]); + } else { + rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[TX_RFPLL_INT], + phy->clks[TX_REFCLK]->rate); + } + break; + default: + rate = 0; + break; + } + + return rate; +} + +/** + * Calculate the closest possible clock rate that can be set. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return The closest possible clock rate that can be set. + */ +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t round_rate; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_round_rate) + round_rate = phy->ad9361_rfpll_ext_round_rate(clk_priv, rate); + else + round_rate = rate; + } else { + round_rate = ad9361_rfpll_int_round_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + &phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + break; + default: + round_rate = 0; + break; + } + + return round_rate; +} + +/** + * Set the clock rate. + * @param clk_priv The refclk_scale structure. + * @param rate The clock rate. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + switch (clk_priv->source) { + case RX_RFPLL: + if (phy->pdata->use_ext_rx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[RX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[RX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[RX_RFPLL_INT]->parent_source]->rate); + } + /* Load Gain Table */ + ret = ad9361_load_gt(phy, ad9361_from_clk(rate), GT_RX1 + GT_RX2); + if (ret < 0) + return ret; + break; + case TX_RFPLL: + if (phy->pdata->use_ext_tx_lo) { + if (phy->ad9361_rfpll_ext_set_rate) + phy->ad9361_rfpll_ext_set_rate(clk_priv, rate); + else + ad9361_rfpll_dummy_set_rate(phy->ref_clk_scale[TX_RFPLL_DUMMY], rate); + } else { + ad9361_rfpll_int_set_rate(phy->ref_clk_scale[TX_RFPLL_INT], rate, + phy->clks[phy->ref_clk_scale[TX_RFPLL_INT]->parent_source]->rate); + } + /* For RX LO we typically have the tracking option enabled + * so for now do nothing here. + */ + if (phy->auto_cal_en && !phy->pdata->use_ext_tx_lo) + if ((diff_abs(phy->last_tx_quad_cal_freq, ad9361_from_clk(rate))) > + phy->cal_threshold_freq) { + ret = ad9361_do_calib_run(phy, TX_QUAD_CAL, -1); + if (ret < 0) + dev_err(&phy->spi->dev, + "%s: TX QUAD cal failed", __func__); + phy->last_tx_quad_cal_freq = ad9361_from_clk(rate); + } + break; + default: + break; + } + + return 0; +} + +/** + * Set clock mux parent. + * @param clk_priv The refclk_scale structure. + * @param index Index - Enable (1), disable (0) ext lo. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index) +{ + struct ad9361_rf_phy *phy = clk_priv->phy; + int32_t ret; + + dev_dbg(&clk_priv->spi->dev, "%s: index %d", __func__, index); + + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + ret = ad9361_trx_ext_lo_control(phy, clk_priv->source == TX_RFPLL, index == 1); + if (ret >= 0) + clk_priv->mult = index; + + ad9361_ensm_restore_prev_state(phy); + + return ret; +} + +/** + * Register and initialize a new clock. + * @param phy The AD9361 state structure. + * @param name The name of the new clock. + * @param parent_name The name of the parent clock. + * @param flags The flags. + * @param source The source of the new clock. + * @param parent_source The source of the parent clock. + * @return A struct clk for the new clock or a negative error code. + */ +static struct clk *ad9361_clk_register(struct ad9361_rf_phy *phy, + const char *name, + const char *parent_name, uint32_t flags, + uint32_t source, uint32_t parent_source) +{ + struct refclk_scale *clk_priv; + struct clk *clk; + + if (name) { + // Unused variable - fix compiler warning + } + if (parent_name) { + // Unused variable - fix compiler warning + } + if (flags) { + // Unused variable - fix compiler warning + } + + clk_priv = (struct refclk_scale *)malloc(sizeof(*clk_priv)); + if (!clk_priv) { + dev_err(&phy->spi->dev, + "ad9361_clk_register: could not allocate fixed factor clk"); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + /* struct refclk_scale assignments */ + clk_priv->source = (enum ad9361_clocks)source; + clk_priv->parent_source = (enum ad9361_clocks)parent_source; + clk_priv->spi = phy->spi; + clk_priv->phy = phy; + + phy->ref_clk_scale[source] = clk_priv; + + clk = (struct clk *)malloc(sizeof(*clk)); + if (!clk) { + free(clk_priv); + return (struct clk *)ERR_PTR(-ENOMEM); + } + + switch (source) { + case TX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case RX_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BB_REFCLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clk_refin->rate); + break; + case BBPLL_CLK: + clk->rate = ad9361_bbpll_recalc_rate(clk_priv, phy->clks[BB_REFCLK]->rate); + break; + case ADC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[BBPLL_CLK]->rate); + break; + case R2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case R1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R2_CLK]->rate); + break; + case CLKRF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[R1_CLK]->rate); + break; + case RX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKRF_CLK]->rate); + break; + case DAC_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[ADC_CLK]->rate); + break; + case T2_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[DAC_CLK]->rate); + break; + case T1_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T2_CLK]->rate); + break; + case CLKTF_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[T1_CLK]->rate); + break; + case TX_SAMPL_CLK: + clk->rate = ad9361_clk_factor_recalc_rate(clk_priv, phy->clks[CLKTF_CLK]->rate); + break; + case RX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[RX_REFCLK]->rate); + break; + case TX_RFPLL_INT: + clk->rate = ad9361_rfpll_int_recalc_rate(clk_priv, phy->clks[TX_REFCLK]->rate); + break; + case RX_RFPLL_DUMMY: + clk->rate = phy->pdata->rx_synth_freq; + break; + case TX_RFPLL_DUMMY: + clk->rate = phy->pdata->tx_synth_freq; + break; + case RX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case TX_RFPLL: + clk->rate = ad9361_rfpll_recalc_rate(clk_priv); + } + + return clk; +} + +/** + * Register and initialize all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy) +{ + uint32_t flags = CLK_GET_RATE_NOCACHE; + + /* Scaled Reference Clocks */ + phy->clks[TX_REFCLK] = ad9361_clk_register(phy, + "tx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + TX_REFCLK, EXT_REF_CLK); + + phy->clks[RX_REFCLK] = ad9361_clk_register(phy, + "rx_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + RX_REFCLK, EXT_REF_CLK); + + phy->clks[BB_REFCLK] = ad9361_clk_register(phy, + "bb_refclk", "ad9361_ext_refclk", + flags | CLK_IGNORE_UNUSED, + BB_REFCLK, EXT_REF_CLK); + + /* Base Band PLL Clock */ + phy->clks[BBPLL_CLK] = ad9361_clk_register(phy, + "bbpll_clk", "bb_refclk", + flags | CLK_IGNORE_UNUSED, + BBPLL_CLK, BB_REFCLK); + + phy->clks[ADC_CLK] = ad9361_clk_register(phy, + "adc_clk", "bbpll_clk", + flags | CLK_IGNORE_UNUSED, + ADC_CLK, BBPLL_CLK); + + phy->clks[R2_CLK] = ad9361_clk_register(phy, + "r2_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + R2_CLK, ADC_CLK); + + phy->clks[R1_CLK] = ad9361_clk_register(phy, + "r1_clk", "r2_clk", + flags | CLK_IGNORE_UNUSED, + R1_CLK, R2_CLK); + + phy->clks[CLKRF_CLK] = ad9361_clk_register(phy, + "clkrf_clk", "r1_clk", + flags | CLK_IGNORE_UNUSED, + CLKRF_CLK, R1_CLK); + + phy->clks[RX_SAMPL_CLK] = ad9361_clk_register(phy, + "rx_sampl_clk", "clkrf_clk", + flags | CLK_IGNORE_UNUSED, + RX_SAMPL_CLK, CLKRF_CLK); + + + phy->clks[DAC_CLK] = ad9361_clk_register(phy, + "dac_clk", "adc_clk", + flags | CLK_IGNORE_UNUSED, + DAC_CLK, ADC_CLK); + + phy->clks[T2_CLK] = ad9361_clk_register(phy, + "t2_clk", "dac_clk", + flags | CLK_IGNORE_UNUSED, + T2_CLK, DAC_CLK); + + phy->clks[T1_CLK] = ad9361_clk_register(phy, + "t1_clk", "t2_clk", + flags | CLK_IGNORE_UNUSED, + T1_CLK, T2_CLK); + + phy->clks[CLKTF_CLK] = ad9361_clk_register(phy, + "clktf_clk", "t1_clk", + flags | CLK_IGNORE_UNUSED, + CLKTF_CLK, T1_CLK); + + phy->clks[TX_SAMPL_CLK] = ad9361_clk_register(phy, + "tx_sampl_clk", "clktf_clk", + flags | CLK_IGNORE_UNUSED, + TX_SAMPL_CLK, CLKTF_CLK); + + phy->clks[RX_RFPLL_INT] = ad9361_clk_register(phy, + "rx_rfpll", "rx_refclk", + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_INT, RX_REFCLK); + + phy->clks[TX_RFPLL_INT] = ad9361_clk_register(phy, + "tx_rfpll", "tx_refclk", + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_INT, TX_REFCLK); + + phy->clks[RX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "rx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL_DUMMY, 0); + + phy->clks[TX_RFPLL_DUMMY] = ad9361_clk_register(phy, + "tx_rfpll_dummy", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL_DUMMY, 0); + + phy->clks[RX_RFPLL] = ad9361_clk_register(phy, + "rx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + RX_RFPLL, 0); + + phy->clks[TX_RFPLL] = ad9361_clk_register(phy, + "tx_rfpll", NULL, + flags | CLK_IGNORE_UNUSED, + TX_RFPLL, 0); + + return 0; +} + +/** + * Unregister all the system clocks. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy) +{ + int32_t i; + + for (i = 0; i < NUM_AD9361_CLKS; i++) { + free(phy->clks[i]); + free(phy->ref_clk_scale[i]); + } + + return 0; +} + +/** + * Perform an RSSI gain step calibration. + * Note: Before running the function, provide a single tone within the channel + * bandwidth and monitor the received data. Adjust the tone amplitude until + * the received data is within a few dB of full scale but not overloading. + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy) +{ + uint32_t lna_error[4]; + uint32_t mixer_error[15]; + uint64_t lo_freq_hz; + uint8_t lo_index; + uint8_t i; + + lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + if (lo_freq_hz < 1300000000ULL) + lo_index = 0; + else if (lo_freq_hz < 3300000000ULL) + lo_index = 1; + else if (lo_freq_hz < 4100000000ULL) + lo_index = 2; + else + lo_index = 3; + + /* Put the AD9361 into the Alert state. */ + ad9361_ensm_force_state(phy, ENSM_STATE_ALERT); + + /* Program the directly-addressable register values. */ + ad9361_spi_write(phy->spi, REG_MAX_MIXER_CALIBRATION_GAIN_INDEX, + MAX_MIXER_CALIBRATION_GAIN_INDEX(0x0F)); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION, + GAIN_CAL_MEAS_DURATION(0x0E)); + ad9361_spi_write(phy->spi, REG_SETTLE_TIME, + SETTLE_TIME(0x3F)); + ad9361_spi_write(phy->spi, REG_RSSI_CONFIG, + RSSI_MODE_SELECT(0x3) | DEFAULT_RSSI_MEAS_MODE); + ad9361_spi_write(phy->spi, REG_MEASURE_DURATION_01, + MEASUREMENT_DURATION_0(0x0E)); + ad9361_spi_write(phy->spi, REG_LNA_GAIN, + gain_step_calib_reg_val[lo_index][0]); + + /* Program the LNA gain step words into the internal table. */ + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, + gain_step_calib_reg_val[lo_index][i+1]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_GAIN_DIFF | START_CALIB_TABLE_CLOCK); + udelay(3); //Wait for data to fully write to internal table + } + + ad9361_spi_write(phy->spi, REG_CONFIG, START_CALIB_TABLE_CLOCK); + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Run and wait until the calibration completes. */ + ad9361_run_calibration(phy, RX_GAIN_STEP_CAL); + + /* Read the LNA and Mixer error terms into nonvolatile memory. */ + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1) | READ_SELECT); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + lna_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, CALIB_TABLE_SELECT(0x1)); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + mixer_error[i] = ad9361_spi_read(phy->spi, REG_GAIN_ERROR_READ); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + /* Programming gain step errors into the AD9361 in the field */ + ad9361_spi_write(phy->spi, + REG_CONFIG, CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 4; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, lna_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_LNA_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | START_CALIB_TABLE_CLOCK); + for(i = 0; i < 15; i++) { + ad9361_spi_write(phy->spi, REG_WORD_ADDRESS, i); + ad9361_spi_write(phy->spi, REG_GAIN_DIFF_WORDERROR_WRITE, mixer_error[i]); + ad9361_spi_write(phy->spi, REG_CONFIG, + CALIB_TABLE_SELECT(0x3) | WRITE_MIXER_ERROR_TABLE | START_CALIB_TABLE_CLOCK); + } + ad9361_spi_write(phy->spi, REG_CONFIG, 0x00); + + ad9361_ensm_restore_prev_state(phy); + + return 0; +} diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.h b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.h new file mode 100644 index 0000000..638acdc --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361.h @@ -0,0 +1,3568 @@ +/***************************************************************************//** + * @file ad9361.h + * @brief Header file of AD9361 Driver. +******************************************************************************** + * Copyright 2014(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef IIO_FREQUENCY_AD9361_H_ +#define IIO_FREQUENCY_AD9361_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "common.h" +#include "../../../include/gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define REG_SPI_CONF 0x000 /* SPI Configuration */ +#define REG_MULTICHIP_SYNC_AND_TX_MON_CTRL 0x001 /* Multi-Chip Sync and Tx Mon Control */ +#define REG_TX_ENABLE_FILTER_CTRL 0x002 /* Tx Enable & Filter Control */ +#define REG_RX_ENABLE_FILTER_CTRL 0x003 /* Rx Enable & Filter Control */ +#define REG_INPUT_SELECT 0x004 /* Input Select */ +#define REG_RFPLL_DIVIDERS 0x005 /* RFPLL Dividers */ +#define REG_RX_CLOCK_DATA_DELAY 0x006 /* Rx Clock & Data Delay */ +#define REG_TX_CLOCK_DATA_DELAY 0x007 /* Tx Clock & Data Delay */ +#define REG_CLOCK_ENABLE 0x009 /* Clock Enable */ +#define REG_BBPLL 0x00A /* BBPLL */ +#define REG_TEMP_OFFSET 0x00B /* Offset */ +#define REG_START_TEMP_READING 0x00C /* Start Temp Reading */ +#define REG_TEMP_SENSE2 0x00D /* Temp Sense2 */ +#define REG_TEMPERATURE 0x00E /* Temperature */ +#define REG_TEMP_SENSOR_CONFIG 0x00F /* Temp Sensor Config */ +#define REG_PARALLEL_PORT_CONF_1 0x010 /* Parallel Port Configuration 1 */ +#define REG_PARALLEL_PORT_CONF_2 0x011 /* Parallel Port Configuration 2 */ +#define REG_PARALLEL_PORT_CONF_3 0x012 /* Parallel Port Configuration 3 */ +#define REG_ENSM_MODE 0x013 /* ENSM Mode */ +#define REG_ENSM_CONFIG_1 0x014 /* ENSM Config 1 */ +#define REG_ENSM_CONFIG_2 0x015 /* ENSM Config 2 */ +#define REG_CALIBRATION_CTRL 0x016 /* Calibration Control */ +#define REG_STATE 0x017 /* State */ +#define REG_AUXDAC_1_WORD 0x018 /* AuxDAC 1 Word */ +#define REG_AUXDAC_2_WORD 0x019 /* AuxDAC 2 Word */ +#define REG_AUXDAC_1_CONFIG 0x01A /* AuxDAC 1 Config */ +#define REG_AUXDAC_2_CONFIG 0x01B /* AuxDAC 2 Config */ +#define REG_AUXADC_CLOCK_DIVIDER 0x01C /* AuxADC Clock Divider */ +#define REG_AUXADC_CONFIG 0x01D /* Aux ADC Config */ +#define REG_AUXADC_WORD_MSB 0x01E /* AuxADC Word MSB */ +#define REG_AUXADC_LSB 0x01F /* AuxADC LSB */ +#define REG_AUTO_GPO 0x020 /* Auto GPO */ +#define REG_AGC_GAIN_LOCK_DELAY 0x021 /* AGC Gain Lock Delay */ +#define REG_AGC_ATTACK_DELAY 0x022 /* AGC Attack Delay */ +#define REG_AUXDAC_ENABLE_CTRL 0x023 /* AuxDAC Enable Control */ +#define REG_RX_LOAD_SYNTH_DELAY 0x024 /* RX Load Synth Delay */ +#define REG_TX_LOAD_SYNTH_DELAY 0x025 /* TX Load Synth Delay */ +#define REG_EXTERNAL_LNA_CTRL 0x026 /* External LNA control */ +#define REG_GPO_FORCE_AND_INIT 0x027 /* GPO Force and Init */ +#define REG_GPO0_RX_DELAY 0x028 /* GPO0 Rx delay */ +#define REG_GPO1_RX_DELAY 0x029 /* GPO1 Rx delay */ +#define REG_GPO2_RX_DELAY 0x02A /* GPO2 Rx delay */ +#define REG_GPO3_RX_DELAY 0x02B /* GPO3 Rx delay */ +#define REG_GPO0_TX_DELAY 0x02C /* GPO0 Tx Delay */ +#define REG_GPO1_TX_DELAY 0x02D /* GPO1 Tx Delay */ +#define REG_GPO2_TX_DELAY 0x02E /* GPO2 Tx Delay */ +#define REG_GPO3_TX_DELAY 0x02F /* GPO3 Tx Delay */ +#define REG_AUXDAC1_RX_DELAY 0x030 /* AuxDAC1 Rx Delay */ +#define REG_AUXDAC1_TX_DELAY 0x031 /* AuxDAC1 Tx Delay */ +#define REG_AUXDAC2_RX_DELAY 0x032 /* AuxDAC2 Rx Delay */ +#define REG_AUXDAC2_TX_DELAY 0x033 /* AuxDAC2 Tx Delay */ +#define REG_CTRL_OUTPUT_POINTER 0x035 /* Control Output Pointer */ +#define REG_CTRL_OUTPUT_ENABLE 0x036 /* Control Output Enable */ +#define REG_PRODUCT_ID 0x037 /* Product ID */ +#define REG_REFERENCE_CLOCK_CYCLES 0x03A /* Reference Clock Cycles */ +#define REG_DIGITAL_IO_CTRL 0x03B /* Digital I/O Control */ +#define REG_LVDS_BIAS_CTRL 0x03C /* LVDS Bias control */ +#define REG_LVDS_INVERT_CTRL1 0x03D /* LVDS Invert control1 */ +#define REG_LVDS_INVERT_CTRL2 0x03E /* LVDS Invert control2 */ +#define REG_SDM_CTRL_1 0x03F /* SDM Control 1 */ +#define REG_FRACT_BB_FREQ_WORD_1 0x041 /* Fractional BB Freq Word 1 */ +#define REG_FRACT_BB_FREQ_WORD_2 0x042 /* Fractional BB Freq Word 2 */ +#define REG_FRACT_BB_FREQ_WORD_3 0x043 /* Fractional BB Freq Word 3 */ +#define REG_INTEGER_BB_FREQ_WORD 0x044 /* Integer BB Freq Word */ +#define REG_CLOCK_CTRL 0x045 /* Clock Control */ +#define REG_CP_CURRENT 0x046 /* CP Current */ +#define REG_CP_BLEED_CURRENT 0x047 /* CP Bleed Current */ +#define REG_LOOP_FILTER_1 0x048 /* Loop Filter 1 */ +#define REG_LOOP_FILTER_2 0x049 /* Loop Filter 2 */ +#define REG_LOOP_FILTER_3 0x04A /* Loop Filter 3 */ +#define REG_VCO_CTRL 0x04B /* VCO Control */ +#define REG_VCO_PROGRAM_1 0x04C +#define REG_VCO_PROGRAM_2 0x04D +#define REG_SDM_CTRL 0x04E /* SDM Control */ +#define REG_RX_SYNTH_POWER_DOWN_OVERRIDE 0x050 /* Rx Synth Power Down Override */ +#define REG_TX_SYNTH_POWER_DOWN_OVERRIDE 0x051 /* TX Synth Power Down Override */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 0x052 /* Rx Analog Power Down Override 1 */ +#define REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 0x053 /* Rx Analog Power Down Override 2 */ +#define REG_RX1_ADC_POWER_DOWN_OVERRIDE 0x054 /* Rx1 ADC Power Down Override */ +#define REG_RX2_ADC_POWER_DOWN_OVERRIDE 0x055 /* Rx2 ADC Power Down Override */ +#define REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 0x056 /* Tx Analog Power Down Override 1 */ +#define REG_ANALOG_POWER_DOWN_OVERRIDE 0x057 /* Analog Power Down Override */ +#define REG_MISC_POWER_DOWN_OVERRIDE 0x058 /* Misc Power Down Override */ +#define REG_CH_1_OVERFLOW 0x05E /* CH 1 Overflow */ +#define REG_CH_2_OVERFLOW 0x05F /* CH 2 Overflow */ +#define REG_TX_FILTER_COEF_ADDR 0x060 /* TX Filter Coefficient Address */ +#define REG_TX_FILTER_COEF_WRITE_DATA_1 0x061 /* TX Filter Coefficient Write Data 1 */ +#define REG_TX_FILTER_COEF_WRITE_DATA_2 0x062 /* TX Filter Coefficient Write Data 2 */ +#define REG_TX_FILTER_COEF_READ_DATA_1 0x063 /* TX Filter Coefficient Read Data 1 */ +#define REG_TX_FILTER_COEF_READ_DATA_2 0x064 /* TX Filter Coefficient Read Data 2 */ +#define REG_TX_FILTER_CONF 0x065 /* TX Filter Configuration */ +#define REG_TX_MON_LOW_GAIN 0x067 /* Tx Mon Low Gain */ +#define REG_TX_MON_HIGH_GAIN 0x068 /* Tx Mon High Gain */ +#define REG_TX_MON_DELAY 0x069 /* Tx Mon Delay */ +#define REG_TX_LEVEL_THRESH 0x06A /* Tx Level Threshold */ +#define REG_TX_RSSI1 0x06B /* TX RSSI1 */ +#define REG_TX_RSSI2 0x06C /* TX RSSI2 */ +#define REG_TX_RSSI_LSB 0x06D /* TX RSSI LSB */ +#define REG_TPM_MODE_ENABLE 0x06E /* TPM Mode Enable */ +#define REG_TX_MON_TEMP_GAIN_COEF 0x06F /* Temp Gain Coefficient */ +#define REG_TX_MON_1_CONFIG 0x070 /* Tx Mon 1 Config */ +#define REG_TX_MON_2_CONFIG 0x071 /* Tx Mon 2 Config */ +#define REG_TX1_ATTEN_0 0x073 /* Tx1 Atten 0 */ +#define REG_TX1_ATTEN_1 0x074 /* Tx1 Atten 1 */ +#define REG_TX2_ATTEN_0 0x075 /* Tx2 Atten 0 */ +#define REG_TX2_ATTEN_1 0x076 /* Tx2 Atten 1 */ +#define REG_TX_ATTEN_OFFSET 0x077 /* Tx Atten Offset */ +#define REG_TX_ATTEN_THRESH 0x078 /* Tx Atten Threshold */ +#define REG_TX1_DIG_ATTEN 0x079 /* Tx1 Dig Attenuation */ +#define REG_TX2_DIG_ATTEN 0x07C /* Tx2 Dig Attenuation */ +#define REG_TX1_SYMBOL_ATTEN 0x07F /* TX1 Symbol Attenuation */ +#define REG_TX2_SYMBOL_ATTEN 0x080 /* TX2 Symbol Attenuation */ +#define REG_TX_SYMBOL_ATTEN_CONFIG 0x081 /* TX Symbol Atten Config */ +#define REG_TX1_OUT_1_PHASE_CORR 0x08E /* Tx1 Out 1 Phase Corr */ +#define REG_TX1_OUT_1_GAIN_CORR 0x08F /* Tx1 Out 1 Gain Corr */ +#define REG_TX2_OUT_1_PHASE_CORR 0x090 /* Tx2 Out 1 Phase Corr */ +#define REG_TX2_OUT_1_GAIN_CORR 0x091 /* Tx2 Out 1 Gain Corr */ +#define REG_TX1_OUT_1_OFFSET_I 0x092 /* Tx1 Out 1 Offset I */ +#define REG_TX1_OUT_1_OFFSET_Q 0x093 /* Tx1 Out 1 Offset Q */ +#define REG_TX2_OUT_1_OFFSET_I 0x094 /* Tx2 Out 1 Offset I */ +#define REG_TX2_OUT_1_OFFSET_Q 0x095 /* Tx2 Out 1 Offset Q */ +#define REG_TX1_OUT_2_PHASE_CORR 0x096 /* Tx1 Out 2 Phase Corr */ +#define REG_TX1_OUT_2_GAIN_CORR 0x097 /* Tx1 Out 2 Gain Corr */ +#define REG_TX2_OUT_2_PHASE_CORR 0x098 /* Tx2 Out 2 Phase Corr */ +#define REG_TX2_OUT_2_GAIN_CORR 0x099 /* Tx2 Out 2 Gain Corr */ +#define REG_TX1_OUT_2_OFFSET_I 0x09A /* Tx1 Out 2 Offset I */ +#define REG_TX1_OUT_2_OFFSET_Q 0x09B /* Tx1 Out 2 Offset Q */ +#define REG_TX2_OUT_2_OFFSET_I 0x09C /* Tx2 Out 2 Offset I */ +#define REG_TX2_OUT_2_OFFSET_Q 0x09D /* Tx2 Out 2 Offset Q */ +#define REG_TX_FORCE_BITS 0x09F /* Force Bits */ +#define REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET 0x0A0 /* Quad Cal NCO Freq & Phase Offset */ +#define REG_QUAD_CAL_CTRL 0x0A1 /* Quad Cal Control */ +#define REG_KEXP_1 0x0A2 /* Kexp 1 */ +#define REG_KEXP_2 0x0A3 /* Kexp 2 */ +#define REG_QUAD_SETTLE_COUNT 0x0A4 /* QUAD Settle count */ +#define REG_MAG_FTEST_THRESH 0x0A5 /* Mag. Ftest Thresh */ +#define REG_MAG_FTEST_THRESH_2 0x0A6 /* Mag. Ftest Thresh 2 */ +#define REG_QUAD_CAL_STATUS_TX1 0x0A7 /* Quad cal status Tx1 */ +#define REG_QUAD_CAL_STATUS_TX2 0x0A8 /* Quad cal status Tx2 */ +#define REG_QUAD_CAL_COUNT 0x0A9 /* Quad cal Count */ +#define REG_TX_QUAD_FULL_LMT_GAIN 0x0AA /* Tx Quad Full/LMT Gain */ +#define REG_SQUARER_CONFIG 0x0AB /* Squarer Config */ +#define REG_TX_QUAD_CAL_ATTEN 0x0AC /* TX Quad Cal Atten */ +#define REG_THRESH_ACCUM 0x0AD /* Thresh Accum */ +#define REG_TX_QUAD_LPF_GAIN 0x0AE /* Tx Quad LPF Gain */ +#define REG_TXDAC_VDS_I 0x0B0 /* TxDAC Vds I */ +#define REG_TXDAC_VDS_Q 0x0B1 /* TxDAC Vds Q */ +#define REG_TXDAC_GN_I 0x0B2 /* TxDAC gn I */ +#define REG_TXDAC_GN_Q 0x0B3 /* TxDAC gn Q */ +#define REG_TXBBF_OPAMP_A 0x0C0 /* TxBBF OpAmp A */ +#define REG_TXBBF_OPAMP_B 0x0C1 /* TxBBF OpAmp B */ +#define REG_TX_BBF_R1 0x0C2 /* Tx BBF R1 */ +#define REG_TX_BBF_R2 0x0C3 /* Tx BBF R2 */ +#define REG_TX_BBF_R3 0x0C4 /* Tx BBF R3 */ +#define REG_TX_BBF_R4 0x0C5 /* Tx BBF R4 */ +#define REG_TX_BBF_RP 0x0C6 /* Tx BBF RP */ +#define REG_TX_BBF_C1 0x0C7 /* Tx BBF C1 */ +#define REG_TX_BBF_C2 0x0C8 /* Tx BBF C2 */ +#define REG_TX_BBF_CP 0x0C9 /* Tx BBF Cp */ +#define REG_TX_TUNE_CTRL 0x0CA /* Tx Tune Control */ +#define REG_TX_BBF_R2B 0x0CB /* Tx BBF R2b */ +#define REG_TX_BBF_TUNE 0x0CC /* Tx BBF Tune */ +#define REG_CONFIG0 0x0D0 /* Config0 */ +#define REG_RESISTOR 0x0D1 /* Resistor */ +#define REG_CAPACITOR 0x0D2 /* Capacitor */ +#define REG_LO_CM 0x0D3 /* LO CM */ +#define REG_TX_BBF_TUNE_DIVIDER 0x0D6 /* TX BBF Tune Divider */ +#define REG_TX_BBF_TUNE_MODE 0x0D7 /* TX BBF Tune Mode */ +#define REG_RX_FILTER_COEF_ADDR 0x0F0 /* Rx Filter Coeff Addr */ +#define REG_RX_FILTER_COEF_DATA_1 0x0F1 /* Rx Filter Coeff Data 1 */ +#define REG_RX_FILTER_COEF_DATA_2 0x0F2 /* Rx Filter Coeff Data 2 */ +#define REG_RX_FILTER_COEF_READ_DATA_1 0x0F3 /* Rx Filter Coeff Read Data 1 */ +#define REG_RX_FILTER_COEF_READ_DATA_2 0x0F4 /* Rx Filter Coeff Read Data 2 */ +#define REG_RX_FILTER_CONFIG 0x0F5 /* Rx Filter Config */ +#define REG_RX_FILTER_GAIN 0x0F6 /* Rx Filter Gain */ +#define REG_AGC_CONFIG_1 0x0FA /* AGC Config1 */ +#define REG_AGC_CONFIG_2 0x0FB /* AGC config2 */ +#define REG_AGC_CONFIG_3 0x0FC /* AGC Config3 */ +#define REG_MAX_LMT_FULL_GAIN 0x0FD /* Max LMT/Full Gain */ +#define REG_PEAK_WAIT_TIME 0x0FE /* Peak Wait Time */ +#define REG_DIGITAL_GAIN 0x100 /* Digital Gain */ +#define REG_AGC_LOCK_LEVEL 0x101 /* AGC Lock Level */ +#define REG_ADC_NOISE_CORRECTION_FACTOR 0x102 /* ADC noise Correction Factor */ +#define REG_GAIN_STP_CONFIG1 0x103 /* Gain Step Config1 */ +#define REG_ADC_SMALL_OVERLOAD_THRESH 0x104 /* ADC Small Overload Threshold */ +#define REG_ADC_LARGE_OVERLOAD_THRESH 0x105 /* ADC Large Overload Threshold */ +#define REG_GAIN_STP_CONFIG_2 0x106 /* Gain Step Config 2 */ +#define REG_SMALL_LMT_OVERLOAD_THRESH 0x107 /* Small LMT Overload Threshold */ +#define REG_LARGE_LMT_OVERLOAD_THRESH 0x108 /* Large LMT Overload Threshold */ +#define REG_RX1_MANUAL_LMT_FULL_GAIN 0x109 /* Rx1 Manual LMT/Full Gain */ +#define REG_RX1_MANUAL_LPF_GAIN 0x10A /* Rx1 Manual LPF gain */ +#define REG_RX1_MANUAL_DIGITALFORCED_GAIN 0x10B /* Rx1 Manual Digital/Forced Gain */ +#define REG_RX2_MANUAL_LMT_FULL_GAIN 0x10C /* Rx2 Manual LMT/Full Gain */ +#define REG_RX2_MANUAL_LPF_GAIN 0x10D /* Rx2 Manual LPF Gain */ +#define REG_RX2_MANUAL_DIGITALFORCED_GAIN 0x10E /* Rx2 Manual Digital/Forced Gain */ +#define REG_FAST_CONFIG_1 0x110 /* Config 1 */ +#define REG_FAST_CONFIG_2_SETTLING_DELAY 0x111 /* Config 2 & Settling Delay */ +#define REG_FAST_ENERGY_LOST_THRESH 0x112 /* Energy Lost Threshold */ +#define REG_FAST_STRONGER_SIGNAL_THRESH 0x113 /* Stronger Signal Threshold */ +#define REG_FAST_LOW_POWER_THRESH 0x114 /* Low Power Threshold */ +#define REG_FAST_STRONG_SIGNAL_FREEZE 0x115 /* Strong Signal Freeze */ +#define REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN 0x116 /* Final Over Range and Opt Gain */ +#define REG_FAST_ENERGY_DETECT_COUNT 0x117 /* Energy Detect Count */ +#define REG_FAST_AGCLL_UPPER_LIMIT 0x118 /* AGCLL Upper Limit */ +#define REG_FAST_GAIN_LOCK_EXIT_COUNT 0x119 /* Gain Lock Exit Count */ +#define REG_FAST_INITIAL_LMT_GAIN_LIMIT 0x11A /* Initial LMT Gain Limit */ +#define REG_FAST_INCREMENT_TIME 0x11B /* Increment Time */ +#define REG_AGC_INNER_LOW_THRESH 0x120 /* AGC Inner Low Threshold */ +#define REG_LMT_OVERLOAD_COUNTERS 0x121 /* LMT Overload Counters */ +#define REG_ADC_OVERLOAD_COUNTERS 0x122 /* ADC Overload Counters */ +#define REG_GAIN_STP1 0x123 /* Gain Step1 */ +#define REG_GAIN_UPDATE_COUNTER1 0x124 /* Gain Update Counter1 */ +#define REG_GAIN_UPDATE_COUNTER2 0x125 /* Gain Update Counter2 */ +#define REG_DIGITAL_SAT_COUNTER 0x128 /* Digital Sat Counter */ +#define REG_OUTER_POWER_THRESHS 0x129 /* Outer Power Thresholds */ +#define REG_GAIN_STP_2 0x12A /* Gain Step 2 */ +#define REG_EXT_LNA_HIGH_GAIN 0x12C /* Ext LNA High Gain */ +#define REG_EXT_LNA_LOW_GAIN 0x12D /* Ext LNA Low Gain */ +#define REG_GAIN_TABLE_ADDRESS 0x130 /* Gain Table Address */ +#define REG_GAIN_TABLE_WRITE_DATA1 0x131 /* Gain Table Write Data1 */ +#define REG_GAIN_TABLE_WRITE_DATA2 0x132 /* Gain Table Write Data2 */ +#define REG_GAIN_TABLE_WRITE_DATA3 0x133 /* Gain Table Write Data 3 */ +#define REG_GAIN_TABLE_READ_DATA1 0x134 /* Gain Table Read Data 1 */ +#define REG_GAIN_TABLE_READ_DATA2 0x135 /* Gain Table Read Data 2 */ +#define REG_GAIN_TABLE_READ_DATA3 0x136 /* Gain Table Read Data 3 */ +#define REG_GAIN_TABLE_CONFIG 0x137 /* Gain Table Config */ +#define REG_GM_SUB_TABLE_ADDRESS 0x138 /* Gm Sub Table Address */ +#define REG_GM_SUB_TABLE_GAIN_WRITE 0x139 /* Gm Sub Table Gain Word Write */ +#define REG_GM_SUB_TABLE_BIAS_WRITE 0x13A /* Gm Sub Table Bias Word Write */ +#define REG_GM_SUB_TABLE_CTRL_WRITE 0x13B /* Gm Sub Table Control Word Write */ +#define REG_GM_SUB_TABLE_GAIN_READ 0x13C /* Gm Sub Table Gain Word Read */ +#define REG_GM_SUB_TABLE_BIAS_READ 0x13D /* Gm Sub Table Bias Word Read */ +#define REG_GM_SUB_TABLE_CTRL_READ 0x13E /* Gm Sub Table Control Word Read */ +#define REG_GM_SUB_TABLE_CONFIG 0x13F /* Gm Sub Table Config */ +#define REG_WORD_ADDRESS 0x140 /* Word Address */ +#define REG_GAIN_DIFF_WORDERROR_WRITE 0x141 /* Gain Diff Word/Error Write */ +#define REG_GAIN_ERROR_READ 0x142 /* Gain Error Read */ +#define REG_CONFIG 0x143 /* Config */ +#define REG_LNA_GAIN_DIFF_READ_BACK 0x144 /* LNA Gain Diff Read Back */ +#define REG_MAX_MIXER_CALIBRATION_GAIN_INDEX 0x145 /* Max Mixer Calibration Gain Index */ +#define REG_TEMP_GAIN_COEF 0x146 /* Temp Gain Coefficient */ +#define REG_SETTLE_TIME 0x147 /* Settle Time */ +#define REG_MEASURE_DURATION 0x148 /* Measure Duration */ +#define REG_CAL_TEMP_SENSOR_WORD 0x149 /* Cal Temp sensor word */ +#define REG_MEASURE_DURATION_01 0x150 /* Measure Duration 0&1 */ +#define REG_MEASURE_DURATION_23 0x151 /* Measure Duration 2&3 */ +#define REG_RSSI_WEIGHT_0 0x152 /* RSSI Weight 0 */ +#define REG_RSSI_WEIGHT_1 0x153 /* RSSI Weight 1 */ +#define REG_RSSI_WEIGHT_2 0x154 /* RSSI Weight 2 */ +#define REG_RSSI_WEIGHT_3 0x155 /* RSSI Weight 3 */ +#define REG_RSSI_DELAY 0x156 /* RSSI delay */ +#define REG_RSSI_WAIT_TIME 0x157 /* RSSI wait time */ +#define REG_RSSI_CONFIG 0x158 /* RSSI Config */ +#define REG_ADC_MEASURE_DURATION_01 0x159 /* ADC Measure Duration 0&1 */ +#define REG_ADC_WEIGHT_0 0x15A /* ADC Weight 0 */ +#define REG_ADC_WEIGHT_1 0x15B /* ADC Weight 1 */ +#define REG_DEC_POWER_MEASURE_DURATION_0 0x15C /* Dec Power Measure Duration 0 */ +#define REG_LNA_GAIN 0x15D /* LNA Gain */ +#define REG_CH1_ADC_POWER 0x160 /* CH1 ADC Power */ +#define REG_CH1_RX_FILTER_POWER 0x161 /* CH1 Rx filter Power */ +#define REG_CH2_ADC_POWER 0x162 /* CH2 ADC Power */ +#define REG_CH2_RX_FILTER_POWER 0x163 /* CH2 Rx filter Power */ +#define REG_RX_QUAD_CAL_LEVEL 0x168 /* Rx Quad Cal Level */ +#define REG_CALIBRATION_CONFIG_1 0x169 /* Calibration Config 1 */ +#define REG_CALIBRATION_CONFIG_2 0x16A /* Calibration config2 */ +#define REG_CALIBRATION_CONFIG_3 0x16B /* Calibration config3 */ +#define REG_CALIB_COUNT 0x16C /* Calib count */ +#define REG_SETTLE_COUNT 0x16D /* Settle count */ +#define REG_RX_QUAD_GAIN1 0x16E /* Rx Quad gain1 */ +#define REG_RX_QUAD_GAIN2 0x16F /* Rx Quad gain2 */ +#define REG_RX1_INPUT_A_PHASE_CORR 0x170 /* Rx1 Input A Phase Corr */ +#define REG_RX1_INPUT_A_GAIN_CORR 0x171 /* Rx1 Input A Gain Corr */ +#define REG_RX2_INPUT_A_PHASE_CORR 0x172 /* Rx2 Input A Phase Corr */ +#define REG_RX2_INPUT_A_GAIN_CORR 0x173 /* Rx2 Input A Gain Corr */ +#define REG_RX1_INPUT_A_Q_OFFSET 0x174 /* Rx1 Input A Q" Offset */ +#define REG_RX1_INPUT_A_OFFSETS 0x175 /* Rx1 Input A Offsets */ +#define REG_INPUT_A_OFFSETS_1 0x176 /* Input A Offsets 1 */ +#define REG_RX2_INPUT_A_OFFSETS 0x177 /* Rx2 Input A Offsets */ +#define REG_RX2_INPUT_A_I_OFFSET 0x178 /* Rx2 Input A "I" Offset */ +#define REG_RX1_INPUT_BC_PHASE_CORR 0x179 /* Rx1 Input B&C Phase Corr */ +#define REG_RX1_INPUT_BC_GAIN_CORR 0x17A /* Rx1 Input B&C Gain Corr */ +#define REG_RX2_INPUT_BC_PHASE_CORR 0x17B /* Rx2 Input B&C Phase Corr */ +#define REG_RX2_INPUT_BC_GAIN_CORR 0x17C /* Rx2 Input B&C Gain Corr */ +#define REG_RX1_INPUT_BC_Q_OFFSET 0x17D /* Rx1 Input B&C "Q" Offset */ +#define REG_RX1_INPUT_BC_OFFSETS 0x17E /* Rx1 Input B&C Offsets */ +#define REG_INPUT_BC_OFFSETS_1 0x17F /* Input B&C Offsets 1 */ +#define REG_RX2_INPUT_BC_OFFSETS 0x180 /* Rx2 Input B&C Offsets */ +#define REG_RX2_INPUT_BC_I_OFFSET 0x181 /* Rx2 Input B&C "I" Offset */ +#define REG_FORCE_BITS 0x182 /* Force Bits */ +#define REG_WAIT_COUNT 0x185 /* Wait Count */ +#define REG_RF_DC_OFFSET_COUNT 0x186 /* RF DC Offset Count */ +#define REG_RF_DC_OFFSET_CONFIG_1 0x187 /* RF DC Offset Config1 */ +#define REG_RF_DC_OFFSET_ATTEN 0x188 /* RF DC Offset Attenuation */ +#define REG_INVERT_BITS 0x189 /* Invert Bits */ +#define REG_DC_OFFSET_CONFIG2 0x18B /* DC Offset Config2 */ +#define REG_RF_CAL_GAIN_INDEX 0x18C /* RF Cal Gain Index */ +#define REG_SOI_THRESH 0x18D /* SOI Threshold */ +#define REG_BB_DC_OFFSET_SHIFT 0x190 /* BB DC Offset Shift */ +#define REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT 0x191 /* BB DC Offset Fast Settle Shift */ +#define REG_BB_FAST_SETTLE_DUR 0x192 /* BB Fast Settle Dur */ +#define REG_BB_DC_OFFSET_COUNT 0x193 /* BB DC Offset Count */ +#define REG_BB_DC_OFFSET_ATTEN 0x194 /* BB DC Offset Attenuation */ +#define REG_RX1_BB_DC_WORD_I_MSB 0x19A /* RX1 BB DC word I MSB */ +#define REG_RX1_BB_DC_WORD_I_LSB 0x19B /* RX1 BB DC word I LSB */ +#define REG_RX1_BB_DC_WORD_Q_MSB 0x19C /* RX1 BB DC word Q MSB */ +#define REG_RX1_BB_DC_WORD_Q_LSB 0x19D /* RX1 BB DC word Q LSB */ +#define REG_RX2_BB_DC_WORD_I_MSB 0x19E /* RX2 BB DC word I MSB */ +#define REG_RX2_BB_DC_WORD_I_LSB 0x19F /* RX2 BB DC word I LSB */ +#define REG_RX2_BB_DC_WORD_Q_MSB 0x1A0 /* RX2 BB DC word Q MSB */ +#define REG_RX2_BB_DC_WORD_Q_LSB 0x1A1 /* RX2 BB DC word Q LSB */ +#define REG_BB_TRACK_CORR_WORD_I_MSB 0x1A2 /* BB Track corr word I MSB */ +#define REG_BB_TRACK_CORR_WORD_I_LSB 0x1A3 /* BB Track corr word I LSB */ +#define REG_BB_TRACK_CORR_WORD_Q_MSB 0x1A4 /* BB Track corr word Q MSB */ +#define REG_BB_TRACK_CORR_WORD_Q_LSB 0x1A5 /* BB Track corr word Q LSB */ +#define REG_RX1_RSSI_SYMBOL 0x1A7 /* Rx1 RSSI Symbol */ +#define REG_RX1_RSSI_PREAMBLE 0x1A8 /* Rx1 RSSI preamble */ +#define REG_RX2_RSSI_SYMBOL 0x1A9 /* Rx2 RSSI symbol */ +#define REG_RX2_RSSI_PREAMBLE 0x1AA /* Rx2 RSSI preamble */ +#define REG_SYMBOL_LSB 0x1AB /* Symbol LSB */ +#define REG_PREAMBLE_LSB 0x1AC /* Preamble LSB */ +#define REG_RX_PATH_GAIN_MSB 0x1AD /* Rx Path Gain */ +#define REG_RX_PATH_GAIN_LSB 0x1AE /* Rx Path Gain */ +#define REG_RX_DIFF_LNA_FORCE 0x1B0 /* Rx Diff LNA Force */ +#define REG_RX_LNA_BIAS_COARSE 0x1B1 /* Rx LNA Bias Coarse */ +#define REG_RX_LNA_BIAS_FINE_0 0x1B2 /* Rx LNA Bias Fine 0 */ +#define REG_RX_LNA_BIAS_FINE_1 0x1B3 /* Rx LNA Bias Fine 1 */ +#define REG_RX_MIX_GM_CONFIG 0x1C0 /* Rx Mix Gm Config */ +#define REG_RX1_MIX_GM_FORCE 0x1C1 /* Rx1 Mix Gm Force */ +#define REG_RX1_MIX_GM_BIAS_FORCE 0x1C2 /* Rx1 Mix Gm Bias (Force) */ +#define REG_RX2_MIX_GM_FORCE 0x1C3 /* Rx2 Mix Gm Force */ +#define REG_RX2_MIX_GM_BIAS_FORCE 0x1C4 /* Rx2 Mix Gm Bias (Force) */ +#define REG_INPUT_A_MSBS 0x1C8 /* Input A MSBs */ +#define REG_INPUT_A_RX1_I 0x1C9 /* Input A RX1 I */ +#define REG_INPUT_A_RX1_Q 0x1CA /* Input A RX1 Q */ +#define REG_INPUT_A_RX2_I 0x1CB /* Input A RX2 I */ +#define REG_INPUT_A_RX2_Q 0x1CC /* Input A RX2 Q */ +#define REG_INPUTS_BC_RX1_I 0x1CD /* Inputs B&C RX1 I */ +#define REG_BAND1_RX1_Q 0x1CE /* Band1 RX1 Q */ +#define REG_INPUTS_BC_RX2_I 0x1CF /* Inputs B&C RX2 I */ +#define REG_INPUTS_BC_RX2_Q 0x1D0 /* Inputs B&C RX2 Q */ +#define REG_INPUTS_BC_MSBS 0x1D1 /* Inputs B&C MSBs */ +#define REG_FORCE_OS_DAC 0x1D2 /* Force OS DAC */ +#define REG_RX_MIX_LO_CM 0x1D5 /* Rx Mix LO CM */ +#define REG_RX_CGB_SEG_ENABLE 0x1D6 /* Rx CGB Seg Enable */ +#define REG_RX_MIX_INPUTBIAS 0x1D7 /* Rx Mix Input/Bias */ +#define REG_RX_TIA_CONFIG 0x1DB /* Rx TIA Config */ +#define REG_TIA1_C_LSB 0x1DC /* TIA1 C LSB */ +#define REG_TIA1_C_MSB 0x1DD /* TIA1 C MSB */ +#define REG_TIA2_C_LSB 0x1DE /* TIA2 C LSB */ +#define REG_TIA2_C_MSB 0x1DF /* TIA2 C MSB */ +#define REG_RX1_BBF_R1A 0x1E0 /* Rx1 BBF R1A */ +#define REG_RX2_BBF_R1A 0x1E1 /* Rx2 BBF R1A */ +#define REG_RX1_TUNE_CTRL 0x1E2 /* Rx1 Tune Control */ +#define REG_RX2_TUNE_CTRL 0x1E3 /* Rx2 Tune Control */ +#define REG_RX1_BBF_R5 0x1E4 /* Rx1 BBF R5 */ +#define REG_RX2_BBF_R5 0x1E5 /* Rx2 BBF R5 */ +#define REG_RX_BBF_R2346 0x1E6 /* Rx BBF R2346 */ +#define REG_RX_BBF_C1_MSB 0x1E7 /* Rx BBF C1 MSB */ +#define REG_RX_BBF_C1_LSB 0x1E8 /* Rx BBF C1 LSB */ +#define REG_RX_BBF_C2_MSB 0x1E9 /* Rx BBF C2 MSB */ +#define REG_RX_BBF_C2_LSB 0x1EA /* Rx BBF C2 LSB */ +#define REG_RX_BBF_C3_MSB 0x1EB /* Rx BBF C3 MSB */ +#define REG_RX_BBF_C3_LSB 0x1EC /* Rx BBF C3 LSB */ +#define REG_RX_BBF_CC1_CTR 0x1ED /* Rx BBF CC1 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE0 0x1EE /* Rx BBF Pow Rz Byte0 */ +#define REG_RX_BBF_CC2_CTR 0x1EF /* Rx BBF CC2 Ctr */ +#define REG_RX_BBF_POW_RZ_BYTE1 0x1F0 /* Rx BBF Pow Rz Byte1 */ +#define REG_RX_BBF_CC3_CTR 0x1F1 /* Rx BBF CC3 Ctr */ +#define REG_RX_BBF_R5_TUNE 0x1F2 /* Rx BBF R5 Tune */ +#define REG_RX_BBF_TUNE 0x1F3 /* Rx BBF Tune */ +#define REG_RX1_BBF_MAN_GAIN 0x1F4 /* Rx1 BBF Man Gain */ +#define REG_RX2_BBF_MAN_GAIN 0x1F5 /* Rx2 BBF Man Gain */ +#define REG_RX_BBF_TUNE_DIVIDE 0x1F8 /* RX BBF Tune Divide */ +#define REG_RX_BBF_TUNE_CONFIG 0x1F9 /* RX BBF Tune Config */ +#define REG_POLE_GAIN 0x1FA /* Pole gain */ +#define REG_RX_BBBW_MHZ 0x1FB /* Rx BBBW MHz */ +#define REG_RX_BBBW_KHZ 0x1FC /* Rx BBBW kHz */ +#define REG_FB_DAC_CLK_DELAY1 0x201 /* FB DAC Clk Delay1 */ +#define REG_FB_DAC_CLK_DELAY2 0x202 /* FB DAC Clk Delay2 */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3P 0x203 /* Flash Sample Clk Delay 3p */ +#define REG_FLASH_SAMPLE_CLK_DELAY_3N 0x204 /* Flash Sample Clk Delay 3n */ +#define REG_TEST_MUX_2I 0x205 /* Test MUX 2i */ +#define REG_TEST_MUX_2Q 0x206 /* Test MUX 2q */ +#define REG_INTEGRATOR_1_RESISTANCE 0x207 /* Integrator 1 Resistance */ +#define REG_INTEGRATOR_1_CAPACITANCE 0x208 /* Integrator 1 Capacitance */ +#define REG_INTEGRATOR_23_RESISTANCE 0x209 /* Integrator 23 Resistance */ +#define REG_INTEGRATOR_2_RESISTANCE 0x20A /* Integrator 2 Resistance */ +#define REG_INTEGRATOR_2_CAPACITANCE 0x20B /* Integrator 2 Capacitance */ +#define REG_INTEGRATOR_3_RESISTANCE 0x20C /* Integrator 3 Resistance */ +#define REG_INTEGRATOR_3_CAPACITANCE 0x20D /* Integrator 3 Capacitance */ +#define REG_INTEGRATOR_AMP_CC 0x20E /* Integrator Amp Cc */ +#define REG_INT_1_FB_DAC_NMOS_CURRENT_SOURCE 0x20F /* Int 1 FB DAC NMOS Current Source */ +#define REG_INT_1_FB_DAC_NMOS_CASOADE_BIAS_CURRENT 0x210 /* Int 1 FB DAC NMOS Casoade Bias Current */ +#define REG_INT_1_FB_DAC_PMOS_CURRENT_SOURCE 0x211 /* Int 1 FB DAC PMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CURRENT_SOURCE 0x212 /* Int 2 FB DAC NMOS Current Source */ +#define REG_INT_2_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x213 /* Int 2 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_2_FB_DAC_PMOS_CURRENT_SOURCE 0x214 /* Int 2 FB DAC PMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CURRENT_SOURCE 0x215 /* Int 3 FB DAC NMOS Current Source */ +#define REG_INT_3_FB_DAC_NMOS_CASCODE_BIAS_CURRENT 0x216 /* Int 3 FB DAC NMOS Cascode Bias Current */ +#define REG_INT_3_FB_DAC_PMOS_CURRENT_SOURCE 0x217 /* Int 3 FB DAC PMOS Current Source */ +#define REG_FB_DAC_BIAS_CURRENT 0x218 /* FB DAC Bias Current */ +#define REG_INT_1_1ST_STAGE_CURRENT 0x219 /* Int 1 1st Stage Current */ +#define REG_INT_1_1ST_STAGE_CASCODE_CURRENT 0x21A /* Int 1 1st Stage Cascode Current */ +#define REG_INT_1_2ND_STAGE_CURRENT 0x21B /* Int 1 2nd Stage Current */ +#define REG_INTEGRATOR_2_1ST_STAGE_CURRENT 0x21C /* Integrator 2 1st Stage Current */ +#define REG_INT_2_1ST_STAGE_CASCODE_CURRENT 0x21D /* Int 2 1st Stage Cascode Current */ +#define REG_INT_2_2ND_STAGE_CURRENT 0x21E /* Int 2 2nd Stage Current */ +#define REG_INT_3_1ST_STAGE_CURRENT 0x21F /* Int 3 1st Stage Current */ +#define REG_INT_3_1ST_STAGE_CASCODE_CURRENT 0x220 /* Int 3 1st Stage Cascode Current */ +#define REG_INT_3_2ND_STAGE_CURRENT 0x221 /* Int 3 2nd Stage Current */ +#define REG_FLASH_BIAS_CURRENT 0x222 /* Flash Bias Current */ +#define REG_FLASH_LADDER_BIAS 0x223 /* Flash Ladder Bias */ +#define REG_FLASH_LADDER_CASCODE_CURRENT 0x224 /* Flash Ladder Cascode Current */ +#define REG_FLASH_LADDER_BIAS2 0x225 /* Flash Ladder Bias2 */ +#define REG_RESET 0x226 /* Reset */ +#define REG_RX_PFD_CONFIG 0x230 /* RX PFD Config */ +#define REG_RX_INTEGER_BYTE_0 0x231 /* RX Integer Byte 0 */ +#define REG_RX_INTEGER_BYTE_1 0x232 /* RX Integer Byte 1 */ +#define REG_RX_FRACT_BYTE_0 0x233 /* RX Fractional Byte 0 */ +#define REG_RX_FRACT_BYTE_1 0x234 /* RX Fractional Byte 1 */ +#define REG_RX_FRACT_BYTE_2 0x235 /* RX Fractional Byte 2 */ +#define REG_RX_FORCE_ALC 0x236 /* RX Force ALC */ +#define REG_RX_FORCE_VCO_TUNE_0 0x237 /* RX Force VCO Tune 0 */ +#define REG_RX_FORCE_VCO_TUNE_1 0x238 /* RX Force VCO Tune 1 */ +#define REG_RX_ALC_VARACTOR 0x239 /* RX ALC/Varactor */ +#define REG_RX_VCO_OUTPUT 0x23A /* RX VCO Output */ +#define REG_RX_CP_CURRENT 0x23B /* RX CP Current */ +#define REG_RX_CP_OFFSET 0x23C /* RX CP Offset */ +#define REG_RX_CP_CONFIG 0x23D /* RX CP Config */ +#define REG_RX_LOOP_FILTER_1 0x23E /* RX Loop Filter 1 */ +#define REG_RX_LOOP_FILTER_2 0x23F /* RX Loop Filter 2 */ +#define REG_RX_LOOP_FILTER_3 0x240 /* RX Loop Filter 3 */ +#define REG_RX_DITHERCP_CAL 0x241 /* RX Dither/CP Cal */ +#define REG_RX_VCO_BIAS_1 0x242 /* RX VCO Bias 1 */ +#define REG_RX_CAL_STATUS 0x244 /* RX Cal Status */ +#define REG_RX_VCO_CAL_REF 0x245 /* RX VCO Cal Ref */ +#define REG_RX_VCO_PD_OVERRIDES 0x246 /* RX VCO Pd Overrides */ +#define REG_RX_CP_OVERRANGE_VCO_LOCK 0x247 /* RX CP Over Range/VCO Lock */ +#define REG_RX_VCO_LDO 0x248 /* RX VCO LDO */ +#define REG_RX_VCO_CAL 0x249 /* RX VCO Cal */ +#define REG_RX_LOCK_DETECT_CONFIG 0x24A /* RX Lock Detect Config */ +#define REG_RX_CP_LEVEL_DETECT 0x24B /* RX CP Level Detect */ +#define REG_RX_DSM_SETUP_0 0x24C /* RX DSM Setup 0 */ +#define REG_RX_DSM_SETUP_1 0x24D /* RX DSM Setup 1 */ +#define REG_RX_CORRECTION_WORD0 0x24E /* RX Correction Word0 */ +#define REG_RX_CORRECTION_WORD1 0x24F /* RX Correction Word1 */ +#define REG_RX_VCO_VARACTOR_CTRL_0 0x250 /* RX VCO Varactor Control 0 */ +#define REG_RX_VCO_VARACTOR_CTRL_1 0x251 /* RX VCO Varactor Control 1 */ +#define REG_RX_FAST_LOCK_SETUP 0x25A /* Rx Fast Lock Setup */ +#define REG_RX_FAST_LOCK_SETUP_INIT_DELAY 0x25B /* Rx Fast Lock Setup Init Delay */ +#define REG_RX_FAST_LOCK_PROGRAM_ADDR 0x25C /* Rx Fast Lock Program Addr */ +#define REG_RX_FAST_LOCK_PROGRAM_DATA 0x25D /* Rx Fast Lock Program Data */ +#define REG_RX_FAST_LOCK_PROGRAM_READ 0x25E /* Rx Fast Lock Program Read */ +#define REG_RX_FAST_LOCK_PROGRAM_CTRL 0x25F /* Rx Fast Lock Program Control */ +#define REG_RX_LO_GEN_POWER_MODE 0x261 /* Rx LO Gen Power Mode */ +#define REG_TX_PFD_CONFIG 0x270 /* TX PFD Config */ +#define REG_TX_INTEGER_BYTE_0 0x271 /* TX Integer Byte 0 */ +#define REG_TX_INTEGER_BYTE_1 0x272 /* TX Integer Byte 1 */ +#define REG_TX_FRACT_BYTE_0 0x273 /* TX Fractional Byte 0 */ +#define REG_TX_FRACT_BYTE_1 0x274 /* TX Fractional Byte 1 */ +#define REG_TX_FRACT_BYTE_2 0x275 /* TX Fractional Byte 2 */ +#define REG_TX_FORCE_ALC 0x276 /* TX Force ALC */ +#define REG_TX_FORCE_VCO_TUNE_0 0x277 /* TX Force VCO Tune 0 */ +#define REG_TX_FORCE_VCO_TUNE_1 0x278 /* TX Force VCO Tune 1 */ +#define REG_TX_ALCVARACT_OR 0x279 /* TX ALC/Varact or */ +#define REG_TX_VCO_OUTPUT 0x27A /* TX VCO Output */ +#define REG_TX_CP_CURRENT 0x27B /* TX CP Current */ +#define REG_TX_CP_OFFSET 0x27C /* TX CP Offset */ +#define REG_TX_CP_CONFIG 0x27D /* TX CP Config */ +#define REG_TX_LOOP_FILTER_1 0x27E /* TX Loop Filter 1 */ +#define REG_TX_LOOP_FILTER_2 0x27F /* TX Loop Filter 2 */ +#define REG_TX_LOOP_FILTER_3 0x280 /* TX Loop Filter 3 */ +#define REG_TX_DITHERCP_CAL 0x281 /* TX Dither/CP Cal */ +#define REG_TX_VCO_BIAS_1 0x282 /* TX VCO Bias 1 */ +#define REG_TX_VCO_BIAS_2 0x283 /* TX VCO Bias 2 */ +#define REG_TX_CAL_STATUS 0x284 /* TX Cal Status */ +#define REG_TX_VCO_CAL_REF 0x285 /* TX VCO Cal Ref */ +#define REG_TX_VCO_PD_OVERRIDES 0x286 /* TX VCO Pd Overrides */ +#define REG_TX_CP_OVERRANGE_VCO_LOCK 0x287 /* TX CP Over Range/VCO Lock */ +#define REG_TX_VCO_LDO 0x288 /* TX VCO LDO */ +#define REG_TX_VCO_CAL 0x289 /* TX VCO Cal */ +#define REG_TX_LOCK_DETECT_CONFIG 0x28A /* TX Lock Detect Config */ +#define REG_TX_CP_LEVEL_DETECT 0x28B /* TX CP Level Detect */ +#define REG_TX_DSM_SETUP_0 0x28C /* TX DSM Setup 0 */ +#define REG_TX_DSM_SETUP_1 0x28D /* TX DSM Setup 1 */ +#define REG_TX_CORRECTION_WORD0 0x28E /* TX Correction Word0 */ +#define REG_TX_CORRECTION_WORD1 0x28F /* TX Correction Word1 */ +#define REG_TX_VCO_VARACTOR_CTRL_0 0x290 /* TX VCO Varactor Control 0 */ +#define REG_TX_VCO_VARACTOR_CTRL_1 0x291 /* TX VCO Varactor Control 1 */ +#define REG_DCXO_COARSE_TUNE 0x292 /* DCXO Coarse Tune */ +#define REG_DCXO_FINE_TUNE_HIGH 0x293 /* DCXO Fine Tune2 */ +#define REG_DCXO_FINE_TUNE_LOW 0x294 /* DCXO Fine Tune1 */ +#define REG_DCXO_CONFIG 0x295 /* DCXO Config */ +#define REG_DCXO_TEMPCO_WRITE 0x296 /* DCXO Tempco Write */ +#define REG_DCXO_TEMPCO_READ 0x297 /* DCXO Tempco Read */ +#define REG_DCXO_TEMPCO_ADDR 0x298 /* DCXO Tempco Addr */ +#define REG_DELTA_T_READ 0x299 /* Delta T Read */ +#define REG_TX_FAST_LOCK_SETUP 0x29A /* Tx Fast Lock Setup */ +#define REG_TX_FAST_LOCK_SETUP_INIT_DELAY 0x29B /* Tx Fast Lock Setup Init Delay */ +#define REG_TX_FAST_LOCK_PROGRAM_ADDR 0x29C /* Tx Fast Lock Program Addr */ +#define REG_TX_FAST_LOCK_PROGRAM_DATA 0x29D /* Tx Fast Lock Program Data */ +#define REG_TX_FAST_LOCK_PROGRAM_READ 0x29E /* Tx Fast Lock Program Read */ +#define REG_TX_FAST_LOCK_PROGRAM_CTRL 0x29F /* Tx Fast Lock Program Ctrl */ +#define REG_TX_LO_GEN_POWER_MODE 0x2A1 /* Tx LO Gen Power Mode */ +#define REG_BANDGAP_CONFIG0 0x2A6 /* Bandgap Config0 */ +#define REG_BANDGAP_CONFIG1 0x2A8 /* Bandgap Config1 */ +#define REG_REF_DIVIDE_CONFIG_1 0x2AB /* Ref Divide Config 1 */ +#define REG_REF_DIVIDE_CONFIG_2 0x2AC /* Ref Divide Config 2 */ +#define REG_GAIN_RX1 0x2B0 /* Gain Rx1 */ +#define REG_LPF_GAIN_RX1 0x2B1 /* LPF Gain Rx1 */ +#define REG_DIG_GAIN_RX1 0x2B2 /* Dig gain Rx1 */ +#define REG_FAST_ATTACK_STATE 0x2B3 /* Fast Attack State */ +#define REG_SLOW_LOOP_STATE 0x2B4 /* Slow Loop State */ +#define REG_GAIN_RX2 0x2B5 /* Gain Rx2 */ +#define REG_LPF_GAIN_RX2 0x2B6 /* LPF Gain Rx2 */ +#define REG_DIG_GAIN_RX2 0x2B7 /* Dig Gain Rx2 */ +#define REG_OVRG_SIGS_RX1 0x2B8 /* Ovrg Sigs Rx1 */ +#define REG_OVRG_SIGS_RX2 0x2B9 /* Ovrg Sigs Rx2 */ +#define REG_CTRL 0x3DF /* Control */ +#define REG_BIST_CONFIG 0x3F4 /* BIST Config */ +#define REG_OBSERVE_CONFIG 0x3F5 /* Observe Config */ +#define REG_BIST_AND_DATA_PORT_TEST_CONFIG 0x3F6 /* BIST and Data Port Test Config */ +#define REG_DAC_TEST_0 0x3FC /* DAC Test 0 */ +#define REG_DAC_TEST_1 0x3FD /* DAC Test 1 */ +#define REG_DAC_TEST_2 0x3FE /* DAC Test 2 */ + +/* +* REG_SPI_CONF +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define WIRE3_SPI (1 << 6) /* 3-Wire SPI */ +#define LSB_FIRST (1 << 5) /* LSB First */ +#define _LSB_FIRST (1 << 2) /* LSB First */ +#define _WIRE3_SPI (1 << 1) /* 3-Wire SPI */ +#define _SOFT_RESET (1 << 0) /* Soft reset */ + +/* +* REG_MULTICHIP_SYNC_AND_TX_MON_CTRL +*/ +#define TX2_MONITOR_ENABLE (1 << 6) /* Tx2 Monitor Enable */ +#define TX1_MONITOR_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define MCS_RF_ENABLE (1 << 3) /* MCS RF Enable */ +#define MCS_BBPLL_ENABLE (1 << 2) /* MCS BBPLL enable */ +#define MCS_DIGITAL_CLK_ENABLE (1 << 1) /* MCS Digital CLK Enable */ +#define MCS_BB_ENABLE (1 << 0) /* MCS BB Enable */ + +/* +* REG_TX_ENABLE_FILTER_CTRL +*/ +#define THB2_EN (1 << 3) /* THB2 Enable */ +#define THB1_EN (1 << 2) /* THB1 Enable */ +#define TX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Tx channel Enable<1:0> */ +#define THB3_ENABLE_INTERP(x) (((x) & 0x3) << 4) /* THB3 Enable & Interp<1:0> */ +#define TX_FIR_ENABLE_INTERPOLATION(x) (((x) & 0x3) << 0) /* Tx FIR Enable & Interpolation<1:0> */ +#define TX_1 1 +#define TX_2 2 +#define TX_ENABLE 1 +#define TX_DISABLE 0 + +/* +* REG_RX_ENABLE_FILTER_CTRL +*/ +#define RHB2_EN (1 << 3) /* RHB2 Enable */ +#define RHB1_EN (1 << 2) /* RHB1 Enable */ +#define RX_CHANNEL_ENABLE(x) (((x) & 0x3) << 6) /* Rx channel Enable<1:0> */ +#define DEC3_ENABLE_DECIMATION(x) (((x) & 0x3) << 4) /* DEC3 Enable & Decimation<1:0> */ +#define RX_FIR_ENABLE_DECIMATION(x) (((x) & 0x3) << 0) /* Rx FIR Enable & Decimation<1:0> */ +#define RX_1 1 +#define RX_2 2 +#define RX_ENABLE 1 +#define RX_DISABLE 0 + +/* +* REG_INPUT_SELECT +*/ +#define TX_OUTPUT (1 << 6) /* TX Output */ +#define RX_INPUT(x) (((x) & 0x3F) << 0) /* RX Input <5:0> */ + +/* +* REG_RFPLL_DIVIDERS +*/ +#define TX_VCO_DIVIDER(x) (((x) & 0xF) << 4) /* TX VCO Divider<3:0> */ +#define RX_VCO_DIVIDER(x) (((x) & 0xF) << 0) /* RX VCO Divider<3:0> */ + +/* +* REG_RX_CLOCK_DATA_DELAY +*/ +#define DATA_CLK_DELAY(x) (((x) & 0xF) << 4) /* DATA_CLK Delay<3:0> */ +#define RX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Rx Data Delay <3:0> */ + +/* +* REG_TX_CLOCK_DATA_DELAY +*/ +#define FB_CLK_DELAY(x) (((x) & 0xF) << 4) /* FB_CLK Delay<3:0> */ +#define TX_DATA_DELAY(x) (((x) & 0xF) << 0) /* Tx Data Delay <3:0> */ + +/* +* REG_CLOCK_ENABLE +*/ +#define XO_BYPASS (1 << 4) /* XO Bypass */ +#define DIGITAL_POWER_UP (1 << 2) /* Digital Power Up */ +#define CLOCK_ENABLE_DFLT (1 << 1) /* Set to 1 */ +#define BBPLL_ENABLE (1 << 0) /* BBPLL Enable */ + +/* +* REG_BBPLL +*/ +#define CLKOUT_ENABLE (1 << 4) /* CLKOUT Enable */ +#define DAC_CLK_DIV2 (1 << 3) /* DAC Clk div2 */ +#define CLKOUT_SELECT(x) (((x) & 0x7) << 5) /* CLKOUT Select<2:0> */ +#define BBPLL_DIVIDER(x) (((x) & 0x7) << 0) /* BBPLL Divider <2:0> */ + +/* +* REG_START_TEMP_READING +*/ +#define START_TEMP_READING (1 << 0) /* Start Temp Reading */ + +/* +* REG_TEMP_SENSE2 +*/ +#define TEMP_SENSE_PERIODIC_ENABLE (1 << 0) /* Temp Sense Periodic Enable */ +#define MEASUREMENT_TIME_INTERVAL(x) (((x) & 0x7F) << 1) /* Measurement Time Interval<6:0> */ + +/* +* REG_TEMP_SENSOR_CONFIG +*/ +#define TEMP_SENSOR_DECIMATION(x) (((x) & 0x7) << 0) /* Temp Sensor Decimation<2:0> */ + +/* +* REG_PARALLEL_PORT_CONF_1 +*/ +#define PP_TX_SWAP_IQ (1 << 7) /* PP Tx Swap IQ */ +#define PP_RX_SWAP_IQ (1 << 6) /* PP Rx Swap IQ */ +#define TX_CHANNEL_SWAP (1 << 5) /* Tx Channel swap */ +#define RX_CHANNEL_SWAP (1 << 4) /* Rx Channel swap */ +#define RX_FRAME_PULSE_MODE (1 << 3) /* Rx Frame Pulse Mode */ +#define R2T2_TIMING (1 << 2) /* 2R2T Timing */ +#define INVERT_DATA_BUS (1 << 1) /* Invert data bus */ +#define INVERT_DATA_CLK (1 << 0) /* Invert DATA CLK */ + +/* +* REG_PARALLEL_PORT_CONF_2 +*/ +#define FDD_ALT_WORD_ORDER (1 << 7) /* FDD Alt Word Order */ +#define INVERT_RX1 (1 << 6) /* Invert Rx1 */ +#define INVERT_RX2 (1 << 5) /* Invert Rx2 */ +#define INVERT_TX1 (1 << 4) /* Invert Tx1 */ +#define INVERT_TX2 (1 << 3) /* Invert Tx2 */ +#define INVERT_RX_FRAME (1 << 2) /* Invert Rx Frame */ +#define DELAY_RX_DATA(x) (((x) & 0x3) << 0) /* Delay Rx Data<1:0> */ + +/* +* REG_PARALLEL_PORT_CONF_3 +*/ +#define FDD_RX_RATE_2TX_RATE (1 << 7) /* FDD Rx Rate = 2*Tx Rate */ +#define SWAP_PORTS (1 << 6) /* Swap Ports */ +#define SINGLE_DATA_RATE (1 << 5) /* Single Data Rate */ +#define LVDS_MODE (1 << 4) /* LVDS Mode */ +#define HALF_DUPLEX_MODE (1 << 3) /* Half Duplex Mode */ +#define SINGLE_PORT_MODE (1 << 2) /* Single Port Mode */ +#define FULL_PORT (1 << 1) /* Full Port */ +#define FULL_DUPLEX_SWAP_BITS (1 << 0) /* Full Duplex Swap Bits */ + +/* +* REG_ENSM_MODE +*/ +#define FDD_MODE (1 << 0) /* FDD Mode */ + +/* +* REG_ENSM_CONFIG_1 +*/ +#define ENABLE_RX_DATA_PORT_FOR_CAL (1 << 7) /* Enable Rx Data Port for Cal */ +#define FORCE_RX_ON (1 << 6) /* Force Rx On */ +#define FORCE_TX_ON (1 << 5) /* Force Tx On */ +#define ENABLE_ENSM_PIN_CTRL (1 << 4) /* Enable ENSM Pin Control */ +#define LEVEL_MODE (1 << 3) /* Level Mode */ +#define FORCE_ALERT_STATE (1 << 2) /* Force Alert State */ +#define AUTO_GAIN_LOCK (1 << 1) /* Auto Gain Lock */ +#define TO_ALERT (1 << 0) /* To Alert */ + +/* +* REG_ENSM_CONFIG_2 +*/ +#define FDD_EXTERNAL_CTRL_ENABLE (1 << 7) /* FDD External Control Enable */ +#define POWER_DOWN_RX_SYNTH (1 << 6) /* Power Down Rx Synth */ +#define POWER_DOWN_TX_SYNTH (1 << 5) /* Power Down Tx Synth */ +#define TXNRX_SPI_CTRL (1 << 4) /* TXNRX SPI Control */ +#define SYNTH_ENABLE_PIN_CTRL_MODE (1 << 3) /* Synth Enable Pin Control Mode */ +#define DUAL_SYNTH_MODE (1 << 2) /* Dual Synth Mode */ +#define RX_SYNTH_READY_MASK (1 << 1) /* Rx Synth Ready Mask */ +#define TX_SYNTH_READY_MASK (1 << 0) /* Tx Synth Ready Mask */ + +/* +* REG_CALIBRATION_CTRL +*/ +#define RX_BB_TUNE_CAL (1 << 7) /* Rx BB Tune */ +#define TX_BB_TUNE_CAL (1 << 6) /* Tx BB Tune */ +#define RX_QUAD_CAL (1 << 5) /* Rx Quad Cal */ +#define TX_QUAD_CAL (1 << 4) /* Tx Quad Cal */ +#define RX_GAIN_STEP_CAL (1 << 3) /* Rx Gain Step Cal */ +#define TXMON_CAL (1 << 2) +#define RFDC_CAL (1 << 1) /* DC Cal RF Start */ +#define BBDC_CAL (1 << 0) /* DC cal BB Start */ + + +/* +* REG_STATE +*/ +#define CALIBRATION_SEQUENCE_STATE(x) (((x) & 0xF) << 4) /* Calibration Sequence State<3:0> */ +#define ENSM_STATE(x) (((x) & 0xF) << 0) /* ENSM State<3:0> */ +#define ENSM_STATE_SLEEP_WAIT 0x0 +#define ENSM_STATE_ALERT 0x5 +#define ENSM_STATE_TX 0x6 +#define ENSM_STATE_TX_FLUSH 0x7 +#define ENSM_STATE_RX 0x8 +#define ENSM_STATE_RX_FLUSH 0x9 +#define ENSM_STATE_FDD 0xA +#define ENSM_STATE_FDD_FLUSH 0xB +#define ENSM_STATE_INVALID 0xFF +#define ENSM_STATE_SLEEP 0x80 + +/* +* REG_AUXDAC_2_WORD +*/ +#define AUXDAC_2_WORD_MSB(x) (((x) & 0x3F) << 2) /* AuxDAC 2 Word<9:2> */ +#define AUXDAC_1_WORD(x) (((x) & 0x3) << 0) /* AuxDAC 1 Word <1:0> */ + +/* +* REG_AUXDAC_1_CONFIG +*/ +#define COMP_CTRL_1 (1 << 5) /* Comp Ctrl 1 */ +#define AUXDAC1_STP_FACTOR (1 << 4) /* AuxDAC1 Step Factor */ +#define AUXDAC_1_VREF(x) (((x) & 0x3) << 2) /* AuxDAC 1 Vref<1:0> */ +#define AUXDAC_1_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXDAC_2_CONFIG +*/ +#define COMP_CTRL_2 (1 << 5) /* Comp Ctrl 2 */ +#define AUXDAC2_STP_FACTOR (1 << 4) /* AuxDAC2 Step Factor */ +#define AUXDAC_2_VREF(x) (((x) & 0xF) << 2) /* AuxDAC 2 Vref<1:0> */ +#define AUXDAC_2_WORD_LSB(x) (((x) & 0x3) << 0) /* AuxDAC 2 Word <1:0> */ + +/* +* REG_AUXADC_CLOCK_DIVIDER +*/ +#define AUXADC_CLOCK_DIVIDER(x) (((x) & 0x3F) << 0) /* AuxADC Clock Divider<5:0> */ + +/* +* REG_AUXADC_CONFIG +*/ +#define AUXADC_POWER_DOWN (1 << 0) /* AuxADC Power Down */ +#define AUX_ADC_DECIMATION(x) (((x) & 0x7) << 1) /* Aux ADC Decimation<2:0> */ + +/* +* REG_AUXADC_LSB +*/ +#define AUXADC_WORD_LSB(x) (((x) & 0xF) << 0) /* AuxADC Word LSB<3:0> */ + +/* +* REG_AUTO_GPO +*/ +#define GPO_ENABLE_AUTO_RX(x) (((x) & 0xF) << 4) /* GPO Enable Auto Rx<3:0> */ +#define GPO_ENABLE_AUTO_TX(x) (((x) & 0xF) << 0) /* GPO Enable Auto Tx<3:0> */ + +/* +* REG_AGC_ATTACK_DELAY +*/ +#define INVERT_BYPASSED_LNA_POLARITY (1 << 6) /* Invert Bypassed LNA Polarity */ +#define AGC_ATTACK_DELAY(x) (((x) & 0x3F) << 0) /* AGC Attack Delay<5:0> */ + +/* +* REG_AUXDAC_ENABLE_CTRL +*/ +#define AUXDAC_MANUAL_BAR(x) (((x) & 0x3) << 6) /* AuxDac Manual Bar<1:0> */ +#define AUXDAC_AUTO_TX_BAR(x) (((x) & 0x3) << 4) /* AuxDAC Auto Tx Bar<1:0> */ +#define AUXDAC_AUTO_RX_BAR(x) (((x) & 0x3) << 2) /* AuxDAC Auto Rx Bar<1:0> */ +#define AUXDAC_INIT_BAR(x) (((x) & 0x3) << 0) /* AuxDAC Init Bar<1:0> */ + +/* +* REG_EXTERNAL_LNA_CTRL +*/ +#define AUXDAC_MANUAL_SELECT (1 << 7) /* AuxDAC Manual Select */ +#define EXTERNAL_LNA2_CTRL (1 << 6) /* External LNA2 control */ +#define EXTERNAL_LNA1_CTRL (1 << 5) /* External LNA1 control */ +#define GPO_MANUAL_SELECT (1 << 4) /* GPO manual select */ +#define OPEN(x) (((x) & 0xF) << 0) /* Open<3:0> */ + +/* +* REG_GPO_FORCE_AND_INIT +*/ +#define GPO_MANUAL_CTRL(x) (((x) & 0xF) << 4) /* GPO Manual Control<3:0> */ +#define GPO_INIT_STATE(x) (((x) & 0xF) << 0) /* GPO Init State<3:0> */ + +/* +* REG_CTRL_OUTPUT_ENABLE +*/ +#define EN_CTRL7 (1 << 7) /* En ctrl7 */ +#define EN_CTRL6 (1 << 6) /* En ctrl6 */ +#define EN_CTRL5 (1 << 5) /* En ctrl5 */ +#define EN_CTRL4 (1 << 4) /* En ctrl4 */ +#define EN_CTRL3 (1 << 3) /* En ctrl3 */ +#define EN_CTRL2 (1 << 2) /* En ctrl2 */ +#define EN_CTRL1 (1 << 1) /* En ctrl1 */ +#define EN_CTRL0 (1 << 0) /* En ctrl0 */ + +/* +* REG_PRODUCT_ID +*/ +#define PRODUCT_ID_MASK 0xF8 +#define PRODUCT_ID_9361 0x08 +#define REV_MASK 0x07 + +/* +* REG_REFERENCE_CLOCK_CYCLES +*/ +#define REFERENCE_CLOCK_CYCLES_PER_US(x) (((x) & 0x7F) << 0) /* Reference Clock Cycles per us<6:0> */ + +/* +* REG_DIGITAL_IO_CTRL +*/ +#define CLK_OUT_DRIVE (1 << 7) /* CLK Out Drive */ +#define DATACLK_DRIVE (1 << 6) /* DATACLK drive */ +#define DATA_PORT_DRIVE (1 << 2) /* Data Port Drive */ +#define DATACLK_SLEW(x) (((x) & 0x3) << 4) /* DATACLK slew <1:0> */ +#define DATA_PORT_SLEW(x) (((x) & 0x3) << 0) /* Data Port Slew<1:0> */ + +/* +* REG_LVDS_BIAS_CTRL +*/ +#define RX_ON_CHIP_TERM (1 << 5) /* Rx On Chip Term */ +#define LVDS_BYPASS_BIAS_R (1 << 4) /* Bypass Bias R */ +#define LVDS_TX_LO_VCM (1 << 3) /* LVDS Tx LO VCM */ +#define CLK_OUT_SLEW(x) (((x) & 0x3) << 6) /* CLK Out Slew<1:0> */ +#define LVDS_BIAS(x) (((x) & 0x7) << 0) /* LVDS Bias <2:0> */ + +/* +* REG_SDM_CTRL_1 +*/ +#define INIT_BB_FO_CAL (1 << 2) /* Init BB FO CAL */ +#define BBPLL_RESET_BAR (1 << 0) /* BBPLL Reset Bar */ + +/* +* REG_CLOCK_CTRL +*/ +#define REF_FREQ_SCALER(x) (((x) & 0x3) << 0) /* Ref Frequency Scaler */ + +/* +* REG_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_CP_BLEED_CURRENT +*/ +#define MCS_REFCLK_SCALE_EN (1 << 7) /* MCS refclk Scale En */ + +/* +* REG_LOOP_FILTER_1 +*/ +#define C1_WORD(x) (((x) & 0x7) << 5) /* C1 Word<2:0> */ +#define R1_WORD(x) (((x) & 0x1F) << 0) /* R1 Word<4:0> */ + +/* +* REG_LOOP_FILTER_2 +*/ +#define R2_WORD (1 << 7) /* R2 Word<0> */ +#define C2_WORD(x) (((x) & 0x1F) << 2) /* C2 Word<4:0> */ +#define C1_WORD_LSB(x) (((x) & 0x3) << 0) /* C1 Word<4:3> */ + +/* +* REG_LOOP_FILTER_3 +*/ +#define BYPASS_C3 (1 << 7) /* Bypass C3 */ +#define BYPASS_R2 (1 << 6) /* Bypass R2 */ +#define C3_WORD(x) (((x) & 0xF) << 2) /* C3 Word<3:0> */ +#define R2_WORD_LSB(x) (((x) & 0x3) << 0) /* R2 Word<2:1> */ + +/* +* REG_VCO_CTRL +*/ +#define FREQ_CAL_ENABLE (1 << 7) /* Freq Cal Enable */ +#define FREQ_CAL_RESET (1 << 4) /* Freq Cal Reset */ +#define FREQ_CAL_COUNT_LENGTH(x) (((x) & 0x3) << 5) /* Freq Cal Count Length<1:0> */ + +/* +* REG_SDM_CTRL +*/ +#define CAL_CLOCK_DIV_4 (1 << 4) /* Cal Clock div 4 */ + +/* +* REG_RX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define RX_LO_POWER_DOWN (1 << 4) /* Rx LO Power Down */ +#define RX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Rx Synth VCO ALC Power Down */ +#define RX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Rx Synth PTAT Power Down */ +#define RX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Rx Synth VCO Power Down */ +#define RX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Rx Synth VCO LDO Power Down */ + +/* +* REG_TX_SYNTH_POWER_DOWN_OVERRIDE +*/ +#define TX_LO_POWER_DOWN (1 << 4) /* Tx LO Power Down */ +#define TX_SYNTH_VCO_ALC_POWER_DOWN (1 << 3) /* Tx Synth VCO ALC Power Down */ +#define TX_SYNTH_PTAT_POWER_DOWN (1 << 2) /* Tx Synth PTAT Power Down */ +#define TX_SYNTH_VCO_POWER_DOWN (1 << 1) /* Tx Synth VCO Power Down */ +#define TX_SYNTH_VCO_LDO_POWER_DOWN (1 << 0) /* Tx Synth VCO LDO Power Down */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define RX_OFFSET_DAC_CGIN_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx Offset DAC CGin Power Down<1:0> */ +#define RX_LMT_OVERLOAD_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx LMT Overload Power Down<1:0> */ +#define RX_MIXER_GM_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Gm Power Down<1:0> */ +#define RX_CGB_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx CGB Power Down<1:0> */ + +/* +* REG_RX_ANALOG_POWER_DOWN_OVERRIDE_2 +*/ +#define RX_BBF_POWER_DOWN(x) (((x) & 0x3) << 6) /* Rx BBF Power Down<1:0> */ +#define RX_TIA_POWER_DOWN(x) (((x) & 0x3) << 4) /* Rx TIA Power Down<1:0> */ +#define RX_MIXER_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Mixer Power Down<1:0> */ +#define RX_OFFSET_DAC_CGOUT_POWER_DOWN(x) (((x) & 0x3) << 0) /* Rx Offset DAC CGOut Power Down<1:0> */ + +/* +* REG_TX_ANALOG_POWER_DOWN_OVERRIDE_1 +*/ +#define TX_SECONDARY_FILTER_POWER_DOWN(x) (((x) & 0x3) << 6) /* Tx Secondary Filter Power Down<1:0> */ +#define TX_BBF_POWER_DOWN(x) (((x) & 0x3) << 4) /* Tx BBF Power Down<1:0> */ +#define TX_DAC_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx DAC Power Down<1:0> */ +#define TX_DAC_BIAS_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx DAC Bias Power Down<1:0> */ + +/* +* REG_ANALOG_POWER_DOWN_OVERRIDE +*/ +#define RX_EXT_VCO_BUFFER_POWER_DOWN (1 << 5) /* Rx Ext VCO Buffer Power Down */ +#define TX_EXT_VCO_BUFFER_POWER_DOWN (1 << 4) /* Tx Ext VCO Buffer Power Down */ +#define TX_MONITOR_POWER_DOWN(x) (((x) & 0x3) << 2) /* Tx Monitor Power Down<1:0> */ +#define TX_UPCONVERTER_POWER_DOWN(x) (((x) & 0x3) << 0) /* Tx Upconverter Power Down<1:0> */ + +/* +* REG_MISC_POWER_DOWN_OVERRIDE +*/ +#define RX_LNA_POWER_DOWN (1 << 6) /* Rx LNA Power Down */ +#define DCXO_POWER_DOWN (1 << 1) /* DCXO Power Down */ +#define MASTER_BIAS_POWER_DOWN (1 << 0) /* Master Bias Power Down */ +#define RX_CALIBRATION_POWER_DOWN(x) (((x) & 0x3) << 2) /* Rx Calibration Power Down<1:0> */ + +/* +* REG_CH_1_OVERFLOW +*/ +#define BBPLL_LOCK (1 << 7) /* BBPLL Lock */ +#define CH_1_INT3 (1 << 6) /* CH 1 INT3 */ +#define CH1_HB3 (1 << 5) /* CH1 HB3 */ +#define CH1_HB2 (1 << 4) /* CH1 HB2 */ +#define CH1_QEC (1 << 3) /* CH1 QEC */ +#define CH1_HB1 (1 << 2) /* CH1 HB1 */ +#define CH1_TFIR (1 << 1) /* CH1 TFIR */ +#define CH1_RFIR (1 << 0) /* CH1 RFIR */ + +/* +* REG_CH_2_OVERFLOW +*/ +#define CH2_INT3 (1 << 6) /* CH2 INT3 */ +#define CH2_HB3 (1 << 5) /* CH2 HB3 */ +#define CH2_HB2 (1 << 4) /* CH2 HB2 */ +#define CH2_QEC (1 << 3) /* CH2 QEC */ +#define CH2_HB1 (1 << 2) /* CH2 HB1 */ +#define CH2_TFIR (1 << 1) /* CH2 TFIR */ +#define CH2_RFIR (1 << 0) /* CH2 RFIR */ + +/* +* REG_TX_FILTER_CONF +*/ +#define TX_FIR_GAIN_6DB (1 << 0) /* Filter Gain */ +#define FIR_START_CLK (1 << 1) /* Start Tx/Rx Clock */ +#define FIR_WRITE (1 << 2) /* Write Tx/Rx */ +#define FIR_SELECT(x) (((x) & 0x3) << 3) /* Select Tx/Rx CH<1:0> */ +#define FIR_NUM_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps<2:0> */ + +/* +* REG_TX_MON_LOW_GAIN +*/ +#define TX_MON_TRACK (1 << 5) /* Tx Mon Track */ +#define TX_MON_LOW_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon Low Gain<4:0> */ + +/* +* REG_TX_MON_HIGH_GAIN +*/ +#define TX_MON_HIGH_GAIN(x) (((x) & 0x1F) << 0) /* Tx Mon High Gain<4:0> */ + +/* +* REG_TX_LEVEL_THRESH +*/ +#define TX_LEVEL_THRESH(x) (((x) & 0x3F) << 2) /* Tx Level Threshold<5:0> */ +#define TX_MON_DELAY_COUNTER(x) (((x) & 0x3) << 0) /* Tx Mon Delay Counter<9:8> */ + +/* +* REG_TX_RSSI_LSB +*/ +#define TX_RSSI_2 (1 << 1) /* Tx RSSI 2<0> */ +#define TX_RSSI_1 (1 << 0) /* TX RSSI 1<0> */ + +/* +* REG_TPM_MODE_ENABLE +*/ +#define TX2_MON_ENABLE (1 << 7) /* Tx2 Monitor Enable */ +#define TX1_MON_ENABLE (1 << 5) /* Tx1 Monitor Enable */ +#define ONE_SHOT_MODE (1 << 6) /* One Shot Mode */ +#define TX_MON_DURATION(x) (((x) & 0xF) << 0) /* Tx Mon Duration<3:0> */ + +/* +* REG_TX_MON_1_CONFIG +*/ +#define TX_MON_1_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 1 LO CM<5:0> */ +#define TX_MON_1_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 1 Gain<1:0> */ + +/* +* REG_TX_MON_2_CONFIG +*/ +#define TX_MON_2_LO_CM(x) (((x) & 0x3F) << 2) /* Tx Mon 2 LO CM<5:0> */ +#define TX_MON_2_GAIN(x) (((x) & 0x3) << 0) /* Tx Mon 2 Gain<1:0> */ + +/* +* REG_TX1_ATTEN_1 +*/ +#define TX_1_ATTEN (1 << 0) /* Tx 1 Atten <8> */ + +/* +* REG_TX2_ATTEN_1 +*/ +#define TX_2_ATTEN (1 << 0) /* Tx 2 Atten <8> */ + +/* +* REG_TX_ATTEN_OFFSET +*/ +#define MASK_CLR_ATTEN_UPDATE (1 << 6) /* Mask Clr Atten Update */ +#define TX_ATTEN_OFFSET(x) (((x) & 0x3F) << 0) /* Tx Atten Offset<5:0> */ + +/* +* REG_TX1_DIG_ATTEN +*/ +#define SEL_TX1_TX2 (1 << 6) /* Sel Tx1 & Ttx2 */ + +/* +* REG_TX2_DIG_ATTEN +*/ +#define IMMEDIATELY_UPDATE_TPC_ATTEN (1 << 6) /* Immediately Update TPC Atten */ + +/* +* REG_TX1_SYMBOL_ATTEN +*/ +#define TX_1_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 1 Symbol Attenuation<6:0> */ + +/* +* REG_TX2_SYMBOL_ATTEN +*/ +#define TX_2_SYMBOL_ATTEN(x) (((x) & 0x7F) << 0) /* Tx 2 Symbol Attenuation<6:0> */ + +/* +* REG_TX_SYMBOL_ATTEN_CONFIG +*/ +#define USE_TX1_PIN_SYMBOL_ATTEN (1 << 3) /* Use Tx1 Pin & Symbol Atten */ +#define USE_CTRL_IN_FOR_SYMBOL_ATTEN (1 << 1) /* Use CTRL IN for symbol Atten */ +#define ENABLE_SYMBOL_ATTEN (1 << 0) /* Enable Symbol Atten */ + +/* +* REG_TX_FORCE_BITS +*/ +#define FORCE_OUT_2_TX2_OFFSET (1 << 7) /* Force Out 2 Tx2 Offset */ +#define FORCE_OUT_2_TX1_OFFSET (1 << 6) /* Force Out 2 Tx1 Offset */ +#define FORCE_OUT_2_TX2_PHASE_GAIN (1 << 5) /* Force Out 2 Tx2 Phase & Gain */ +#define FORCE_OUT_2_TX1_PHASE_GAIN (1 << 4) /* Force Out 2 Tx1 Phase & Gain */ +#define FORCE_OUT_1_TX2_OFFSET (1 << 3) /* Force Out 1 Tx2 Offset */ +#define FORCE_OUT_1_TX1_OFFSET (1 << 2) /* Force Out 1 Tx1 Offset */ +#define FORCE_OUT_1_TX2_PHASE_GAIN (1 << 1) /* Force Out 1 Tx2 Phase & Gain */ +#define FORCE_OUT_1_TX1_PHASE_GAIN (1 << 0) /* Force Out 1 Tx1 Phase & Gain */ + +/* +* REG_QUAD_CAL_NCO_FREQ_PHASE_OFFSET +*/ +#define RX_NCO_FREQ(x) (((x) & 0x3) << 5) /* Rx NCO Frequency<1:0> */ +#define RX_NCO_PHASE_OFFSET(x) (((x) & 0x1F) << 0) /* Rx NCO Phase Offset<4:0> */ + +/* +* REG_QUAD_CAL_CTRL +*/ +#define FREE_RUN_ENABLE (1 << 7) /* Free Run Enable */ +#define SETTLE_MAIN_ENABLE (1 << 6) /* Settle Main Enable */ +#define DC_OFFSET_ENABLE (1 << 5) /* DC Offset Enable */ +#define GAIN_ENABLE (1 << 4) /* Gain Enable */ +#define PHASE_ENABLE (1 << 3) /* Phase Enable */ +#define QUAD_CAL_SOFT_RESET (1 << 2) /* Quad Cal Soft Reset */ +#define M_DECIM(x) (((x) & 0x3) << 0) /* M<1:0> */ + +/* +* REG_KEXP_1 +*/ +#define KEXP_TX(x) (((x) & 0x3) << 6) /* Kexp Tx<1:0> */ +#define KEXP_TX_COMP(x) (((x) & 0x3) << 4) /* Kexp Tx_comp <1:0> */ +#define KEXP_DC_I(x) (((x) & 0x3) << 2) /* Kexp DC I <1:0> */ +#define KEXP_DC_Q(x) (((x) & 0x3) << 0) /* Kexp DC Q <1:0> */ + +/* +* REG_KEXP_2 +*/ +#define INVERT_I_DATA (1 << 5) /* Invert I data */ +#define INVERT_Q_DATA (1 << 4) /* Invert Q data */ +#define TX_NCO_FREQ(x) (((x) & 0x3) << 6) /* Tx NCO frequency<1:0> */ +#define KEXP_PHASE(x) (((x) & 0x3) << 2) /* Kexp Phase <1:0> */ +#define KEXP_AMP(x) (((x) & 0x3) << 0) /* Kexp Amp <1:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX1 +*/ +#define TX1_LO_CONV (1 << 1) /* Tx1 LO Conv */ +#define TX1_SSB_CONV (1 << 0) /* Tx1 SSB Conv */ +#define TX1_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx1 Convergence Count<5:0> */ + +/* +* REG_QUAD_CAL_STATUS_TX2 +*/ +#define TX2_LO_CONV (1 << 1) /* Tx2 LO Conv */ +#define TX2_SSB_CONV (1 << 0) /* Tx2 SSB Conv */ +#define TX2_CONVERGENCE_COUNT(x) (((x) & 0x3F) << 2) /* Tx2 Convergence Count<5:0> */ + +/* +* REG_TX_QUAD_FULL_LMT_GAIN +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* RX Full table/LMT table gain<6:0> */ + +/* +* REG_SQUARER_CONFIG +*/ +#define GM_STAGE_TIME_CON_OVERRIDE (1 << 5) /* Gm Stage Time Con Override */ +#define GM_STAGE_MV_HP_POLE (1 << 4) /* Gm Stage MV HP Pole */ +#define GM_STAGE_LOWER_CM (1 << 3) /* Gm Stage Lower CM */ +#define BYPASS_BIAS_R (1 << 0) /* Bypass Bias R */ +#define VBIAS_CTRL(x) (((x) & 0x3) << 1) /* Vbias Control<1:0> */ + +/* +* REG_THRESH_ACCUM +*/ +#define THRESH_ACCUMULATOR(x) (((x) & 0xF) << 0) /* Threshold Accumulator<3:0> */ + +/* +* REG_TX_QUAD_LPF_GAIN +*/ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* RX LPF gain<4:0> */ + +/* +* REG_TXDAC_VDS_I +*/ +#define TXDAC_VDS_I(x) (((x) & 0x3F) << 0) /* TxDAC Vds I<5:0> */ + +/* +* REG_TXDAC_VDS_Q +*/ +#define TXDAC_VDS_Q(x) (((x) & 0x3F) << 0) /* TxDAC Vds Q<5:0> */ + +/* +* REG_TXDAC_GN_I +*/ +#define TXDAC_GN_I(x) (((x) & 0x3F) << 0) /* txDAC_gn_I<5:0> */ + +/* +* REG_TXDAC_GN_Q +*/ +#define TXDAC_GN_Q(x) (((x) & 0x3F) << 0) /* txDAC_gn_Q<5:0> */ + +/* +* REG_TXBBF_OPAMP_A +*/ +#define OPAMPA_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpA Output Bias<1:0> */ +#define OPAMPA_RZ(x) (((x) & 0x3) << 3) /* OpAmpA RZ<1:0> */ +#define OPAMP_A_CC(x) (((x) & 0x7) << 0) /* OpAmp A CC<2:0> */ + +/* +* REG_TXBBF_OPAMP_B +*/ +#define OPAMPB_OUTPUT_BIAS(x) (((x) & 0x3) << 5) /* OpAmpB Output Bias<1:0> */ +#define OPAMPB_RZ(x) (((x) & 0x3) << 3) /* OpAmpB RZ<1:0> */ +#define OPAMP_B_CC(x) (((x) & 0x7) << 0) /* OpAmp B CC<2:0> */ + +/* +* REG_TX_BBF_R1 +*/ +#define OVERRIDE_ENABLE (1 << 7) /* Override enable */ +#define R1(x) (((x) & 0x1F) << 0) /* R1<4:0> */ + +/* +* REG_TX_BBF_R2 +*/ +#define R2(x) (((x) & 0x1F) << 0) /* R2<4:0> */ + +/* +* REG_TX_BBF_R3 +*/ +#define R3(x) (((x) & 0x1F) << 0) /* R3<4:0> */ + +/* +* REG_TX_BBF_R4 +*/ +#define R4(x) (((x) & 0x1F) << 0) /* R4<4:0> */ + +/* +* REG_TX_BBF_RP +*/ +#define RP(x) (((x) & 0x1F) << 0) /* Rp<4:0> */ + +/* +* REG_TX_BBF_C1 +*/ +#define C1(x) (((x) & 0x3F) << 0) /* C1<5:0> */ + +/* +* REG_TX_BBF_C2 +*/ +#define C2(x) (((x) & 0x3F) << 0) /* C2<5:0> */ + +/* +* REG_TX_BBF_CP +*/ +#define CP(x) (((x) & 0x3F) << 0) /* Cp<5:0> */ + +/* +* REG_TX_TUNE_CTRL +*/ +#define PD_TUNE (1 << 2) /* PD Tune */ +#define TUNER_RESAMPLE (1 << 1) /* Tuner Resample */ +#define TUNER_RESAMPLE_PHASE (1 << 0) /* Tuner Resample Phase */ +#define TUNE_CTRL(x) (((x) & 0x3) << 5) /* Tune Control<1:0> */ + +/* +* REG_TX_BBF_R2B +*/ +#define TX_BBF_BYPASS_BIAS_R (1 << 7) /* Bypass Bias R */ +#define R2B_OVR (1 << 5) /* R2b Ovr */ +#define R2B(x) (((x) & 0x1F) << 0) /* R2b<4:0> */ + +/* +* REG_TX_BBF_TUNE +*/ +#define BBF1_COMP_I (1 << 3) /* BBF1 Comp I */ +#define BBF1_COMP_Q (1 << 2) /* BBF1 Comp Q */ +#define BBF2_COMP_I (1 << 1) /* BBF2 Comp I */ +#define BBF2_COMP_Q (1 << 0) /* BBF2 Comp Q */ + +/* +* REG_CONFIG0 +*/ +#define BIAS(x) (((x) & 0x3) << 6) /* Bias<1:0> */ +#define RGM(x) (((x) & 0x3) << 4) /* Rgm<1:0> */ +#define CC(x) (((x) & 0x3) << 2) /* Cc<1:0> */ +#define AMPBIAS(x) (((x) & 0x3) << 0) /* AmpBias<1:0> */ + +/* +* REG_RESISTOR +*/ +#define RESISTOR(x) (((x) & 0xF) << 0) /* Resistor<3:0> */ + +/* +* REG_CAPACITOR +*/ +#define CAPACITOR(x) (((x) & 0x3F) << 0) /* Capacitor<5:0> */ + +/* +* REG_LO_CM +*/ +#define LO_COMMON_MODE(x) (((x) & 0x3) << 5) /* LO Common Mode<1:0> */ + +/* +* REG_TX_BBF_TUNE_MODE +*/ +#define EVALTIME (1 << 4) /* EvalTime */ +#define TX_BBF_TUNE_DIVIDER (1 << 0) /* TX BBF Tune Divider<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask<1:0> */ +#define TUNER_MODE(x) (((x) & 0x7) << 1) /* Tuner Mode<2:0> */ + +/* +* REG_RX_FILTER_CONFIG +*/ +#define WRITE_RX (1 << 2) /* Write Rx */ +#define START_RX_CLOCK (1 << 1) /* Start Rx Clock */ +#define NUMBER_OF_TAPS(x) (((x) & 0x7) << 5) /* Number of Taps */ +#define SELECT_RX_CH(x) (((x) & 0x3) << 3) /* Select Rx Ch<1:0> */ + +/* +* REG_RX_FILTER_GAIN +*/ +#define FILTER_GAIN(x) (((x) & 0x3) << 0) /* Filter gain<1:0> */ + +/* +* REG_AGC_CONFIG_1 +*/ +#define DEC_PWR_FOR_LOW_PWR (1 << 7) /* Dec Pwr for Low Pwr */ +#define DEC_PWR_FOR_LOCK_LEVEL (1 << 6) /* Dec Pwr for Lock Level */ +#define DEC_PWR_FOR_GAIN_LOCK_EXIT (1 << 5) /* Dec Pwr for Gain Lock Exit */ +#define SLOW_ATTACK_HYBRID_MODE (1 << 4) /* Slow Attack Hybrid Mode */ +#define RX2_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 2) /* Rx 2 Gain Control Setup<1:0> */ +#define RX1_GAIN_CTRL_SETUP(x) (((x) & 0x3) << 0) /* Rx 1 Gain Control Setup<1:0> */ +#define RX_GAIN_CTL_MASK 0x03 +#define RX2_GAIN_CTRL_SHIFT 2 +#define RX1_GAIN_CTRL_SHIFT 0 +#define RX_GAIN_CTL_MGC 0x00 +#define RX_GAIN_CTL_AGC_FAST_ATK 0x01 +#define RX_GAIN_CTL_AGC_SLOW_ATK 0x02 +#define RX_GAIN_CTL_AGC_SLOW_ATK_HYBD 0x03 + +/* +* REG_AGC_CONFIG_2 +*/ +#define AGC_SOFT_RESET (1 << 7) /* Soft Reset */ +#define AGC_GAIN_UNLOCK_CTRL (1 << 6) /* Gain Unlock Control */ +#define AGC_USE_FULL_GAIN_TABLE (1 << 3) /* Use Full Gain Table */ +#define DIG_GAIN_EN (1 << 2) /* Enable Digital Gain */ +#define MAN_GAIN_CTRL_RX2 (1 << 1) /* Manual Gain Control Rx 2 */ +#define MAN_GAIN_CTRL_RX1 (1 << 0) /* Manual Gain Control Rx 1 */ + +/* +* REG_AGC_CONFIG_3 +*/ +#define INCDEC_LMT_GAIN (1 << 4) /* Inc/Dec LMT Gain */ +#define USE_AGC_FOR_LMTLPF_GAIN (1 << 3) /* Use AGC for LMT/LPF Gain */ +#define MANUAL_INCR_STEP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Incr Gain Step Size<2:0> */ +#define ADC_OVERRANGE_SAMPLE_SIZE(x) (((x) & 0x7) << 0) /* ADC Overrange Sample Size<2:0> */ + +/* +* REG_MAX_LMT_FULL_GAIN +*/ +#define MAXIMUM_FULL_TABLELMT_TABLE_INDEX(x) (((x) & 0x7F) << 0) /* Maximum Full Table/LMT Table Index<6:0> */ + +/* +* REG_PEAK_WAIT_TIME +*/ +#define MANUAL_CTRL_IN_DECR_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Manual (CTRL_IN) Decr Gain Step Size<2:0> */ +#define PEAK_OVERLOAD_WAIT_TIME(x) (((x) & 0x1F) << 0) /* Peak Overload Wait Time<4:0> */ + +/* +* REG_DIGITAL_GAIN +*/ +#define DIG_GAIN_STP_SIZE(x) (((x) & 0x7) << 5) /* Dig Gain Step Size<2:0> */ +#define MAXIMUM_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Maximum Digital Gain<4:0> */ + +/* +* REG_AGC_LOCK_LEVEL +*/ +#define ENABLE_DIG_SAT_OVRG (1 << 7) /* Enable Dig Sat Ovrg */ +#define AGC_LOCK_LEVEL_FAST_AGC_INNER_HIGH_THRESH_SLOW(x) (((x) & 0x7F) << 0) /* AGC Lock Level (Fast)/ AGC Inner High Threshold (Slow) <6:0> */ + +/* +* REG_GAIN_STP_CONFIG1 +*/ +#define LMT_DETECTOR_SETTLING_TIME(x) (((x) & 0x7) << 5) /* LMT Detector Settling Time<2:0> */ +#define DEC_STP_SIZE_FOR_LARGE_LMT_OVERLOAD(x) (((x) & 0x7) << 2) /* Dec Step Size for: Large LMT Overload/ Full Table Case #3 <2:0> */ +#define ADC_NOISE_CORRECTION_FACTOR(x) (((x) & 0x3) << 0) /* ADC Noise Correction Factor<1:0> */ + +/* +* REG_GAIN_STP_CONFIG_2 +*/ +#define DECREMENT_STP_SIZE_FOR_SMALL_LPF_GAIN_CHANGE(x) (((x) & 0x7) << 4) /* Fast Attack Only. Decrement Step Size for: Small LPF Gain Change / Full Table Case #2 <2:0> */ +#define LARGE_LPF_GAIN_STEP(x) (((x) & 0xF) << 0) /* Decrement Step Size for: Large LPF Gain Change / Full Table Case #1<3:0> */ + +/* +* REG_SMALL_LMT_OVERLOAD_THRESH +*/ +#define FORCE_PD_RESET_RX2 (1 << 7) /* Force PD Reset Rx2 */ +#define FORCE_PD_RESET_RX1 (1 << 6) /* Force PD Reset Rx1 */ +#define SMALL_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Small LMT Overload Threshold<5:0> */ + +/* +* REG_LARGE_LMT_OVERLOAD_THRESH +*/ +#define LARGE_LMT_OVERLOAD_THRESH(x) (((x) & 0x3F) << 0) /* Large LMT Overload Threshold<5:0> */ + +/* +* REG_RX1_MANUAL_LMT_FULL_GAIN +*/ +#define POWER_MEAS_IN_STATE_5_MSB (1 << 7) /* Power Meas in State 5 <3> */ +#define RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx1 Manual Full table/LMT table Gain Index<6:0> */ +#define RX_FULL_TBL_IDX_MASK RX1_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(~0) + +/* +* REG_RX1_MANUAL_LPF_GAIN +*/ +#define POWER_MEAS_IN_STATE_5(x) (((x) & 0x7) << 5) /* Power Meas in State 5<2:0> */ +#define RX1_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual LPF Gain <4:0> */ +#define RX_LPF_IDX_MASK RX1_MANUAL_LPF_GAIN(~0) + +/* +* REG_RX1_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX1_DIGITAL_GAIN (1 << 5) /* Force Rx1 Digital Gain */ +#define RX1_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx1 Manual/Forced Digital Gain<4:0> */ +#define RX_DIGITAL_IDX_MASK RX1_MANUALFORCED_DIGITAL_GAIN(~0) +/* +* REG_RX2_MANUAL_LMT_FULL_GAIN +*/ +#define RX2_MANUAL_FULL_TABLE_LMT_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Rx2 Manual Full table/ LMT table Gain Index<6:0> */ + +/* +* REG_RX2_MANUAL_LPF_GAIN +*/ +#define RX2_MANUAL_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual LPF Gain<4:0> */ + +/* +* REG_RX2_MANUAL_DIGITALFORCED_GAIN +*/ +#define FORCE_RX2_DIGITAL_GAIN (1 << 5) /* Force Rx2 Digital Gain */ +#define RX2_MANUALFORCED_DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Rx2 Manual/Forced Digital Gain<4:0> */ + +/* +* REG_FAST_CONFIG_1 +*/ +#define ENABLE_GAIN_INC_AFTER_GAIN_LOCK (1 << 7) /* Enable Gain Inc after Gain Lock */ +#define GOTO_OPT_GAIN_IF_ENERGY_LOST_OR_EN_AGC_HIGH (1 << 6) /* Goto Opt Gain if Energy Lost or EN_AGC High */ +#define GOTO_SET_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Set Gain if EN_AGC High */ +#define GOTO_SET_GAIN_IF_EXIT_RX_STATE (1 << 4) /* Goto Set Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_ENERGY_LOST (1 << 3) /* Don't Unlock Gain if Energy Lost */ +#define GOTO_OPTIMIZED_GAIN_IF_EXIT_RX_STATE (1 << 2) /* Goto Optimized Gain if Exit Rx State */ +#define DONT_UNLOCK_GAIN_IF_LG_ADC_OR_LMT_OVRG (1 << 1) /* Don't Unlock Gain If Lg ADC or LMT Ovrg */ +#define ENABLE_INCR_GAIN (1 << 0) /* Enable Incr Gain */ + +/* +* REG_FAST_CONFIG_2_SETTLING_DELAY +*/ +#define USE_LAST_LOCK_LEVEL_FOR_SET_GAIN (1 << 7) /* Use Last Lock Level for Set Gain */ +#define ENABLE_LMT_GAIN_INC_FOR_LOCK_LEVEL (1 << 6) /* Enable LMT Gain Inc for Lock Level */ +#define GOTO_MAX_GAIN_OR_OPT_GAIN_IF_EN_AGC_HIGH (1 << 5) /* Goto Max Gain or Opt Gain if EN_AGC High */ +#define SETTLING_DELAY(x) (((x) & 0x1F) << 0) /* Settling Delay<4:0> */ + +/* +* REG_FAST_ENERGY_LOST_THRESH +*/ +#define POST_LOCK_LEVEL_STP_SIZE_FOR_LPF_TABLE_FULL_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step Size for: LPF Table/ Full Table <1:0> */ +#define ENERGY_LOST_THRESH(x) (((x) & 0x3F) << 0) /* Energy lost threshold<5:0> */ + +/* +* REG_FAST_STRONGER_SIGNAL_THRESH +*/ +#define POST_LOCK_LEVEL_STP_FOR_LMT_TABLE(x) (((x) & 0x3) << 6) /* Post Lock Level Step for LMT Table <1:0> */ +#define STRONGER_SIGNAL_THRESH(x) (((x) & 0x3F) << 0) /* Stronger Signal Threshold<5:0> */ + +/* +* REG_FAST_LOW_POWER_THRESH +*/ +#define DONT_UNLOCK_GAIN_IF_ADC_OVRG (1 << 7) /* Don't unlock gain if ADC Ovrg */ +#define LOW_POWER_THRESH(x) (((x) & 0x7F) << 0) /* Low Power Threshold<6:0> */ + +/* +* REG_FAST_STRONG_SIGNAL_FREEZE +*/ +#define DONT_UNLOCK_GAIN_IF_STRONGER_SIGNAL (1 << 7) /* Don't unlock gain if Stronger Signal */ + +/* +* REG_FAST_FINAL_OVER_RANGE_AND_OPT_GAIN +*/ +#define FINAL_OVER_RANGE_COUNT(x) (((x) & 0x7) << 5) /* Final Over Range Count<2:0> */ +#define OPTIMIZE_GAIN_OFFSET(x) (((x) & 0xF) << 0) /* Optimize Gain Offset<3:0> */ + +/* +* REG_FAST_ENERGY_DETECT_COUNT +*/ +#define INCREMENT_GAIN_STP_LPFLMT(x) (((x) & 0x7) << 5) /* Increment Gain Step (LPF/LMT)<2:0> */ +#define ENERGY_DETECT_COUNT(x) (((x) & 0x1F) << 0) /* Energy Detect count<4:0> */ + +/* +* REG_FAST_AGCLL_UPPER_LIMIT +*/ +#define AGCLL_MAX_INCREASE(x) (((x) & 0x3F) << 0) /* AGCLL Max Increase<5:0> */ + +/* +* REG_FAST_GAIN_LOCK_EXIT_COUNT +*/ +#define GAIN_LOCK_EXIT_COUNT(x) (((x) & 0x3F) << 0) /* Gain Lock Exit Count<5:0> */ + +/* +* REG_FAST_INITIAL_LMT_GAIN_LIMIT +*/ +#define INITIAL_LMT_GAIN_LIMIT(x) (((x) & 0x7F) << 0) /* Initial LMT Gain Limit<6:0> */ + +/* +* REG_AGC_INNER_LOW_THRESH +*/ +#define PREVENT_GAIN_INC (1 << 7) /* Prevent Gain Inc */ +#define AGC_INNER_LOW_THRESH(x) (((x) & 0x7F) << 0) /* AGC Inner Low Threshold<6:0> */ + +/* +* REG_LMT_OVERLOAD_COUNTERS +*/ +#define LARGE_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large LMT Overload Exceeded Counter<3:0> */ +#define SMALL_LMT_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small LMT Overload Exceeded Counter<3:0> */ + +/* +* REG_ADC_OVERLOAD_COUNTERS +*/ +#define LARGE_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 4) /* Large ADC Overload Exceeded Counter<3:0> */ +#define SMALL_ADC_OVERLOAD_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Small ADC Overload Exceeded Counter<3:0> */ + +/* +* REG_GAIN_STP1 +*/ +#define IMMED_GAIN_CHANGE_IF_LG_LMT_OVERLOAD (1 << 7) /* Immed. Gain Change if Lg LMT Overload */ +#define IMMED_GAIN_CHANGE_IF_LG_ADC_OVERLOAD (1 << 3) /* Immed. Gain Change if Lg ADC Overload */ +#define AGC_INNER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 4) /* AGC Inner High Threshold Exceeded Step Size<2:0> */ +#define AGC_INNER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0x7) << 0) /* AGC Inner Low Threshold Exceeded Step Size<2:0> */ + +/* +* REG_DIGITAL_SAT_COUNTER +*/ +#define DOUBLE_GAIN_COUNTER (1 << 5) /* Double Gain Counter */ +#define ENABLE_SYNC_FOR_GAIN_COUNTER (1 << 4) /* Enable Sync for Gain Counter */ +#define DIG_SATURATION_EXED_COUNTER(x) (((x) & 0xF) << 0) /* Dig Saturation Exceeded Counter<3:0> */ + +/* +* REG_OUTER_POWER_THRESHS +*/ +#define AGC_OUTER_HIGH_THRESH(x) (((x) & 0xF) << 4) /* AGC Outer High Threshold<3:0> */ +#define AGC_OUTER_LOW_THRESH(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold<3:0> */ + +/* +* REG_GAIN_STP_2 +*/ +#define AGC_OUTER_HIGH_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 4) /* AGC outer High Threshold Exceeded Step Size<3:0> */ +#define AGC_OUTER_LOW_THRESH_EXED_STP_SIZE(x) (((x) & 0xF) << 0) /* AGC Outer Low Threshold Exceeded Step Size<3:0> */ + +/* +* REG_EXT_LNA_HIGH_GAIN +*/ +#define EXT_LNA_HIGH_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA High Gain<5:0> */ + +/* +* REG_EXT_LNA_LOW_GAIN +*/ +#define EXT_LNA_LOW_GAIN(x) (((x) & 0x3F) << 0) /* Ext LNA Low Gain<5:0> */ + +/* +* REG_GAIN_TABLE_ADDRESS +*/ +#define GAIN_TABLE_ADDRESS(x) (((x) & 0x7F) << 0) /* Gain Table Address<6:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA1 +*/ +#define EXT_LNA_CTRL (1 << 7) /* Ext LNA Ctrl */ +#define LNA_GAIN(x) (((x) & 0x3) << 5) /* LNA Gain <1:0> */ +#define MIXER_GM_GAIN(x) (((x) & 0x1F) << 0) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA2 +*/ +#define TIA_GAIN (1 << 5) /* TIA Gain */ +#define LPF_GAIN(x) (((x) & 0x1F) << 0) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_WRITE_DATA_3 +*/ +#define RF_DC_CAL (1 << 5) /* RF DC Cal */ +#define DIGITAL_GAIN(x) (((x) & 0x1F) << 0) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_1 +*/ +#define TO_LNA_GAIN(x) (((x) >> 5) & 0x3) /* LNA Gain <1:0> */ +#define TO_MIXER_GM_GAIN(x) (((x) >> 0) & 0x1F) /* Mixer Gm Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_2 +*/ +#define TO_LPF_GAIN(x) (((x) >> 0) & 0x1F) /* LPF Gain <4:0> */ + +/* +* REG_GAIN_TABLE_READ_DATA_3 +*/ +#define TO_DIGITAL_GAIN(x) (((x) >> 0) & 0x1F) /* Digital Gain <4:0> */ + +/* +* REG_GAIN_TABLE_CONFIG +*/ +#define WRITE_GAIN_TABLE (1 << 2) /* Write Gain Table */ +#define START_GAIN_TABLE_CLOCK (1 << 1) /* Start Gain Table Clock */ +#define RECEIVER_SELECT(x) (((x) & 0x3) << 3) /* Receiver Select<1:0> */ +#define GT_RX1 1 +#define GT_RX2 2 + + +/* +* REG_GM_SUB_TABLE_GAIN_WRITE +*/ +#define GM_SUB_TABLE_GAIN_WRITE(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Write<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_WRITE +*/ +#define GM_SUB_TABLE_BIAS_WRITE(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Write<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_WRITE +*/ +#define GM_SUB_TABLE_CTRL_WRITE(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Write<5:0> */ + +/* +* REG_GM_SUB_TABLE_GAIN_READ +*/ +#define GM_SUB_TABLE_GAIN_READ(x) (((x) & 0x7F) << 0) /* Gm Sub Table Gain Word Read<6:0> */ + +/* +* REG_GM_SUB_TABLE_BIAS_READ +*/ +#define GM_SUB_TABLE_BIAS_READ(x) (((x) & 0x1F) << 0) /* Gm Sub Table Bias Word Read<4:0> */ + +/* +* REG_GM_SUB_TABLE_CTRL_READ +*/ +#define GM_SUB_TABLE_CTRL_READ(x) (((x) & 0x3F) << 0) /* Gm Sub Table Control Word Read<5:0> */ + +/* +* REG_GM_SUB_TABLE_CONFIG +*/ +#define WRITE_GM_SUB_TABLE (1 << 2) /* Write Gm Sub Table */ +#define START_GM_SUB_TABLE_CLOCK (1 << 1) /* Start Gm Sub Table Clock */ + +/* +* REG_GAIN_DIFF_WORDERROR_WRITE +*/ +#define CALIB_TABLE_GAIN_DIFFERROR_WORD(x) (((x) & 0x3F) << 0) /* Calib Table Gain Diff/Error Word<5:0> */ + +/* +* REG_GAIN_ERROR_READ +*/ +#define CALIB_TABLE_GAIN_ERROR(x) (((x) & 0x1F) << 0) /* Calib Table Gain Error<4:0> */ + +/* +* REG_CONFIG +*/ +#define READ_SELECT (1 << 4) /* Read Select */ +#define WRITE_MIXER_ERROR_TABLE (1 << 3) /* Write Mixer Error Table */ +#define WRITE_LNA_ERROR_TABLE (1 << 2) /* Write LNA Error Table */ +#define WRITE_LNA_GAIN_DIFF (1 << 1) /* Write LNA Gain Diff */ +#define START_CALIB_TABLE_CLOCK (1 << 0) /* Start Calib Table Clock */ +#define CALIB_TABLE_SELECT(x) (((x) & 0x3) << 5) /* Calib Table Select<1:0> */ + +/* +* REG_LNA_GAIN_DIFF_READ_BACK +*/ +#define LNA_CALIB_TABLE_GAIN_DIFFERENCE_WORD(x) (((x) & 0x3F) << 0) /* LNA Calib Table Gain Difference Word<5:0> */ + +/* +* REG_MAX_MIXER_CALIBRATION_GAIN_INDEX +*/ +#define MAX_MIXER_CALIBRATION_GAIN_INDEX(x) (((x) & 0x1F) << 0) /* Max Mixer Calibration Gain Index<4:0> */ + +/* +* REG_SETTLE_TIME +*/ +#define ENABLE_DIG_GAIN_CORR (1 << 7) /* Enable Dig Gain Corr */ +#define FORCE_TEMP_SENSOR_FOR_CAL (1 << 6) /* Force Temp Sensor for Cal */ +#define SETTLE_TIME(x) (((x) & 0x3F) << 0) /* Settle Time<5:0> */ + +/* +* REG_MEASURE_DURATION +*/ +#define GAIN_CAL_MEAS_DURATION(x) (((x) & 0xF) << 0) /* Gain Cal Meas Duration<3:0> */ + +/* +* REG_MEASURE_DURATION_01 +*/ +#define MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* Measurement duration 1 <3:0> */ +#define MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* Measurement duration 0 <3:0> */ + +/* +* REG_MEASURE_DURATION_23 +*/ +#define MEASUREMENT_DURATION_3(x) (((x) & 0xF) << 4) /* Measurement duration 3 <3:0> */ +#define MEASUREMENT_DURATION_2(x) (((x) & 0xF) << 0) /* Measurement duration 2 <3:0> */ + +/* +* REG_RSSI_CONFIG +*/ +#define START_RSSI_MEAS (1 << 5) /* Start RSSI Meas (Mode 4) */ +#define ENABLE_ADC_POWER_MEAS (1 << 1) /* Enable ADC Power Meas. */ +#define DEFAULT_RSSI_MEAS_MODE (1 << 0) /* Default RSSI Meas Mode */ +#define RFIR_FOR_RSSI_MEASUREMENT(x) (((x) & 0x3) << 6) /* RFIR for RSSI measurement<1:0> */ +#define RSSI_MODE_SELECT(x) (((x) & 0x7) << 2) /* RSSI Mode Select<2:0> */ + +/* +* REG_ADC_MEASURE_DURATION_01 +*/ +#define ADC_POWER_MEASUREMENT_DURATION_1(x) (((x) & 0xF) << 4) /* ADC Power Measurement Duration 1<3:0> */ +#define ADC_POWER_MEASUREMENT_DURATION_0(x) (((x) & 0xF) << 0) /* ADC Power Measurement Duration 0 <3:0> */ + +/* +* REG_DEC_POWER_MEASURE_DURATION_0 +*/ +#define USE_HB3_OUT_FOR_ADC_PWR_MEAS (1 << 7) /* Use HB3 Out for ADC Pwr Meas */ +#define USE_HB1_OUT_FOR_DEC_PWR_MEAS (1 << 6) /* Use HB1 Out for Dec pwr Meas */ +#define ENABLE_DEC_PWR_MEAS (1 << 5) /* Enable Dec Pwr Meas */ +#define DEFAULT_MODE_ADC_POWER (1 << 4) /* Default Mode ADC Power */ +#define DEC_POWER_MEASUREMENT_DURATION(x) (((x) & 0xF) << 0) /* Dec Power Measurement Duration <3:0> */ + +/* +* REG_LNA_GAIN +*/ +#define DB_GAIN_READBACK_CHANNEL (1 << 0) /* dB Gain Read-back Channel */ +#define MAX_LNA_GAIN(x) (((x) & 0x7F) << 1) /* Max LNA Gain<6:0> */ + +/* +* REG_RX_QUAD_CAL_LEVEL +*/ +#define RX_QUAD_CAL_LEVEL(x) (((x) & 0xF) << 0) /* Rx Quad Cal Level <3 :0> */ + +/* +* REG_CALIBRATION_CONFIG_1 +*/ +#define ENABLE_PHASE_CORR (1 << 7) /* Enable Phase Corr */ +#define ENABLE_GAIN_CORR (1 << 6) /* Enable Gain Corr */ +#define USE_SETTLE_COUNT_FOR_DC_CAL_WAIT (1 << 5) /* Use Settle Count for DC Cal Wait */ +#define FIXED_DC_CAL_WAIT_TIME (1 << 4) /* Fixed DC Cal Wait Time */ +#define FREE_RUN_MODE (1 << 3) /* Free Run Mode */ +#define ENABLE_CORR_WORD_DECIMATION (1 << 2) /* Enable Corr Word Decimation */ +#define ENABLE_TRACKING_MODE_CH2 (1 << 1) /* Enable Tracking Mode CH2 */ +#define ENABLE_TRACKING_MODE_CH1 (1 << 0) /* Enable Tracking Mode CH1 */ + +/* +* REG_CALIBRATION_CONFIG_2 +*/ +#define SOFT_RESET (1 << 7) /* Soft Reset */ +#define CALIBRATION_CONFIG2_DFLT (0x3 << 5) /* Must be 2'b11 */ +#define K_EXP_PHASE(x) (((x) & 0x1F) << 0) /* K exp Phase<4:0> */ + +/* +* REG_CALIBRATION_CONFIG_3 +*/ +#define PREVENT_POS_LOOP_GAIN (1 << 7) /* Prevent Pos Loop Gain */ +#define K_EXP_AMPLITUDE(x) (((x) & 0x1F) << 0) /* K exp Amplitude<4:0> */ + +/* +* REG_RX_QUAD_GAIN1 +*/ +#define RX_FULL_TABLELMT_TABLE_GAIN(x) (((x) & 0x7F) << 0) /* Rx Full table/LMT table gain<6:0> */ + +/* +* REG_RX_QUAD_GAIN2 +*/ +#define CORRECTION_WORD_DECIMATION_M(x) (((x) & 0x7) << 5) /* Correction Word Decimation M<2:0> */ +#define RX_LPF_GAIN(x) (((x) & 0x1F) << 0) /* Rx LPF gain<4:0> */ + +/* +* REG_RX1_INPUT_A_OFFSETS +*/ +#define RX1_INPUT_A_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input A "I" DC Offset<5:0> */ +#define RX1_INPUT_A_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input A "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_A_OFFSETS_1 +*/ +#define RX2_INPUT_A_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input A "Q" DC Offset<3:0> */ +#define RX1_INPUT_A_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input A "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_A_OFFSETS +*/ +#define RX2_INPUT_A_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input A "I" DC Offset<1:0> */ +#define RX2_INPUT_A_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input A "Q" DC Offset<9:4> */ + +/* +* REG_RX1_INPUT_BC_OFFSETS +*/ +#define RX1_INPUT_BC_I_DC_OFFSET_LSB(x) (((x) & 0x3F) << 2) /* Rx1 Input B&C "I" DC Offset<5:0> */ +#define RX1_INPUT_BC_Q_DC_OFFSET(x) (((x) & 0x3) << 0) /* Rx1 Input B&C "Q" DC Offset<9:8> */ + +/* +* REG_INPUT_BC_OFFSETS_1 +*/ +#define RX2_INPUT_BC_Q_DC_OFFSET_LSB(x) (((x) & 0xF) << 4) /* Rx2 Input B&C "Q" DC Offset<3:0> */ +#define RX1_INPUT_BC_I_DC_OFFSET_MSB(x) (((x) & 0xF) << 0) /* Rx1 Input B&C "I" DC Offset<9:6> */ + +/* +* REG_RX2_INPUT_BC_OFFSETS +*/ +#define RX2_INPUT_BC_I_DC_OFFSET(x) (((x) & 0x3) << 6) /* Rx2 Input B&C "I" DC Offset<1:0> */ +#define RX2_INPUT_BC_Q_DC_OFFSET_MSB(x) (((x) & 0x3F) << 0) /* Rx2 Input B&C "Q" DC Offset<9:4> */ + +/* +* REG_FORCE_BITS +*/ +#define RX2_INPUT_BC_FORCE_OFFSET (1 << 7) /* Rx2 Input B&C Force offset */ +#define RX1_INPUT_BC_FORCE_OFFSET (1 << 6) /* Rx1 Input B&C Force offset */ +#define RX2_INPUT_BC_FORCE_PHGAIN (1 << 5) /* Rx2 Input B&C Force Ph/Gain */ +#define RX1_INPUT_BC_FORCE_PHGAIN (1 << 4) /* Rx1 Input B&C Force Ph/Gain */ +#define RX2_INPUT_A_FORCE_OFFSET (1 << 3) /* Rx2 Input A Force offset */ +#define RX1_INPUT_A_FORCE_OFFSET (1 << 2) /* Rx1 Input A Force offset */ +#define RX2_INPUT_A_FORCE_PHGAIN (1 << 1) /* Rx2 Input A Force Ph/Gain */ +#define RX1_INPUT_A_FORCE_PHGAIN (1 << 0) /* Rx1 Input A Force Ph/Gain */ + +/* +* REG_RF_DC_OFFSET_CONFIG_1 +*/ +#define DAC_FS(x) (((x) & 0x3) << 4) /* DAC FS<1:0> */ +#define RF_DC_CALIBRATION_COUNT(x) (((x) & 0xF) << 0) /* RF DC Calibration Count<3:0> */ + +/* +* REG_RF_DC_OFFSET_ATTEN +*/ +#define RF_DC_OFFSET_TABLE_UPDATE_COUNT(x) (((x) & 0x7) << 5) /* RF DC Offset Table Update Count<2:0> */ +#define RF_DC_OFFSET_ATTEN(x) (((x) & 0x1F) << 0) /* RF DC Offset Attenuation<4:0> */ + +/* +* REG_INVERT_BITS +*/ +#define INVERT_RX2_RF_DC_CGIN_WORD (1 << 7) /* Invert Rx2 RF DC CGin Word */ +#define INVERT_RX1_RF_DC_CGIN_WORD (1 << 6) /* Invert Rx1 RF DC CGin Word */ +#define INVERT_RX2_RF_DC_CGOUT_WORD (1 << 5) /* Invert Rx2 RF DC CGout Word */ +#define INVERT_RX1_RF_DC_CGOUT_WORD (1 << 4) /* Invert Rx1 RF DC CGout Word */ + +/* +* REG_DC_OFFSET_CONFIG2 +*/ +#define USE_WAIT_COUNTER_FOR_RF_DC_INIT_CAL (1 << 7) /* Use Wait Counter for RF DC Init Cal */ +#define ENABLE_FAST_SETTLE_MODE (1 << 6) /* Enable Fast Settle Mode */ +#define ENABLE_BB_DC_OFFSET_TRACKING (1 << 5) /* Enable BB DC Offset Tracking */ +#define RESET_ACC_ON_GAIN_CHANGE (1 << 4) /* Reset Acc on Gain Change */ +#define ENABLE_RF_OFFSET_TRACKING (1 << 3) /* Enable RF Offset Tracking */ +#define DC_OFFSET_UPDATE(x) (((x) & 0x7) << 0) /* DC Offset Update<2:0> */ + +/* +* REG_RF_CAL_GAIN_INDEX +*/ +#define RF_MINIMUM_CALIBRATION_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* RF Minimum Calibration Gain Index<6:0> */ + +/* +* REG_SOI_THRESH +*/ +#define RF_SOI_THRESH(x) (((x) & 0x7F) << 0) /* RF SOI Threshold<6:0> */ + +/* +* REG_BB_DC_OFFSET_SHIFT +*/ +#define INCREASE_COUNT_DURATION (1 << 7) /* Increase Count Duration */ +#define BB_TRACKING_DECIMATE(x) (((x) & 0x3) << 5) /* BB Tracking Decimate<1:0> */ +#define BB_DC_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_FAST_SETTLE_SHIFT +*/ +#define READ_BACK_CH_SEL (1 << 7) /* Read Back CH Sel */ +#define UPDATE_TRACKING_WORD (1 << 6) /* Update Tracking Word */ +#define FORCE_RX_NULL (1 << 5) /* Force Rx Null */ +#define BB_DC_TRACKING_FAST_SETTLE_M_SHIFT(x) (((x) & 0x1F) << 0) /* BB DC Tracking Fast Settle M Shift<4:0> */ + +/* +* REG_BB_DC_OFFSET_ATTEN +*/ +#define BB_DC_OFFSET_ATTEN(x) (((x) & 0xF) << 0) /* BB DC Offset Atten<3:0> */ + +/* +* REG_RX1_BB_DC_WORD_I_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX1_BB_DC_WORD_Q_MSB +*/ +#define RX1_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_I_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word I<14:8> */ + +/* +* REG_RX2_BB_DC_WORD_Q_MSB +*/ +#define RX2_BB_DC_OFFSET_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX2 BB DC Offset Correction word Q<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_I_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_I(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word I<14:8> */ + +/* +* REG_BB_TRACK_CORR_WORD_Q_MSB +*/ +#define RX1RX2_BB_DC_OFFSET_TRACKING_CORRECTION_WORD_Q(x) (((x) & 0x7F) << 0) /* RX1/RX2 BB DC Offset Tracking correction word Q<14:8> */ + +/* +* REG_SYMBOL_LSB +*/ +#define RX2_RSSI_SYMBOL (1 << 1) /* Rx2 RSSI symbol <0> */ +#define RX1_RSSI_SYMBOL (1 << 0) /* Rx1 RSSI symbol <0> */ + +/* +* REG_PREAMBLE_LSB +*/ +#define RX2_RSSI_PREAMBLE (1 << 1) /* Rx2 RSSI preamble <0> */ +#define RX1_RSSI_PREAMBLE (1 << 0) /* Rx1 RSSI preamble <0> */ + +/* +* REG_RX1_RSSI_SYMBOL, REG_RX1_RSSI_PREAMBLE, +* REG_RX2_RSSI_SYMBOL, REG_RX2_RSSI_PREAMBLE +*/ +#define RSSI_LSB_SHIFT 1 +#define RSSI_LSB_MASK1 0x01 +#define RSSI_LSB_MASK2 0x02 + +/* +* REG_RX_PATH_GAIN_LSB +*/ +#define RX_PATH_GAIN (1 << 0) /* Rx Path Gain<0> */ + +/* +* REG_RX_DIFF_LNA_FORCE +*/ +#define FORCE_RX2_LNA_GAIN (1 << 7) /* Force Rx2 LNA Gain */ +#define RX2_LNA_BYPASS (1 << 6) /* Rx2 LNA Bypass */ +#define FORCE_RX1_LNA_GAIN (1 << 3) /* Force Rx1 LNA Gain */ +#define RX1_LNA_BYPASS (1 << 2) /* Rx1 LNA Bypass */ +#define RX2_LNA_GAIN(x) (((x) & 0x3) << 4) /* Rx2 LNA Gain<1:0> */ +#define RX1_LNA_GAIN(x) (((x) & 0x3) << 0) /* Rx1 LNA Gain<1:0> */ + +/* +* REG_RX_LNA_BIAS_COARSE +*/ +#define RX_LNA_BIAS_COARSE(x) (((x) & 0xF) << 0) /* Rx LNA Bias Coarse<3:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_0 +*/ +#define RX_LNA_PCASCODE_BIAS(x) (((x) & 0x7) << 5) /* Rx LNA p-Cascode Bias<2:0> */ +#define RX_LNA_BIAS(x) (((x) & 0x1F) << 0) /* Rx LNA Bias<4:0> */ + +/* +* REG_RX_LNA_BIAS_FINE_1 +*/ +#define RX_LNA_P_CASCODE_BIAS_FINE(x) (((x) & 0x3) << 0) /* Rx LNA p- Cascode Bias Fine<4:3> */ + +/* +* REG_RX_MIX_GM_CONFIG +*/ +#define RX_MIX_GM_CM_OUT(x) (((x) & 0x7) << 5) /* Rx Mix Gm CM Out<2:0> */ +#define RX_MIX_GM_PLOAD(x) (((x) & 0x3) << 0) /* Rx Mix Gm pload <1:0> */ + +/* +* REG_RX1_MIX_GM_FORCE +*/ +#define FORCE_RX1_MIX_GM (1 << 6) /* Force Rx1 Mix Gm */ +#define RX1_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx1 Mix Gm Gain<5:0> */ + +/* +* REG_RX1_MIX_GM_BIAS_FORCE +*/ +#define RX1_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx1 Mix Gm Bias<4:0> */ + +/* +* REG_RX2_MIX_GM_FORCE +*/ +#define FORCE_RX2_MIX_GM (1 << 6) /* Force Rx2 Mix Gm */ +#define RX2_MIX_GM_GAIN(x) (((x) & 0x3F) << 0) /* Rx2 Mix Gm Gain<5:0> */ + +/* +* REG_RX2_MIX_GM_BIAS_FORCE +*/ +#define RX2_MIX_GM_BIAS(x) (((x) & 0x1F) << 0) /* Rx2 Mix Gm Bias<4:0> */ + +/* +* REG_INPUT_A_MSBS +*/ +#define INPUT_A_RX1_Q(x) (((x) & 0x3) << 6) /* Input A RX1 Q<9:8> */ +#define INPUT_A_RX1_I(x) (((x) & 0x3) << 4) /* Input A RX1 I<9:8> */ +#define INPUT_A_RX2_I(x) (((x) & 0x3) << 2) /* Input A RX2 I<9:8> */ +#define INPUT_A_RX2_Q(x) (((x) & 0x3) << 0) /* Input A RX2 Q<9:8> */ + +/* +* REG_INPUTS_BC_MSBS +*/ +#define INPUTS_BC_RX1_Q(x) (((x) & 0x3) << 6) /* Inputs B&C RX1 Q<9:8> */ +#define INPUTS_BC_RX1_I(x) (((x) & 0x3) << 4) /* Inputs B&C RX1 I<9:8> */ +#define INPUTS_BC_RX2_I(x) (((x) & 0x3) << 2) /* Inputs B&C RX2 I<9:8> */ +#define INPUTS_BC_RX2_Q(x) (((x) & 0x3) << 0) /* Inputs B&C RX2 Q<9:8> */ + +/* +* REG_FORCE_OS_DAC +*/ +#define FORCE_CGIN_DAC (1 << 2) /* Force CGin DAC */ + +/* +* REG_RX_MIX_LO_CM +*/ +#define RX_MIX_LO_CM(x) (((x) & 0x3F) << 0) /* Rx Mix LO CM<5:0> */ + +/* +* REG_RX_CGB_SEG_ENABLE +*/ +#define RX_CGB_SEG_ENABLE(x) (((x) & 0x3F) << 0) /* Rx CGB Seg Enable<5:0> */ + +/* +* REG_RX_MIX_INPUTBIAS +*/ +#define RX_CGB_INPUT_CM_SEL(x) (((x) & 0x3) << 4) /* Rx CGB Input CM Sel<1:0> */ +#define RX_CGB_BIAS(x) (((x) & 0xF) << 0) /* Rx CGB Bias<3:0> */ + +/* +* REG_RX_TIA_CONFIG +*/ +#define TIA2_OVERRIDE_C (1 << 3) /* TIA2 Override C */ +#define TIA2_OVERRIDE_R (1 << 2) /* TIA2 Override R */ +#define TIA1_OVERRIDE_C (1 << 1) /* TIA1 Override C */ +#define TIA1_OVERRIDE_R (1 << 0) /* TIA1 Override R */ +#define TIA_SEL_CC(x) (((x) & 0x7) << 5) /* TIA Sel CC<2:0> */ + +/* +* REG_TIA1_C_LSB +*/ +#define TIA1_RF(x) (((x) & 0x3) << 6) /* TIA1 RF<1:0> */ +#define TIA1_C_LSB(x) (((x) & 0x3F) << 0) /* TIA1 C LSB<5:0> */ + +/* +* REG_TIA1_C_MSB +*/ +#define TIA1_C_MSB(x) (((x) & 0x7F) << 0) /* TIA1 C MSB<6:0> */ + +/* +* REG_TIA2_C_LSB +*/ +#define TIA2_RF(x) (((x) & 0x3) << 6) /* TIA2 RF<1:0> */ +#define TIA2_C_LSB(x) (((x) & 0x3F) << 0) /* TIA2 C LSB<5:0> */ + +/* +* REG_TIA2_C_MSB +*/ +#define TIA2_C_MSB(x) (((x) & 0x7F) << 0) /* TIA2 C MSB<6:0> */ + +/* +* REG_RX1_BBF_R1A +*/ +#define FORCE_RX1_RESISTORS (1 << 7) /* Force Rx1 Resistors */ +#define RX1_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx1 BBF R1A<5:0> */ + +/* +* REG_RX2_BBF_R1A +*/ +#define FORCE_RX2_RESISTORS (1 << 7) /* Force Rx2 Resistors */ +#define RX2_BBF_R1A(x) (((x) & 0x3F) << 0) /* Rx2 BBF R1A<5:0> */ + +/* +* REG_RX1_TUNE_CTRL +*/ +#define RX1_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx1 Tune Resample Phase */ +#define RX1_TUNE_RESAMPLE (1 << 1) /* Rx1 Tune Resample */ +#define RX1_PD_TUNE (1 << 0) /* Rx1 PD Tune */ + +/* +* REG_RX2_TUNE_CTRL +*/ +#define RX2_TUNE_RESAMPLE_PHASE (1 << 2) /* Rx2 Tune Resam ple Phase */ +#define RX2_TUNE_RESAMPLE (1 << 1) /* Rx2 Tune Resample */ +#define RX2_PD_TUNE (1 << 0) /* Rx2 PD Tune */ + +/* +* REG_RX_BBF_R2346 +*/ +#define TUNE_OVERRIDE (1 << 7) /* Tune Override */ +#define RX_BBF_R2346(x) (((x) & 0x7) << 0) /* Rx BBF R2346<2:0> */ + +/* +* REG_RX_BBF_C1_MSB +*/ +#define RX_BBF_C1_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C1 MSB<5:0> */ + +/* +* REG_RX_BBF_C1_LSB +*/ +#define RX_BBF_C1_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C1 LSB<6:0> */ + +/* +* REG_RX_BBF_C2_MSB +*/ +#define RX_BBF_C2_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C2 MSB<5:0> */ + +/* +* REG_RX_BBF_C2_LSB +*/ +#define RX_BBF_C2_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C2 LSB<6:0> */ + +/* +* REG_RX_BBF_C3_MSB +*/ +#define RX_BBF_C3_MSB(x) (((x) & 0x3F) << 0) /* Rx BBF C3 MSB<5:0> */ + +/* +* REG_RX_BBF_C3_LSB +*/ +#define RX_BBF_C3_LSB(x) (((x) & 0x7F) << 0) /* Rx BBF C3 LSB<6:0> */ + +/* +* REG_RX_BBF_CC1_CTR +*/ +#define RX_BBF_CC1_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC1 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE0 +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define RX1_BBF_POW_CTR(x) (((x) & 0x3) << 5) /* Rx1 BBF Pow Ctr<1:0> */ +#define RX_BBF_RZ1_CTR(x) (((x) & 0x3) << 3) /* Rx BBF Rz1 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC2_CTR +*/ +#define RX_BBF_CC2_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC2 Ctr<6:0> */ + +/* +* REG_RX_BBF_POW_RZ_BYTE1 +*/ +#define RX_BBF_POW3_CTR(x) (((x) & 0x3) << 6) /* Rx BBF Pow3 Ctr<1:0> */ +#define RX_BBF_RZ3_CTR(x) (((x) & 0x3) << 4) /* Rx BBF RZ3 Ctr<1:0> */ +#define RX_BBF_POW2_CTR(x) (((x) & 0x3) << 2) /* Rx BBF Pow2 Ctr<1:0> */ +#define RX_BBF_RZ2_CTR(x) (((x) & 0x3) << 0) /* Rx BBF Rz2 Ctr<1:0> */ + +/* +* REG_RX_BBF_CC3_CTR +*/ +#define RX_BBF_CC3_CTR(x) (((x) & 0x7F) << 0) /* Rx BBF CC3 Ctr<6:0> */ + +/* +* REG_RX_BBF_TUNE +*/ +#define RXBBF_BYPASS_BIAS_R (1 << 7) /* RxBBF Bypass Bias R */ +#define RX_BBF_R5_TUNE (1 << 4) /* Rx BBF R5 Tune */ +#define RX1_BBF_TUNE_COMP_I (1 << 3) /* Rx1 BBF Tune Comp I */ +#define RX1_BBF_TUNE_COMP_Q (1 << 2) /* Rx1 BBF Tune Comp Q */ +#define RX2_BBF_TUNE_COMP_I (1 << 1) /* Rx2 BBF Tune Comp I */ +#define RX2_BBF_TUNE_COMP_Q (1 << 0) /* Rx2 BBF Tune Comp Q */ +#define RX_BBF_TUNE_CTR(x) (((x) & 0x3) << 5) /* Rx BBF Tune Ctr<1:0> */ + +/* +* REG_RX1_BBF_MAN_GAIN +*/ +#define RX1_BBF_FORCE_GAIN (1 << 5) /* Rx1 BBF Force Gain */ +#define RX1_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx1 BBF BQ Gain<1:0> */ +#define RX1_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx1 BBF Pole Gain<2:0> */ + +/* +* REG_RX2_BBF_MAN_GAIN +*/ +#define RX2_BBF_FORCE_GAIN (1 << 5) /* Rx2 BBF Force Gain */ +#define RX2_BBF_BQ_GAIN(x) (((x) & 0x3) << 3) /* Rx2 BBF BQ Gain<1:0> */ +#define RX2_BBF_POLE_GAIN(x) (((x) & 0x7) << 0) /* Rx2 BBF Pole Gain<2:0> */ + +/* +* REG_RX_BBF_TUNE_CONFIG +*/ +#define RX_TUNE_EVALTIME (1 << 4) /* Rx Tune Evaltime */ +#define RX_BBF_TUNE_DIVIDE (1 << 0) /* RX BBF Tune Divide<8> */ +#define TUNE_COMP_MASK(x) (((x) & 0x3) << 5) /* Tune Comp Mask <1:0> */ +#define RX_TUNE_MODE(x) (((x) & 0x7) << 1) /* Rx Tune Mode<2:0> */ + +/* +* REG_POLE_GAIN +*/ +#define POLE_GAIN_TUNE(x) (((x) & 0x3) << 0) /* Pole Gain Tune<1:0> */ + +/* +* REG_RX_BBBW_MHZ +*/ +#define RX_TUNE_BBBW_MHZ(x) (((x) & 0x1F) << 0) /* Rx Tune BBBW MHz<4::0> */ + +/* +* REG_RX_BBBW_KHZ +*/ +#define RX_TUNE_BBBW_KHZ(x) (((x) & 0x7F) << 0) /* Rx Tune BBBW kHz<6:0> */ + +/* +* REG_RX_PFD_CONFIG +*/ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ + +/* +* REG_RX_INTEGER_BYTE_1 +*/ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_RX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_RX_FORCE_VCO_TUNE_1 +*/ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_RX_ALC_VARACTOR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_RX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_RX_CP_CURRENT +*/ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_RX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ + +/* +* REG_RX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define CP_OFFSET_OFF (1 << 4) /* CP Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ + +/* +* REG_RX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_RX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_RX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_RX_DITHERCP_CAL +*/ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_BIAS_1 +*/ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_RX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_RX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_RX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define PWR_DOWN_VARACT_REF_TCF (1 << 2) /* Pwr Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_RX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_RX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_RX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait <2:0> */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count <1:0> */ + +/* +* REG_RX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_RX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Threshold Low<2:0> */ +#define CP_LEVEL_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Threshold High<2:0> */ + +/* +* REG_RX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_RX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_RX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_RX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_RX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_RX_FAST_LOCK_SETUP +*/ +#define RX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Rx Fast Lock Load Synth */ +#define RX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Rx Fast Lock Profile Init */ +#define RX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Rx Fast Lock Profile Pin Select */ +#define RX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Rx Fast Lock Mode Enable */ +#define RX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Rx Fast Lock Profile<2:0> */ + +/* +* REG_RX_FAST_LOCK_PROGRAM_ADDR +*/ +#define RX_FAST_LOCK_PROFILE_ADDR(x) (((x) & 0x7) << 4) /* Rx Fast Lock Profile<2:0> */ +#define RX_FAST_LOCK_PROFILE_WORD(x) (((x) & 0xF) << 0) /* Configuration Word <3:0> */ + + +/* +* REG_RX_FAST_LOCK_PROGRAM_CTRL +*/ +#define RX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Rx Fast Lock Program Write */ +#define RX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Rx Fast Lock Program Clock Enable */ + +#define RX_FAST_LOCK_CONFIG_WORD_NUM 16 + +/* +* REG_RX_LO_GEN_POWER_MODE +*/ +#define RX_LO_GEN_POWER_MODE(x) (((x) & 0x3) << 4) /* Power Mode<3:0> */ + +/* +* REG_TX_PFD_CONFIG +*/ +#define DIV_TEST_EN (1 << 5) /* Div Test En */ +#define PFD_CLK_EDGE (1 << 1) /* PFD Clk Edge */ +#define BYPASS_LD_SYNTH (1 << 0) /* Bypass Ld Synth */ +#define PFD_WIDTH(x) (((x) & 0x3) << 2) /* PFD Width <1:0> */ + +/* +* REG_TX_INTEGER_BYTE_1 +*/ +#define SDM_BYPASS (1 << 7) /* SDM Bypass */ +#define SDM_POWER_DOWN (1 << 6) /* SDM Power Down */ +#define SYNTH_INTEGER_WORD(x) (((x) & 0x7) << 0) /* Synthesizer Integer Word<10:8> */ + +/* +* REG_TX_FRACT_BYTE_2 +*/ +#define SYNTH_FRACT_WORD(x) (((x) & 0x7F) << 0) /* Synthesizer Fractional Word <22:16> */ + +/* +* REG_TX_FORCE_ALC +*/ +#define FORCE_ALC_ENABLE (1 << 7) /* Force ALC Enable */ +#define FORCE_ALC_WORD(x) (((x) & 0x7F) << 0) /* Force ALC Word<6:0> */ + +/* +* REG_TX_FORCE_VCO_TUNE_1 +*/ +#define BYPASS_LOAD_DELAY (1 << 7) /* Bypass Load Delay */ +#define FORCE_VCO_TUNE_ENABLE (1 << 1) /* Force VCO Tune Enable */ +#define FORCE_VCO_TUNE (1 << 0) /* Force VCO Tune */ +#define VCO_CAL_OFFSET(x) (((x) & 0xF) << 3) /* VCO Cal Offset<3:0> */ + +/* +* REG_TX_ALCVARACT_OR +*/ +#define INIT_ALC_VALUE(x) (((x) & 0xF) << 4) /* Init ALC Value<3:0> */ +#define VCO_VARACTOR(x) (((x) & 0xF) << 0) /* VCO Varactor<3:0> */ + +/* +* REG_TX_VCO_OUTPUT +*/ +#define PORB_VCO_LOGIC (1 << 6) /* PORb VCO Logic */ +#define VCO_OUTPUT_LEVEL(x) (((x) & 0xF) << 0) /* VCO Output Level<3:0> */ + +/* +* REG_TX_CP_CURRENT +*/ +#define TX_CP_CURRENT_DFLT (1 << 7) /* Set to 1 */ +#define VTUNE_FORCE (1 << 6) /* Vtune Force */ +#define CHARGE_PUMP_CURRENT(x) (((x) & 0x3F) << 0) /* Charge Pump Current<5:0> */ + +/* +* REG_TX_CP_OFFSET +*/ +#define SYNTH_RECAL (1 << 7) /* Synth Re-Cal */ +#define CHARGE_PUMP_OFFSET(x) (((x) & 0x3F) << 0) /* Charge Pump Offset<5:0> */ + +/* +* REG_TX_CP_CONFIG +*/ +#define HALF_VCO_CAL_CLK (1 << 7) /* Half Vco Cal Clk */ +#define DITHER_MODE (1 << 6) /* Dither Mode */ +#define CP_OFFSET_OFF (1 << 4) /* Cp Offset Off */ +#define F_CPCAL (1 << 3) /* F Cpcal */ +#define CP_CAL_ENABLE (1 << 2) /* Cp Cal Enable */ +#define CP_TEST(x) (((x) & 0x3) << 0) /* Cp Test <1:0> */ + +/* +* REG_TX_LOOP_FILTER_1 +*/ +#define LOOP_FILTER_C2(x) (((x) & 0xF) << 4) /* Loop Filter C2<3:0> */ +#define LOOP_FILTER_C1(x) (((x) & 0xF) << 0) /* Loop Filter C1<3:0> */ + +/* +* REG_TX_LOOP_FILTER_2 +*/ +#define LOOP_FILTER_R1(x) (((x) & 0xF) << 4) /* Loop Filter R1<3:0> */ +#define LOOP_FILTER_C3(x) (((x) & 0xF) << 0) /* Loop Filter C3<3:0> */ + +/* +* REG_TX_LOOP_FILTER_3 +*/ +#define LOOP_FILTER_BYPASS_R3 (1 << 7) /* Loop Filter Bypass R3 */ +#define LOOP_FILTER_BYPASS_R1 (1 << 6) /* Loop Filter Bypass R1 */ +#define LOOP_FILTER_BYPASS_C2 (1 << 5) /* Loop Filter Bypass C2 */ +#define LOOP_FILTER_BYPASS_C1 (1 << 4) /* Loop Filter Bypass C1 */ +#define LOOP_FILTER_R3(x) (((x) & 0xF) << 0) /* Loop Filter R3<3:0> */ + +/* +* REG_TX_DITHERCP_CAL +*/ +#define NUMBER_SDM_DITHER_BITS(x) (((x) & 0xF) << 4) /* Number SDM Dither Bits<3:0> */ +#define FORCED_CP_CAL_WORD(x) (((x) & 0xF) << 0) /* Forced CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_BIAS_1 +*/ +#define MUST_BE_ZEROS(x) (((x) & 0x3) << 5) /* Must be zeros */ +#define VCO_BIAS_TCF(x) (((x) & 0x3) << 3) /* VCO Bias Tcf<1:0> */ +#define VCO_BIAS_REF(x) (((x) & 0x7) << 0) /* VCO Bias Ref<2:0> */ + +/* +* REG_TX_VCO_BIAS_2 +*/ +#define VCO_BYPASS_BIAS_DAC_R (1 << 7) /* VCO Bypass Bias DAC R */ +#define VCO_COMP_BYPASS_BIAS_R (1 << 4) /* VCO Comp Bypass Bias R */ +#define BYPASS_PRESCALE_R (1 << 3) /* Bypass Prescale R */ +#define LAST_ALC_ENABLE (1 << 2) /* Last ALC Enable */ +#define PRESCALE_BIAS(x) (((x) & 0x3) << 0) /* Prescale Bias <1:0> */ + +/* +* REG_TX_CAL_STATUS +*/ +#define CP_CAL_VALID (1 << 7) /* CP Cal Valid */ +#define COMP_OUT (1 << 6) /* Comp Out */ +#define CP_CAL_DONE (1 << 5) /* CP Cal Done */ +#define VCO_CAL_BUSY (1 << 4) /* VCO Cal Busy */ +#define CP_CAL_WORD(x) (((x) & 0xF) << 0) /* CP Cal Word<3:0> */ + +/* +* REG_TX_VCO_CAL_REF +*/ +#define VCO_CAL_REF_MONITOR (1 << 3) /* VCO Cal Ref Monitor */ +#define VCO_CAL_REF_TCF(x) (((x) & 0x7) << 0) /* VCO Cal Ref Tcf<2:0> */ + +/* +* REG_TX_VCO_PD_OVERRIDES +*/ +#define POWER_DOWN_VARACTOR_REF (1 << 3) /* Power Down Varactor Ref */ +#define POWER_DOWN_VARACT_REF_TCF (1 << 2) /* Power Down Varact Ref Tcf */ +#define POWER_DOWN_CAL_TCF (1 << 1) /* Power Down Cal Tcf */ +#define POWER_DOWN_VCO_BUFFFER (1 << 0) /* Power Down VCO Bufffer */ + +/* +* REG_TX_CP_OVERRANGE_VCO_LOCK +*/ +#define CP_OVRG_HIGH (1 << 7) /* CP Ovrg High */ +#define CP_OVRG_LOW (1 << 6) /* CP Ovrg Low */ +#define VCO_LOCK (1 << 1) /* Lock */ + +/* +* REG_TX_VCO_LDO +*/ +#define VCO_LDO_BYPASS (1 << 7) /* VCO LDO Bypass */ +#define VCO_LDO_INRUSH(x) (((x) & 0x3) << 5) /* VCO LDO Inrush<1:0> */ +#define VCO_LDO_VOUT_SEL(x) (((x) & 0x7) << 2) /* VCO LDO Vout Sel<2:0> */ +#define VCO_LDO_VDROP_SEL(x) (((x) & 0x3) << 0) /* VCO LDO Vdrop Sel<1:0> */ + +/* +* REG_TX_VCO_CAL +*/ +#define VCO_CAL_EN (1 << 7) /* VCO Cal En */ +#define VCO_CAL_ALC_WAIT(x) (((x) & 0x7) << 4) /* VCO Cal ALC Wait<2:0) */ +#define VCO_CAL_COUNT(x) (((x) & 0x3) << 2) /* VCO Cal Count<1:0> */ +#define FB_CLOCK_ADV(x) (((x) & 0x3) << 0) /* FB Clock Adv<1:0> */ + +/* +* REG_TX_LOCK_DETECT_CONFIG +*/ +#define LOCK_DETECT_COUNT(x) (((x) & 0x3) << 2) /* Lock Detect Count<1:0> */ +#define LOCK_DETECT_MODE(x) (((x) & 0x3) << 0) /* Lock Detect Mode<1:0> */ + +/* +* REG_TX_CP_LEVEL_DETECT +*/ +#define CP_LEVEL_DETECT_POWER_DOWN (1 << 6) /* CP Level Detect Power Down */ +#define CP_LEVEL_DETECT_THRESH_LOW(x) (((x) & 0x7) << 3) /* CP Level Detect Threshold Low<2:0> */ +#define CP_LEVEL_DETECT_THRESH_HIGH(x) (((x) & 0x7) << 0) /* CP Level Detect Threshold High<2:0> */ + +/* +* REG_TX_DSM_SETUP_0 +*/ +#define DSM_PROG(x) (((x) & 0xF) << 0) /* DSM Prog<3:0> */ + +/* +* REG_TX_DSM_SETUP_1 +*/ +#define SIF_CLOCK (1 << 6) /* SIF clock */ +#define SIF_RESET_BAR (1 << 5) /* SIF Reset Bar */ +#define SIF_ADDR(x) (((x) & 0x1F) << 0) /* SIF Addr<4:0> */ + +/* +* REG_TX_CORRECTION_WORD0 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define READ_EFFECTIVE_TUNING_WORD (1 << 5) /* Read Effective Tuning Word */ +#define FREQ_CORRECTION_WORD_MSB(x) (((x) & 0x1F) << 0) /* Frequency Correction Word<11:7> */ + +/* +* REG_TX_CORRECTION_WORD1 +*/ +#define UPDATE_FREQ_WORD (1 << 7) /* Update Freq Word */ +#define FREQ_CORRECTION_WORD_LSB(x) (((x) & 0x7F) << 0) /* Frequency Correction Word<6:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_0 +*/ +#define VCO_VARACTOR_REFERENCE_TCF(x) (((x) & 0x7) << 4) /* VCO Varactor Reference Tcf<2:0> */ +#define VCO_VARACTOR_OFFSET(x) (((x) & 0xF) << 0) /* VCO Varactor Offset<3:0> */ + +/* +* REG_TX_VCO_VARACTOR_CTRL_1 +*/ +#define VCO_VARACTOR_REFERENCE(x) (((x) & 0xF) << 0) /* VCO Varactor Reference<3:0> */ + +/* +* REG_DCXO_COARSE_TUNE +*/ +#define DCXO_TUNE_COARSE(x) (((x) & 0x3F) << 0) /* DCXO Tune Coarse<5:0> */ + +/* +* REG_DCXO_FINE_TUNE_LOW +*/ +#define DCXO_TUNE_FINE_LOW(x) (((x) & 0x1F) << 3) /* DCXO Tune Fine<4:0> */ + +/* +* REG_DCXO_FINE_TUNE_HIGH +*/ +#define DCXO_TUNE_FINE_HIGH(x) ((x) >> 5) /* DCXO Tune Fine<12:5> */ + +/* +* REG_DCXO_CONFIG +*/ +#define MUST_BE_ZERO (1 << 7) /* Must be zero */ +#define DCXO_RTAIL(x) (((x) & 0x7) << 4) /* DCXO Rtail<2:0> */ +#define DCXO_RD(x) (((x) & 0x3) << 2) /* DCXO Rd<1:0> */ + +/* +* REG_DCXO_TEMPCO_ADDR +*/ +#define DCXO_TEMPCO_EN (1 << 7) /* DCXO Tempco En */ +#define DCXO_TEMPCO_CLK (1 << 6) /* DCXO Tempco Clk */ +#define DCXO_TEMPERATURE_COEF_ADDRESS(x) (((x) & 0x3F) << 0) /* DCXO Temperature Coefficient Address<5:0> */ + +/* +* REG_TX_FAST_LOCK_SETUP +*/ +#define TX_FAST_LOCK_LOAD_SYNTH (1 << 3) /* Tx Fast Lock Load Synth */ +#define TX_FAST_LOCK_PROFILE_INIT (1 << 2) /* Tx Fast Lock Profile Init */ +#define TX_FAST_LOCK_PROFILE_PIN_SELECT (1 << 1) /* Tx Fast Lock Profile Pin Select */ +#define TX_FAST_LOCK_MODE_ENABLE (1 << 0) /* Tx Fast Lock Mode Enable */ +#define TX_FAST_LOCK_PROFILE(x) (((x) & 0x7) << 5) /* Tx Fast Lock Profile<2:0> */ + +/* +* REG_TX_FAST_LOCK_PROGRAM_CTRL +*/ +#define TX_FAST_LOCK_PROGRAM_WRITE (1 << 1) /* Tx Fast Lock Program Write */ +#define TX_FAST_LOCK_PROGRAM_CLOCK_ENABLE (1 << 0) /* Tx Fast Lock Program Clock Enable */ + +/* +* REG_TX_LO_GEN_POWER_MODE +*/ +#define TX_LO_GEN_POWER_MODE(x) (((x) & 0xF) << 4) /* Power Mode<3:0> */ + +/* +* REG_BANDGAP_CONFIG0 +*/ +#define POWER_DOWN_BANDGAP_REF (1 << 7) /* Power Down Bandgap Ref */ +#define MASTER_BIAS_FILTER_BYPASS (1 << 6) /* Master Bias Filter Bypass */ +#define MASTER_BIAS_REF_SEL (1 << 5) /* Master Bias Ref Sel */ +#define MASTER_BIAS_TRIM(x) (((x) & 0x1F) << 0) /* Master Bias Trim<4:0> */ + +/* +* REG_BANDGAP_CONFIG1 +*/ +#define VCO_LDO_FILTER_BYPASS (1 << 7) /* VCO LDO Filter Bypass */ +#define VCO_LDO_REF_SEL (1 << 6) /* VCO LDO Ref Sel */ +#define BANDGAP_REF_RESET (1 << 5) /* Bandgap Ref Reset */ +#define BANDGAP_TEMP_TRIM(x) (((x) & 0x1F) << 0) /* Bandgap Temp Trim<4:0> */ + +/* +* REG_REF_DIVIDE_CONFIG_1 +*/ +#define REF_DIVIDE_CONFIG_1_DFLT (1 << 2) /* Set to 1 */ +#define RX_REF_RESET_BAR (1 << 1) /* Rx Ref Reset Bar */ +#define RX_REF_DIVIDER_MSB (1 << 0) /* Rx Ref Divider<1> */ + +/* +* REG_REF_DIVIDE_CONFIG_2 +*/ +#define RX_REF_DIVIDER_LSB (1 << 7) /* Rx Ref Divider< 0> */ +#define TX_REF_RESET_BAR (1 << 4) /* Tx Ref Reset Bar */ +#define RX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 5) /* Rx Ref Doubler FB Delay<1:0> */ +#define TX_REF_DIVIDER(x) (((x) & 0x3) << 2) /* Tx Ref Divider<1:0> */ +#define TX_REF_DOUBLER_FB_DELAY(x) (((x) & 0x3) << 0) /* Tx Ref Doubler FB Delay<1:0> */ + +/* +* REG_GAIN_RX1,2 +*/ +#define FULL_TABLE_GAIN_INDEX(x) (((x) & 0x7F) << 0) /* Full Table Gain Index Rx1/LMT Gain Rx1<6:0> */ + +/* +* REG_LPF_GAIN_RX1,2 +*/ +#define LPF_GAIN_RX(x) (((x) & 0x1F) << 0) /* LPF gain Rx1<4:0> */ + +/* +* REG_DIG_GAIN_RX1,2 +*/ +#define DIGITAL_GAIN_RX(x) (((x) & 0x1F) << 0) /* Digital gain Rx1<4:0> */ + +/* +* REG_FAST_ATTACK_STATE +*/ +#define FAST_ATTACK_STATE_RX2(x) (((x) & 0x7) << 4) /* Fast Attack State Rx2<2:0> */ +#define FAST_ATTACK_STATE_RX1(x) (((x) & 0x7) << 0) /* Fast Attack State Rx1<2:0> */ +#define FAST_ATK_MASK 0x7 +#define RX1_FAST_ATK_SHIFT 0 +#define RX2_FAST_ATK_SHIFT 4 +#define FAST_ATK_RESET 0 +#define FAST_ATK_PEAK_DETECT 1 +#define FAST_ATK_PWR_MEASURE 2 +#define FAST_ATK_FINAL_SETTELING 3 +#define FAST_ATK_FINAL_OVER 4 +#define FAST_ATK_GAIN_LOCKED 5 + +/* +* REG_SLOW_LOOP_STATE +*/ +#define SLOW_LOOP_STATE_RX2(x) (((x) & 0x7) << 4) /* Slow Loop State Rx2<2:0> */ +#define SLOW_LOOP_STATE_RX1(x) (((x) & 0x7) << 0) /* Slow Loop State Rx1<2:0> */ + + +/* +* REG_OVRG_SIGS_RX1,2 +*/ +#define GAIN_LOCK_1 (1 << 6) /* Gain Lock 1 */ +#define LOW_POWER_1 (1 << 5) /* Low Power 1 */ +#define LARGE_LMT_OL (1 << 4) /* Large LMT OL */ +#define SMALL_LMT_OL (1 << 3) /* Small LMT OL */ +#define LARGE_ADC_OL (1 << 2) /* Large ADC OL */ +#define SMALL_ADC_OL (1 << 1) /* Small ADC OL */ +#define DIG_SAT (1 << 0) /* Dig Sat */ +/* +* REG_CTRL +*/ +#define CTRL_ENABLE (1 << 0) /* Set to 1 */ + +/* +* REG_BIST_CONFIG +*/ +#define TONE_PRBS (1 << 1) /* Tone/ PRBS */ +#define BIST_ENABLE (1 << 0) /* BIST Enable */ +#define TONE_FREQ(x) (((x) & 0x3) << 6) /* Tone Frequency<1:0> */ +#define TONE_LEVEL(x) (((x) & 0x3) << 4) /* Tone Level<1:0> */ +#define BIST_CTRL_POINT(x) (((x) & 0x3) << 2) /* BIST Control Point <1:0> */ + +/* +* REG_OBSERVE_CONFIG +*/ +#define DATA_PORT_SP_HD_LOOP_TEST_OE (1 << 7) /* Data Port SP, HD Loop Test OE */ +#define RX_MASK (1 << 6) /* Rx Mask */ +#define CHANNEL (1 << 5) /* Channel */ +#define DATA_PORT_LOOP_TEST_ENABLE (1 << 0) /* Data Port Loop Test Enable */ +#define OBSERVATION_POINT(x) (((x) & 0xF) << 1) /* Observation Point<2:0> */ + +/* +* REG_BIST_AND_DATA_PORT_TEST_CONFIG +*/ +#define BIST_MASK_CHANNEL_2_Q_DATA (1 << 5) /* BIST Mask Channel 2 Q data */ +#define BIST_MASK_CHANNEL_2_I_DATA (1 << 4) /* BIST Mask Channel 2 I data */ +#define BIST_MASK_CHANNEL_1_Q_DATA (1 << 3) /* BIST Mask Channel 1 Q data */ +#define BIST_MASK_CHANNEL_1_I_DATA (1 << 2) /* BIST Mask Channel 1 I data */ +#define DATA_PORT_HILOW (1 << 1) /* Data Port Hi/Low */ +#define USE_DATA_PORT (1 << 0) /* Use Data Port */ +#define TEMP_SENSE_VBE_TEST(x) (((x) & 0x3) << 6) /* Temp Sense Vbe Test<1:0> */ + +/* +* REG_DAC_TEST_2 +*/ +#define DAC_TEST_ENABLE (1 << 7) /* DAC Test Enable */ +#define DAC_TEST_WORD(x) (((x) & 0x7F) << 0) /* DAC test Word <22:16> */ + +/* +* SPI Comm Helpers +*/ +#define AD_READ (0 << 15) +#define AD_WRITE (1 << 15) +#define AD_CNT(x) ((((x) - 1) & 0x7) << 12) +#define AD_ADDR(x) ((x) & 0x3FF) + + +/* +* AD9361 Limits +*/ + +#define RSSI_MULTIPLIER 100 +#define RSSI_RESOLUTION ((int) (0.25 * RSSI_MULTIPLIER)) +#define RSSI_MAX_WEIGHT 255 + +#define MAX_LMT_INDEX 40 +#define MAX_LPF_GAIN 24 +#define MAX_DIG_GAIN 31 + +#define MAX_BBPLL_FREF 70007000UL /* 70 MHz + 100ppm */ +#define MIN_BBPLL_FREQ 714928500UL /* 715 MHz - 100ppm */ +#define MAX_BBPLL_FREQ 1430143000UL /* 1430 MHz + 100ppm */ +#define MAX_BBPLL_DIV 64 +#define MIN_BBPLL_DIV 2 + +/* + * The ADC minimum and maximum operating output data rates + * are 25MHz and 640MHz respectively. + * For more information see here: https://ez.analog.com/docs/DOC-12763 + */ + +#define MIN_ADC_CLK 25000000UL /* 25 MHz */ +//#define MIN_ADC_CLK (MIN_BBPLL_FREQ / MAX_BBPLL_DIV) /* 11.17MHz */ +#define MAX_ADC_CLK 640000000UL /* 640 MHz */ +#define MAX_DAC_CLK (MAX_ADC_CLK / 2) + +/* Associated with outputs of stage */ +#define MAX_RX_HB1 245760000UL +#define MAX_RX_HB2 320000000UL +#define MAX_RX_HB3 640000000UL +/* Associated with inputs of stage */ +#define MAX_TX_HB1 160000000UL +#define MAX_TX_HB2 320000000UL +#define MAX_TX_HB3 320000000UL + +#define MAX_BASEBAND_RATE 61440000UL + +#define MAX_MBYTE_SPI 8 + +#define RFPLL_MODULUS 8388593UL +#define BBPLL_MODULUS 2088960UL + +#define MAX_SYNTH_FREF 80008000UL /* 80 MHz + 100ppm */ +#define MIN_SYNTH_FREF 9999000UL /* 10 MHz - 100ppm */ +#define MIN_VCO_FREQ_HZ 6000000000ULL +#define MAX_CARRIER_FREQ_HZ 6000000000ULL +#define MIN_RX_CARRIER_FREQ_HZ 70000000ULL +#define MIN_TX_CARRIER_FREQ_HZ 46875001ULL + +#define AD9363A_MAX_CARRIER_FREQ_HZ 3800000000ULL +#define AD9363A_MIN_CARRIER_FREQ_HZ 325000000ULL + +#define MAX_TX_ATTENUATION_DB 89750 + +/* +* Driver +*/ + +enum rx_gain_table_type { + RXGAIN_FULL_TBL, + RXGAIN_SPLIT_TBL, +}; + +enum rx_gain_table_name { + TBL_200_1300_MHZ, + TBL_1300_4000_MHZ, + TBL_4000_6000_MHZ, + RXGAIN_TBLS_END, +}; + +struct gain_table_info { + uint64_t start; + uint64_t end; + uint8_t max_index; + uint8_t split_table; + int8_t *abs_gain_tbl; + uint8_t (*tab)[3]; +}; + +enum fir_dest { + FIR_TX1 = 0x01, + FIR_TX2 = 0x02, + FIR_TX1_TX2 = 0x03, + FIR_RX1 = 0x81, + FIR_RX2 = 0x82, + FIR_RX1_RX2 = 0x83, + FIR_IS_RX = 0x80, +}; + +struct rf_gain_ctrl { + uint32_t ant; + uint8_t mode; +}; + +enum rf_gain_ctrl_mode { + RF_GAIN_MGC, + RF_GAIN_FASTATTACK_AGC, + RF_GAIN_SLOWATTACK_AGC, + RF_GAIN_HYBRID_AGC +}; + +enum f_agc_target_gain_index_type { + MAX_GAIN, + SET_GAIN, + OPTIMIZED_GAIN, + NO_GAIN_CHANGE, +}; + +struct gain_control { + enum rf_gain_ctrl_mode rx1_mode; + enum rf_gain_ctrl_mode rx2_mode; + + /* Common */ + uint8_t adc_ovr_sample_size; /* 1..8 Sum x samples, AGC_CONFIG_3 */ + uint8_t adc_small_overload_thresh; /* 0..255, 0x105 */ + uint8_t adc_large_overload_thresh; /* 0..255, 0x104 */ + + uint16_t lmt_overload_high_thresh; /* 16..800 mV, 0x107 */ + uint16_t lmt_overload_low_thresh; /* 16..800 mV, 0x108 */ + uint16_t dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint8_t low_power_thresh; /* -64..0 dBFS, 0x114 */ + bool use_rx_fir_out_for_dec_pwr_meas; /* clears 0x15C:6 USE_HB1_OUT_FOR_DEC_PWR_MEAS */ + + bool dig_gain_en; /* should be turned off, since ADI GT doesn't use dig gain */ + uint8_t max_dig_gain; /* 0..31 */ + + /* MGC */ + bool mgc_rx1_ctrl_inp_en; /* Enables Pin control on RX1 default SPI ctrl */ + bool mgc_rx2_ctrl_inp_en; /* Enables Pin control on RX2 default SPI ctrl */ + + uint8_t mgc_inc_gain_step; /* 1..8 */ + uint8_t mgc_dec_gain_step; /* 1..8 */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* 0=AGC determine this, 1=only in LPF, 2=only in LMT */ + + /* AGC */ + uint8_t agc_attack_delay_extra_margin_us; /* 0..31 us */ + + uint8_t agc_outer_thresh_high; + uint8_t agc_outer_thresh_high_dec_steps; + uint8_t agc_inner_thresh_high; + uint8_t agc_inner_thresh_high_dec_steps; + uint8_t agc_inner_thresh_low; + uint8_t agc_inner_thresh_low_inc_steps; + uint8_t agc_outer_thresh_low; + uint8_t agc_outer_thresh_low_inc_steps; + + uint8_t adc_small_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_exceed_counter; /* 0..15, 0x122 */ + uint8_t adc_large_overload_inc_steps; /* 0..15, 0x106 */ + + bool adc_lmt_small_overload_prevent_gain_inc; /* 0x120 */ + + uint8_t lmt_overload_large_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_small_exceed_counter; /* 0..15, 0x121 */ + uint8_t lmt_overload_large_inc_steps; /* 0..7, 0x121 */ + + uint8_t dig_saturation_exceed_counter; /* 0..15, 0x128 */ + uint8_t dig_gain_step_size; /* 1..8, 0x100 */ + bool sync_for_gain_counter_en; /* 0x128:4 !Hybrid */ + + uint32_t gain_update_interval_us; /* in us */ + bool immed_gain_change_if_large_adc_overload; /* 0x123:3 */ + bool immed_gain_change_if_large_lmt_overload; /* 0x123:7 */ + + /* + * Fast AGC + */ + uint32_t f_agc_dec_pow_measuremnt_duration; /* Samples, 0x15C */ + uint32_t f_agc_state_wait_time_ns; /* 0x117 0..31 RX samples -> time_ns */ + /* Fast AGC - Low Power */ + bool f_agc_allow_agc_gain_increase; /* 0x110:1 */ + uint8_t f_agc_lp_thresh_increment_time; /* 0x11B RX samples */ + uint8_t f_agc_lp_thresh_increment_steps; /* 0x117 1..8 */ + + /* Fast AGC - Lock Level */ + uint8_t f_agc_lock_level; /* NOT USED: 0x101 0..-127 dBFS same as agc_inner_thresh_high */ + bool f_agc_lock_level_lmt_gain_increase_en; /* 0x111:6 */ + uint8_t f_agc_lock_level_gain_increase_upper_limit; /* 0x118 0..63 */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint8_t f_agc_lpf_final_settling_steps; /* 0x112:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_lmt_final_settling_steps; /* 0x113:6 0..3 (Post Lock Level Step)*/ + uint8_t f_agc_final_overrange_count; /* 0x116:5 0..7 */ + /* Fast AGC - Final Power Test */ + bool f_agc_gain_increase_after_gain_lock_en; /* 0x110:7 */ + /* Fast AGC - Unlocking the Gain */ + /* 0 = MAX Gain, 1 = Set Gain, 2 = Optimized Gain */ + enum f_agc_target_gain_index_type + f_agc_gain_index_type_after_exit_rx_mode; /* 0x110:[4,2] */ + bool f_agc_use_last_lock_level_for_set_gain_en; /* 0x111:7 */ + uint8_t f_agc_optimized_gain_offset; /*0x116 0..15 steps */ + bool f_agc_rst_gla_stronger_sig_thresh_exceeded_en; /* 0x110:~6 */ + uint8_t f_agc_rst_gla_stronger_sig_thresh_above_ll; /*0x113 0..63 dbFS */ + bool f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* 0x110:6 */ + bool f_agc_rst_gla_engergy_lost_goto_optim_gain_en; /* 0x110:6 */ + uint8_t f_agc_rst_gla_engergy_lost_sig_thresh_below_ll; /* 0x112:6 */ + uint8_t f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* 0x119 0..63 RX samples */ + bool f_agc_rst_gla_large_adc_overload_en; /*0x110:~1 and 0x114:~7 */ + bool f_agc_rst_gla_large_lmt_overload_en; /*0x110:~1 */ + bool f_agc_rst_gla_en_agc_pulled_high_en; + /* 0 = Max Gain, 1 = Set Gain, 2 = Optimized Gain, 3 = No Gain Change */ + + enum f_agc_target_gain_index_type + f_agc_rst_gla_if_en_agc_pulled_high_mode; /* 0x0FB, 0x111 */ + uint8_t f_agc_power_measurement_duration_in_state5; /* 0x109, 0x10a RX samples 0..524288*/ + uint8_t f_agc_large_overload_inc_steps; /* 0x106 [D6:D4] 0..7 */ +}; + +struct auxdac_control { + uint16_t dac1_default_value; + uint16_t dac2_default_value; + + bool auxdac_manual_mode_en; + + bool dac1_in_rx_en; + bool dac1_in_tx_en; + bool dac1_in_alert_en; + + bool dac2_in_rx_en; + bool dac2_in_tx_en; + bool dac2_in_alert_en; + + uint8_t dac1_rx_delay_us; + uint8_t dac1_tx_delay_us; + uint8_t dac2_rx_delay_us; + uint8_t dac2_tx_delay_us; +}; + +enum rssi_restart_mode { + AGC_IN_FAST_ATTACK_MODE_LOCKS_THE_GAIN, + EN_AGC_PIN_IS_PULLED_HIGH, + ENTERS_RX_MODE, + GAIN_CHANGE_OCCURS, + SPI_WRITE_TO_REGISTER, + GAIN_CHANGE_OCCURS_OR_EN_AGC_PIN_PULLED_HIGH, +}; + +struct rssi_control { + enum rssi_restart_mode restart_mode; + bool rssi_unit_is_rx_samples; /* default unit is time */ + uint32_t rssi_delay; + uint32_t rssi_wait; + uint32_t rssi_duration; +}; + +struct rx_gain_info { + enum rx_gain_table_type tbl_type; + int32_t starting_gain_db; + int32_t max_gain_db; + int32_t gain_step_db; + int32_t max_idx; + int32_t idx_step_offset; +}; + +struct port_control { + uint8_t pp_conf[3]; + uint8_t rx_clk_data_delay; + uint8_t tx_clk_data_delay; + uint8_t digital_io_ctrl; + uint8_t lvds_bias_ctrl; + uint8_t lvds_invert[2]; +}; + +struct ctrl_outs_control { + uint8_t index; + uint8_t en_mask; +}; + +struct elna_control { + uint16_t gain_mdB; + uint16_t bypass_loss_mdB; + uint32_t settling_delay_ns; + bool elna_1_control_en; /* GPO0 */ + bool elna_2_control_en; /* GPO1 */ + bool elna_in_gaintable_all_index_en; +}; + +struct auxadc_control { + int8_t offset; + uint32_t temp_time_inteval_ms; + uint32_t temp_sensor_decimation; + bool periodic_temp_measuremnt; + uint32_t auxadc_clock_rate; + uint32_t auxadc_decimation; +}; + +struct gpo_control { + uint32_t gpo_manual_mode_enable_mask; + bool gpo_manual_mode_en; + bool gpo0_inactive_state_high_en; + bool gpo1_inactive_state_high_en; + bool gpo2_inactive_state_high_en; + bool gpo3_inactive_state_high_en; + bool gpo0_slave_rx_en; + bool gpo0_slave_tx_en; + bool gpo1_slave_rx_en; + bool gpo1_slave_tx_en; + bool gpo2_slave_rx_en; + bool gpo2_slave_tx_en; + bool gpo3_slave_rx_en; + bool gpo3_slave_tx_en; + uint8_t gpo0_rx_delay_us; + uint8_t gpo0_tx_delay_us; + uint8_t gpo1_rx_delay_us; + uint8_t gpo1_tx_delay_us; + uint8_t gpo2_rx_delay_us; + uint8_t gpo2_tx_delay_us; + uint8_t gpo3_rx_delay_us; + uint8_t gpo3_tx_delay_us; +}; + +struct tx_monitor_control { + bool tx_mon_track_en; + bool one_shot_mode_en; + uint32_t low_high_gain_threshold_mdB; + uint8_t low_gain_dB; + uint8_t high_gain_dB; + uint16_t tx_mon_delay; + uint16_t tx_mon_duration; + uint8_t tx1_mon_front_end_gain; + uint8_t tx2_mon_front_end_gain; + uint8_t tx1_mon_lo_cm; + uint8_t tx2_mon_lo_cm; +}; + +enum ad9361_pdata_rx_freq { + BBPLL_FREQ, + ADC_FREQ, + R2_FREQ, + R1_FREQ, + CLKRF_FREQ, + RX_SAMPL_FREQ, + NUM_RX_CLOCKS, +}; + +enum ad9361_pdata_tx_freq { + IGNORE, + DAC_FREQ, + T2_FREQ, + T1_FREQ, + CLKTF_FREQ, + TX_SAMPL_FREQ, + NUM_TX_CLOCKS, +}; + +enum ad9361_clkout { + CLKOUT_DISABLE, + BUFFERED_XTALN_DCXO, + ADC_CLK_DIV_2, + ADC_CLK_DIV_3, + ADC_CLK_DIV_4, + ADC_CLK_DIV_8, + ADC_CLK_DIV_16, +}; + +struct ad9361_phy_platform_data { + bool rx2tx2; + bool fdd; + bool fdd_independent_mode; + bool split_gt; + bool use_extclk; + bool ensm_pin_pulse_mode; + bool ensm_pin_ctrl; + bool debug_mode; + bool tdd_use_dual_synth; + bool tdd_skip_vco_cal; + bool use_ext_rx_lo; + bool use_ext_tx_lo; + bool rx1rx2_phase_inversion_en; + bool qec_tracking_slow_mode_en; + uint8_t dc_offset_update_events; + uint8_t dc_offset_attenuation_high; + uint8_t dc_offset_attenuation_low; + uint8_t rf_dc_offset_count_high; + uint8_t rf_dc_offset_count_low; + uint8_t dig_interface_tune_skipmode; + uint8_t dig_interface_tune_fir_disable; + uint8_t lo_powerdown_managed_en; + uint32_t dcxo_coarse; + uint32_t dcxo_fine; + uint32_t rf_rx_input_sel; + uint32_t rf_tx_output_sel; + uint32_t rx1tx1_mode_use_rx_num; + uint32_t rx1tx1_mode_use_tx_num; + uint32_t rx_path_clks[NUM_RX_CLOCKS]; + uint32_t tx_path_clks[NUM_TX_CLOCKS]; + uint32_t trx_synth_max_fref; + uint64_t rx_synth_freq; + uint64_t tx_synth_freq; + uint32_t rf_rx_bandwidth_Hz; + uint32_t rf_tx_bandwidth_Hz; + int32_t tx_atten; + bool update_tx_gain_via_alert; + uint32_t rx_fastlock_delay_ns; + uint32_t tx_fastlock_delay_ns; + bool trx_fastlock_pinctrl_en[2]; + + enum ad9361_clkout ad9361_clkout_mode; + + struct gain_control gain_ctrl; + struct rssi_control rssi_ctrl; + struct port_control port_ctrl; + struct ctrl_outs_control ctrl_outs_ctrl; + struct elna_control elna_ctrl; + struct auxadc_control auxadc_ctrl; + struct auxdac_control auxdac_ctrl; + struct gpo_control gpo_ctrl; + struct tx_monitor_control txmon_ctrl; +}; + +struct rf_rx_gain { + uint32_t ant; /* Antenna number to read gain */ + int32_t gain_db; /* gain value in dB */ + uint32_t fgt_lmt_index; /* Full Gain Table / LNA-MIXER-TIA gain index */ + uint32_t lmt_gain; /* LNA-MIXER-TIA gain in dB (Split GT mode only)*/ + uint32_t lpf_gain; /* Low pass filter gain in dB / index (Split GT mode only)*/ + uint32_t digital_gain; /* Digital gain in dB / index */ + /* Debug only */ + uint32_t lna_index; /* LNA Index (Split GT mode only) */ + uint32_t tia_index; /* TIA Index (Split GT mode only) */ + uint32_t mixer_index; /* MIXER Index (Split GT mode only) */ + +}; +struct rf_rssi { + uint32_t ant; /* Antenna number for which RSSI is reported */ + uint32_t symbol; /* Runtime RSSI */ + uint32_t preamble; /* Initial RSSI */ + int32_t multiplier; /* Multiplier to convert reported RSSI */ + uint8_t duration; /* Duration to be considered for measuring */ +}; + +struct SynthLUT { + uint16_t VCO_MHz; + uint8_t VCO_Output_Level; + uint8_t VCO_Varactor; + uint8_t VCO_Bias_Ref; + uint8_t VCO_Bias_Tcf; + uint8_t VCO_Cal_Offset; + uint8_t VCO_Varactor_Reference; + uint8_t Charge_Pump_Current; + uint8_t LF_C2; + uint8_t LF_C1; + uint8_t LF_R1; + uint8_t LF_C3; + uint8_t LF_R3; +}; + +enum { + LUT_FTDD_40, + LUT_FTDD_60, + LUT_FTDD_80, + LUT_FTDD_ENT, +}; + +enum ad9361_clocks { + BB_REFCLK, + RX_REFCLK, + TX_REFCLK, + BBPLL_CLK, + ADC_CLK, + R2_CLK, + R1_CLK, + CLKRF_CLK, + RX_SAMPL_CLK, + DAC_CLK, + T2_CLK, + T1_CLK, + CLKTF_CLK, + TX_SAMPL_CLK, + RX_RFPLL_INT, + TX_RFPLL_INT, + RX_RFPLL_DUMMY, + TX_RFPLL_DUMMY, + RX_RFPLL, + TX_RFPLL, + NUM_AD9361_CLKS, + EXT_REF_CLK, +}; + +struct ad9361_debugfs_entry { + struct ad9361_rf_phy *phy; + const char *propname; + void *out_value; + uint32_t val; + uint8_t size; + uint8_t cmd; +}; + +struct ad9361_fastlock_entry { +#define FASTLOOK_INIT 1 + uint8_t flags; + uint8_t alc_orig; + uint8_t alc_written; +}; + +struct ad9361_fastlock { + uint8_t save_profile; + uint8_t current_profile[2]; + struct ad9361_fastlock_entry entry[2][8]; +}; + +enum dig_tune_flags { + BE_VERBOSE = 1, + BE_MOREVERBOSE = 2, + DO_IDELAY = 4, + DO_ODELAY = 8, + SKIP_STORE_RESULT = 16, + RESTORE_DEFAULT = 32, +}; + +enum ad9361_bist_mode { + BIST_DISABLE, + BIST_INJ_TX, + BIST_INJ_RX, +}; + +enum synth_pd_ctrl { + LO_DONTCARE, + LO_OFF, + LO_ON, +}; + +enum dev_id { + ID_AD9361, + ID_AD9364, + ID_AD9363A +}; + +struct ad9361_rf_phy { + enum dev_id dev_sel; + struct spi_desc *spi; + struct gpio_desc *gpio_desc_resetb; + struct gpio_desc *gpio_desc_sync; + struct gpio_desc *gpio_desc_cal_sw1; + struct gpio_desc *gpio_desc_cal_sw2; +#ifndef AXI_ADC_NOT_PRESENT + struct axi_adc *rx_adc; + struct axi_dac *tx_dac; +#endif + struct clk *clk_refin; + struct clk *clks[NUM_AD9361_CLKS]; + struct refclk_scale *ref_clk_scale[NUM_AD9361_CLKS]; + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + struct ad9361_phy_platform_data *pdata; + uint8_t prev_ensm_state; + uint8_t curr_ensm_state; + uint8_t cached_rx_rfpll_div; + uint8_t cached_tx_rfpll_div; + uint8_t cached_synth_pd[2]; + int32_t tx_quad_lpf_tia_match; + uint32_t current_table; + struct gain_table_info *gt_info; + bool ensm_pin_ctl_en; + + bool auto_cal_en; + bool manual_tx_quad_cal_en; + uint64_t last_tx_quad_cal_freq; + uint32_t last_tx_quad_cal_phase; + uint64_t current_tx_lo_freq; + uint64_t current_rx_lo_freq; + bool current_tx_use_tdd_table; + bool current_rx_use_tdd_table; + uint32_t current_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t current_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t flags; + uint32_t cal_threshold_freq; + uint32_t current_rx_bw_Hz; + uint32_t current_tx_bw_Hz; + uint32_t rxbbf_div; + uint32_t rate_governor; + bool bypass_rx_fir; + bool bypass_tx_fir; + bool rx_eq_2tx; + bool filt_valid; + uint32_t filt_rx_path_clks[NUM_RX_CLOCKS]; + uint32_t filt_tx_path_clks[NUM_TX_CLOCKS]; + uint32_t filt_rx_bw_Hz; + uint32_t filt_tx_bw_Hz; + uint8_t tx_fir_int; + uint8_t tx_fir_ntaps; + uint8_t rx_fir_dec; + uint8_t rx_fir_ntaps; + uint8_t agc_mode[2]; + bool rfdc_track_en; + bool bbdc_track_en; + bool quad_track_en; + bool txmon_tdd_en; + uint16_t auxdac1_value; + uint16_t auxdac2_value; + uint32_t tx1_atten_cached; + uint32_t tx2_atten_cached; + struct ad9361_fastlock fastlock; + struct axiadc_converter *adc_conv; + struct axiadc_state *adc_state; + int32_t bist_loopback_mode; + int32_t bist_config; + enum ad9361_bist_mode bist_prbs_mode; + enum ad9361_bist_mode bist_tone_mode; + uint32_t bist_tone_freq_Hz; + uint32_t bist_tone_level_dB; + uint32_t bist_tone_mask; + bool bbpll_initialized; +}; + +struct refclk_scale { + struct spi_desc *spi; + struct ad9361_rf_phy *phy; + uint32_t mult; + uint32_t div; + enum ad9361_clocks source; + enum ad9361_clocks parent_source; +}; + +enum debugfs_cmd { + DBGFS_NONE, + DBGFS_INIT, + DBGFS_LOOPBACK, + DBGFS_BIST_PRBS, + DBGFS_BIST_TONE, + DBGFS_BIST_DT_ANALYSIS, + DBGFS_RXGAIN_1, + DBGFS_RXGAIN_2, +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t ad9361_spi_readm(struct spi_desc *spi, uint32_t reg, + uint8_t *rbuf, uint32_t num); +int32_t ad9361_spi_read(struct spi_desc *spi, uint32_t reg); +int32_t ad9361_spi_write(struct spi_desc *spi, + uint32_t reg, uint32_t val); +int32_t ad9361_reset(struct ad9361_rf_phy *phy); +int32_t ad9361_register_clocks(struct ad9361_rf_phy *phy); +int32_t ad9361_unregister_clocks(struct ad9361_rf_phy *phy); +uint32_t ad9361_gt(struct ad9361_rf_phy *phy); +int32_t ad9361_init_gain_tables(struct ad9361_rf_phy *phy); +int32_t ad9361_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy); +int32_t ad9361_set_ensm_mode(struct ad9361_rf_phy *phy, bool fdd, bool pinctrl); +int32_t ad9361_ensm_set_state(struct ad9361_rf_phy *phy, uint8_t ensm_state, + bool pinctrl); +int32_t ad9361_set_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_get_rx_gain(struct ad9361_rf_phy *phy, + uint32_t rx_id, struct rf_rx_gain *rx_gain); +int32_t ad9361_update_rf_bandwidth(struct ad9361_rf_phy *phy, + uint32_t rf_rx_bw, uint32_t rf_tx_bw); +int32_t ad9361_calculate_rf_clock_chain(struct ad9361_rf_phy *phy, + uint32_t tx_sample_rate, + uint32_t rate_gov, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_set_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +int32_t ad9361_get_trx_clock_chain(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks); +uint32_t ad9361_to_clk(uint64_t freq); +uint64_t ad9361_from_clk(uint32_t freq); +int32_t ad9361_read_rssi(struct ad9361_rf_phy *phy, struct rf_rssi *rssi); +int32_t ad9361_set_gain_ctrl_mode(struct ad9361_rf_phy *phy, + struct rf_gain_ctrl *gain_ctrl); +int32_t ad9361_load_fir_filter_coef(struct ad9361_rf_phy *phy, + enum fir_dest dest, int32_t gain_dB, + uint32_t ntaps, short *coef); +int32_t ad9361_validate_enable_fir(struct ad9361_rf_phy *phy); +int32_t ad9361_set_tx_atten(struct ad9361_rf_phy *phy, uint32_t atten_mdb, + bool tx1, bool tx2, bool immed); +int32_t ad9361_get_tx_atten(struct ad9361_rf_phy *phy, uint32_t tx_num); +uint32_t ad9361_clk_factor_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_clk_factor_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_clk_factor_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_bbpll_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_bbpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t *prate); +int32_t ad9361_bbpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_int_recalc_rate(struct refclk_scale *clk_priv, + uint32_t parent_rate); +int32_t ad9361_rfpll_int_round_rate(struct refclk_scale *clk_priv, + uint32_t rate, + uint32_t *prate); +int32_t ad9361_rfpll_int_set_rate(struct refclk_scale *clk_priv, uint32_t rate, + uint32_t parent_rate); +uint32_t ad9361_rfpll_dummy_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_dummy_set_rate(struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t ad9361_rfpll_recalc_rate(struct refclk_scale *clk_priv); +int32_t ad9361_rfpll_round_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_rfpll_set_rate(struct refclk_scale *clk_priv, uint32_t rate); +int32_t ad9361_clk_mux_set_parent(struct refclk_scale *clk_priv, uint8_t index); +int32_t ad9361_tracking_control(struct ad9361_rf_phy *phy, bool bbdc_track, + bool rfdc_track, bool rxquad_track); +int32_t ad9361_bist_loopback(struct ad9361_rf_phy *phy, int32_t mode); +void ad9361_get_bist_loopback(struct ad9361_rf_phy *phy, int32_t *mode); +int32_t ad9361_bist_prbs(struct ad9361_rf_phy *phy, enum ad9361_bist_mode mode); +void ad9361_get_bist_prbs(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode); +int32_t ad9361_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode mode, uint32_t freq_Hz, + uint32_t level_dB, uint32_t mask); +void ad9361_get_bist_tone(struct ad9361_rf_phy *phy, + enum ad9361_bist_mode *mode, uint32_t *freq_Hz, + uint32_t *level_dB, uint32_t *mask); +int32_t ad9361_rf_port_setup(struct ad9361_rf_phy *phy, bool is_out, + uint32_t rx_inputs, uint32_t txb); +int32_t ad9361_mcs(struct ad9361_rf_phy *phy, int32_t step); +int32_t ad9361_do_calib_run(struct ad9361_rf_phy *phy, uint32_t cal, + int32_t arg); +int32_t ad9361_fastlock_store(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_recall(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile); +int32_t ad9361_fastlock_load(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +int32_t ad9361_fastlock_save(struct ad9361_rf_phy *phy, bool tx, + uint32_t profile, uint8_t *values); +void ad9361_ensm_force_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +uint8_t ad9361_ensm_get_state(struct ad9361_rf_phy *phy); +void ad9361_ensm_restore_state(struct ad9361_rf_phy *phy, uint8_t ensm_state); +void ad9361_ensm_restore_prev_state(struct ad9361_rf_phy *phy); +int32_t ad9361_set_trx_clock_chain_freq(struct ad9361_rf_phy *phy, + uint32_t freq); +int32_t ad9361_find_opt(uint8_t *field, uint32_t size, uint32_t *ret_start); +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable); +int32_t ad9361_dig_interface_timing_analysis(struct ad9361_rf_phy *phy, + char *buf, int32_t buflen); +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags); +int32_t ad9361_en_dis_tx(struct ad9361_rf_phy *phy, uint32_t tx_if, + uint32_t enable); +int32_t ad9361_en_dis_rx(struct ad9361_rf_phy *phy, uint32_t rx_if, + uint32_t enable); +int32_t ad9361_1rx1tx_channel_map(struct ad9361_rf_phy *phy, bool tx, + int32_t channel); +int32_t ad9361_rssi_gain_step_calib(struct ad9361_rf_phy *phy); +int32_t ad9361_set_dcxo_tune(struct ad9361_rf_phy *phy, + uint32_t coarse, uint32_t fine); +int32_t ad9361_tx_mute(struct ad9361_rf_phy *phy, uint32_t state); +uint32_t ad9361_validate_rf_bw(struct ad9361_rf_phy *phy, uint32_t bw); +int32_t ad9361_get_temp(struct ad9361_rf_phy *phy); +int ad9361_synth_lo_powerdown(struct ad9361_rf_phy *phy, + enum synth_pd_ctrl rx, + enum synth_pd_ctrl tx); +void ad9361_clear_state(struct ad9361_rf_phy *phy); +#endif diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.c b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.c new file mode 100644 index 0000000..12fc513 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.c @@ -0,0 +1,2157 @@ +/***************************************************************************//** + * @file ad9361_api.c + * @brief Implementation of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361.h" +#include "ad9361_api.h" +#include "delay.h" +#include "spi.h" +#include "util.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/************************ Constants Definitions *******************************/ +/******************************************************************************/ + +extern struct gain_table_info ad9361_adi_gt_info[]; + +/** + * Initialize the AD9361 part. + * @param ad9361_phy The AD9361 device structure. + * @param init_param The structure that contains the AD9361 initial parameters. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param) +{ + struct ad9361_rf_phy *phy; + int32_t ret = 0; + int32_t rev = 0; + int32_t i = 0; + + phy = (struct ad9361_rf_phy *)zmalloc(sizeof(*phy)); + if (!phy) { + return -ENOMEM; + } + + phy->clk_refin = (struct clk *)zmalloc(sizeof(*phy->clk_refin)); + if (!phy->clk_refin) { + return -ENOMEM; + } + + phy->pdata = (struct ad9361_phy_platform_data *)zmalloc(sizeof(*phy->pdata)); + if (!phy->pdata) { + return -ENOMEM; + } + + /* Device selection */ + phy->dev_sel = init_param->dev_sel; + + /* Reference Clock */ + phy->clk_refin->rate = init_param->reference_clk_rate; + + /* Base Configuration */ + phy->pdata->fdd = init_param->frequency_division_duplex_mode_enable; + phy->pdata->fdd_independent_mode = + init_param->frequency_division_duplex_independent_mode_enable; + phy->pdata->rx2tx2 = init_param->two_rx_two_tx_mode_enable; + phy->pdata->rx1tx1_mode_use_rx_num = init_param->one_rx_one_tx_mode_use_rx_num; + phy->pdata->rx1tx1_mode_use_tx_num = init_param->one_rx_one_tx_mode_use_tx_num; + phy->pdata->tdd_use_dual_synth = init_param->tdd_use_dual_synth_mode_enable; + phy->pdata->tdd_skip_vco_cal = init_param->tdd_skip_vco_cal_enable; + phy->pdata->rx_fastlock_delay_ns = init_param->rx_fastlock_delay_ns; + phy->pdata->tx_fastlock_delay_ns = init_param->tx_fastlock_delay_ns; + phy->pdata->trx_fastlock_pinctrl_en[0] = + init_param->rx_fastlock_pincontrol_enable; + phy->pdata->trx_fastlock_pinctrl_en[1] = + init_param->tx_fastlock_pincontrol_enable; + if (phy->dev_sel == ID_AD9363A) { + phy->pdata->use_ext_rx_lo = false; + phy->pdata->use_ext_tx_lo = false; + } else { + phy->pdata->use_ext_rx_lo = init_param->external_rx_lo_enable; + phy->pdata->use_ext_tx_lo = init_param->external_tx_lo_enable; + } + phy->pdata->dc_offset_update_events = + init_param->dc_offset_tracking_update_event_mask; + phy->pdata->dc_offset_attenuation_high = + init_param->dc_offset_attenuation_high_range; + phy->pdata->dc_offset_attenuation_low = + init_param->dc_offset_attenuation_low_range; + phy->pdata->rf_dc_offset_count_high = init_param->dc_offset_count_high_range; + phy->pdata->rf_dc_offset_count_low = init_param->dc_offset_count_low_range; + phy->pdata->split_gt = init_param->split_gain_table_mode_enable; + phy->pdata->trx_synth_max_fref = + init_param->trx_synthesizer_target_fref_overwrite_hz; + phy->pdata->qec_tracking_slow_mode_en = + init_param->qec_tracking_slow_mode_enable; + + /* ENSM Control */ + phy->pdata->ensm_pin_pulse_mode = init_param->ensm_enable_pin_pulse_mode_enable; + phy->pdata->ensm_pin_ctrl = init_param->ensm_enable_txnrx_control_enable; + + /* LO Control */ + phy->pdata->rx_synth_freq = init_param->rx_synthesizer_frequency_hz; + phy->pdata->tx_synth_freq = init_param->tx_synthesizer_frequency_hz; + phy->pdata->lo_powerdown_managed_en = + init_param->tx_lo_powerdown_managed_enable; + + /* Rate & BW Control */ + for(i = 0; i < 6; i++) { + phy->pdata->rx_path_clks[i] = init_param->rx_path_clock_frequencies[i]; + } + for(i = 0; i < 6; i++) { + phy->pdata->tx_path_clks[i] = init_param->tx_path_clock_frequencies[i]; + } + phy->pdata->rf_rx_bandwidth_Hz = init_param->rf_rx_bandwidth_hz; + phy->pdata->rf_tx_bandwidth_Hz = init_param->rf_tx_bandwidth_hz; + + /* RF Port Control */ + phy->pdata->rf_rx_input_sel = init_param->rx_rf_port_input_select; + phy->pdata->rf_tx_output_sel = init_param->tx_rf_port_input_select; + + /* TX Attenuation Control */ + phy->pdata->tx_atten = init_param->tx_attenuation_mdB; + phy->pdata->update_tx_gain_via_alert = + init_param->update_tx_gain_in_alert_enable; + + /* Reference Clock Control */ + switch (phy->dev_sel) { + case ID_AD9363A: + phy->pdata->use_extclk = true; + break; + default: + phy->pdata->use_extclk = init_param->xo_disable_use_ext_refclk_enable; + } + phy->pdata->dcxo_coarse = init_param->dcxo_coarse_and_fine_tune[0]; + phy->pdata->dcxo_fine = init_param->dcxo_coarse_and_fine_tune[1]; + phy->pdata->ad9361_clkout_mode = (enum ad9361_clkout) + init_param->clk_output_mode_select; + + /* Gain Control */ + phy->pdata->gain_ctrl.rx1_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx1_mode; + phy->pdata->gain_ctrl.rx2_mode = (enum rf_gain_ctrl_mode) + init_param->gc_rx2_mode; + phy->pdata->gain_ctrl.adc_large_overload_thresh = + init_param->gc_adc_large_overload_thresh; + phy->pdata->gain_ctrl.adc_ovr_sample_size = init_param->gc_adc_ovr_sample_size; + phy->pdata->gain_ctrl.adc_small_overload_thresh = + init_param->gc_adc_small_overload_thresh; + phy->pdata->gain_ctrl.dec_pow_measuremnt_duration = + init_param->gc_dec_pow_measurement_duration; + phy->pdata->gain_ctrl.dig_gain_en = init_param->gc_dig_gain_enable; + phy->pdata->gain_ctrl.lmt_overload_high_thresh = + init_param->gc_lmt_overload_high_thresh; + phy->pdata->gain_ctrl.lmt_overload_low_thresh = + init_param->gc_lmt_overload_low_thresh; + phy->pdata->gain_ctrl.low_power_thresh = init_param->gc_low_power_thresh; + phy->pdata->gain_ctrl.max_dig_gain = init_param->gc_max_dig_gain; + phy->pdata->gain_ctrl.use_rx_fir_out_for_dec_pwr_meas = + init_param->gc_use_rx_fir_out_for_dec_pwr_meas_enable; + + /* Gain MGC Control */ + phy->pdata->gain_ctrl.mgc_dec_gain_step = init_param->mgc_dec_gain_step; + phy->pdata->gain_ctrl.mgc_inc_gain_step = init_param->mgc_inc_gain_step; + phy->pdata->gain_ctrl.mgc_rx1_ctrl_inp_en = init_param->mgc_rx1_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_rx2_ctrl_inp_en = init_param->mgc_rx2_ctrl_inp_enable; + phy->pdata->gain_ctrl.mgc_split_table_ctrl_inp_gain_mode = + init_param->mgc_split_table_ctrl_inp_gain_mode; + + /* Gain AGC Control */ + phy->pdata->gain_ctrl.adc_large_overload_exceed_counter = + init_param->agc_adc_large_overload_exceed_counter; + phy->pdata->gain_ctrl.adc_large_overload_inc_steps = + init_param->agc_adc_large_overload_inc_steps; + phy->pdata->gain_ctrl.adc_lmt_small_overload_prevent_gain_inc = + init_param->agc_adc_lmt_small_overload_prevent_gain_inc_enable; + phy->pdata->gain_ctrl.adc_small_overload_exceed_counter = + init_param->agc_adc_small_overload_exceed_counter; + phy->pdata->gain_ctrl.dig_gain_step_size = init_param->agc_dig_gain_step_size; + phy->pdata->gain_ctrl.dig_saturation_exceed_counter = + init_param->agc_dig_saturation_exceed_counter; + phy->pdata->gain_ctrl.gain_update_interval_us = + init_param->agc_gain_update_interval_us; + phy->pdata->gain_ctrl.immed_gain_change_if_large_adc_overload = + init_param->agc_immed_gain_change_if_large_adc_overload_enable; + phy->pdata->gain_ctrl.immed_gain_change_if_large_lmt_overload = + init_param->agc_immed_gain_change_if_large_lmt_overload_enable; + phy->pdata->gain_ctrl.agc_inner_thresh_high = init_param->agc_inner_thresh_high; + phy->pdata->gain_ctrl.agc_inner_thresh_high_dec_steps = + init_param->agc_inner_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_inner_thresh_low = init_param->agc_inner_thresh_low; + phy->pdata->gain_ctrl.agc_inner_thresh_low_inc_steps = + init_param->agc_inner_thresh_low_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_large_exceed_counter = + init_param->agc_lmt_overload_large_exceed_counter; + phy->pdata->gain_ctrl.lmt_overload_large_inc_steps = + init_param->agc_lmt_overload_large_inc_steps; + phy->pdata->gain_ctrl.lmt_overload_small_exceed_counter = + init_param->agc_lmt_overload_small_exceed_counter; + phy->pdata->gain_ctrl.agc_outer_thresh_high = init_param->agc_outer_thresh_high; + phy->pdata->gain_ctrl.agc_outer_thresh_high_dec_steps = + init_param->agc_outer_thresh_high_dec_steps; + phy->pdata->gain_ctrl.agc_outer_thresh_low = init_param->agc_outer_thresh_low; + phy->pdata->gain_ctrl.agc_outer_thresh_low_inc_steps = + init_param->agc_outer_thresh_low_inc_steps; + phy->pdata->gain_ctrl.agc_attack_delay_extra_margin_us = + init_param->agc_attack_delay_extra_margin_us; + phy->pdata->gain_ctrl.sync_for_gain_counter_en = + init_param->agc_sync_for_gain_counter_enable; + + /* Fast AGC */ + phy->pdata->gain_ctrl.f_agc_dec_pow_measuremnt_duration = + init_param->fagc_dec_pow_measuremnt_duration; + phy->pdata->gain_ctrl.f_agc_state_wait_time_ns = + init_param->fagc_state_wait_time_ns; + /* Fast AGC - Low Power */ + phy->pdata->gain_ctrl.f_agc_allow_agc_gain_increase = + init_param->fagc_allow_agc_gain_increase; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_time = + init_param->fagc_lp_thresh_increment_time; + phy->pdata->gain_ctrl.f_agc_lp_thresh_increment_steps = + init_param->fagc_lp_thresh_increment_steps; + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + phy->pdata->gain_ctrl.f_agc_lock_level_lmt_gain_increase_en = + init_param->fagc_lock_level_lmt_gain_increase_en; + phy->pdata->gain_ctrl.f_agc_lock_level_gain_increase_upper_limit = + init_param->fagc_lock_level_gain_increase_upper_limit; + /* Fast AGC - Peak Detectors and Final Settling */ + phy->pdata->gain_ctrl.f_agc_lpf_final_settling_steps = + init_param->fagc_lpf_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_lmt_final_settling_steps = + init_param->fagc_lmt_final_settling_steps; + phy->pdata->gain_ctrl.f_agc_final_overrange_count = + init_param->fagc_final_overrange_count; + /* Fast AGC - Final Power Test */ + phy->pdata->gain_ctrl.f_agc_gain_increase_after_gain_lock_en = + init_param->fagc_gain_increase_after_gain_lock_en; + /* Fast AGC - Unlocking the Gain */ + phy->pdata->gain_ctrl.f_agc_gain_index_type_after_exit_rx_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_gain_index_type_after_exit_rx_mode; + phy->pdata->gain_ctrl.f_agc_use_last_lock_level_for_set_gain_en = + init_param->fagc_use_last_lock_level_for_set_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_stronger_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_optimized_gain_offset = + init_param->fagc_optimized_gain_offset; + phy->pdata->gain_ctrl.f_agc_rst_gla_stronger_sig_thresh_above_ll = + init_param->fagc_rst_gla_stronger_sig_thresh_above_ll; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_exceeded_en = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_goto_optim_gain_en = + init_param->fagc_rst_gla_engergy_lost_goto_optim_gain_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_engergy_lost_sig_thresh_below_ll = + init_param->fagc_rst_gla_engergy_lost_sig_thresh_below_ll; + phy->pdata->gain_ctrl.f_agc_energy_lost_stronger_sig_gain_lock_exit_cnt = + init_param->fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_adc_overload_en = + init_param->fagc_rst_gla_large_adc_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_large_lmt_overload_en = + init_param->fagc_rst_gla_large_lmt_overload_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_en_agc_pulled_high_en = + init_param->fagc_rst_gla_en_agc_pulled_high_en; + phy->pdata->gain_ctrl.f_agc_rst_gla_if_en_agc_pulled_high_mode = + (enum f_agc_target_gain_index_type) + init_param->fagc_rst_gla_if_en_agc_pulled_high_mode; + phy->pdata->gain_ctrl.f_agc_power_measurement_duration_in_state5 = + init_param->fagc_power_measurement_duration_in_state5; + phy->pdata->gain_ctrl.f_agc_large_overload_inc_steps = + init_param->fagc_large_overload_inc_steps; + + /* RSSI Control */ + phy->pdata->rssi_ctrl.rssi_delay = init_param->rssi_delay; + phy->pdata->rssi_ctrl.rssi_duration = init_param->rssi_duration; + phy->pdata->rssi_ctrl.restart_mode = (enum rssi_restart_mode) + init_param->rssi_restart_mode; + phy->pdata->rssi_ctrl.rssi_unit_is_rx_samples = + init_param->rssi_unit_is_rx_samples_enable; + phy->pdata->rssi_ctrl.rssi_wait = init_param->rssi_wait; + + /* Aux ADC Control */ + phy->pdata->auxadc_ctrl.auxadc_decimation = init_param->aux_adc_decimation; + phy->pdata->auxadc_ctrl.auxadc_clock_rate = init_param->aux_adc_rate; + + /* AuxDAC Control */ + phy->pdata->auxdac_ctrl.auxdac_manual_mode_en = + init_param->aux_dac_manual_mode_enable; + phy->pdata->auxdac_ctrl.dac1_default_value = + init_param->aux_dac1_default_value_mV; + phy->pdata->auxdac_ctrl.dac1_in_rx_en = + init_param->aux_dac1_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac1_in_tx_en = + init_param->aux_dac1_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac1_in_alert_en = + init_param->aux_dac1_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac1_rx_delay_us = init_param->aux_dac1_rx_delay_us; + phy->pdata->auxdac_ctrl.dac1_tx_delay_us = init_param->aux_dac1_tx_delay_us; + phy->pdata->auxdac_ctrl.dac2_default_value = + init_param->aux_dac2_default_value_mV; + phy->pdata->auxdac_ctrl.dac2_in_rx_en = + init_param->aux_dac2_active_in_rx_enable; + phy->pdata->auxdac_ctrl.dac2_in_tx_en = + init_param->aux_dac2_active_in_tx_enable; + phy->pdata->auxdac_ctrl.dac2_in_alert_en = + init_param->aux_dac2_active_in_alert_enable; + phy->pdata->auxdac_ctrl.dac2_rx_delay_us = init_param->aux_dac2_rx_delay_us; + phy->pdata->auxdac_ctrl.dac2_tx_delay_us = init_param->aux_dac2_tx_delay_us; + + /* Temperature Sensor Control */ + phy->pdata->auxadc_ctrl.temp_sensor_decimation = + init_param->temp_sense_decimation; + phy->pdata->auxadc_ctrl.temp_time_inteval_ms = + init_param->temp_sense_measurement_interval_ms; + phy->pdata->auxadc_ctrl.offset = init_param->temp_sense_offset_signed; + phy->pdata->auxadc_ctrl.periodic_temp_measuremnt = + init_param->temp_sense_periodic_measurement_enable; + + /* Control Out Setup */ + phy->pdata->ctrl_outs_ctrl.en_mask = init_param->ctrl_outs_enable_mask; + phy->pdata->ctrl_outs_ctrl.index = init_param->ctrl_outs_index; + + /* External LNA Control */ + phy->pdata->elna_ctrl.settling_delay_ns = init_param->elna_settling_delay_ns; + phy->pdata->elna_ctrl.gain_mdB = init_param->elna_gain_mdB; + phy->pdata->elna_ctrl.bypass_loss_mdB = init_param->elna_bypass_loss_mdB; + phy->pdata->elna_ctrl.elna_1_control_en = + init_param->elna_rx1_gpo0_control_enable; + phy->pdata->elna_ctrl.elna_2_control_en = + init_param->elna_rx2_gpo1_control_enable; + phy->pdata->elna_ctrl.elna_in_gaintable_all_index_en = + init_param->elna_gaintable_all_index_enable; + + /* Digital Interface Control */ + phy->pdata->dig_interface_tune_skipmode = + (init_param->digital_interface_tune_skip_mode); + phy->pdata->dig_interface_tune_fir_disable = + (init_param->digital_interface_tune_fir_disable); + phy->pdata->port_ctrl.pp_conf[0] = (init_param->pp_tx_swap_enable << 7); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->pp_rx_swap_enable << 6); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->tx_channel_swap_enable << 5); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_channel_swap_enable << 4); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->rx_frame_pulse_mode_enable << + 3); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->two_t_two_r_timing_enable << + 2); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_bus_enable << 1); + phy->pdata->port_ctrl.pp_conf[0] |= (init_param->invert_data_clk_enable << 0); + phy->pdata->port_ctrl.pp_conf[1] = (init_param->fdd_alt_word_order_enable << 7); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->invert_rx_frame_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] = (init_param->fdd_rx_rate_2tx_enable << 7); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->swap_ports_enable << 6); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_data_rate_enable << 5); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->lvds_mode_enable << 4); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->half_duplex_mode_enable << 3); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->single_port_mode_enable << 2); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_port_enable << 1); + phy->pdata->port_ctrl.pp_conf[2] |= (init_param->full_duplex_swap_bits_enable << + 0); + phy->pdata->port_ctrl.pp_conf[1] |= (init_param->delay_rx_data & 0x3); + phy->pdata->port_ctrl.rx_clk_data_delay = DATA_CLK_DELAY( + init_param->rx_data_clock_delay); + phy->pdata->port_ctrl.rx_clk_data_delay |= RX_DATA_DELAY( + init_param->rx_data_delay); + phy->pdata->port_ctrl.tx_clk_data_delay = FB_CLK_DELAY( + init_param->tx_fb_clock_delay); + phy->pdata->port_ctrl.tx_clk_data_delay |= TX_DATA_DELAY( + init_param->tx_data_delay); + phy->pdata->port_ctrl.lvds_bias_ctrl = ((init_param->lvds_bias_mV - 75) / 75) & + 0x7; + phy->pdata->port_ctrl.lvds_bias_ctrl |= + (init_param->lvds_rx_onchip_termination_enable << 5); + phy->pdata->rx1rx2_phase_inversion_en = init_param->rx1rx2_phase_inversion_en; + + /* GPO Control */ + phy->pdata->gpo_ctrl.gpo_manual_mode_en = + init_param->gpo_manual_mode_enable; + phy->pdata->gpo_ctrl.gpo_manual_mode_enable_mask = + init_param->gpo_manual_mode_enable_mask; + phy->pdata->gpo_ctrl.gpo0_inactive_state_high_en = + init_param->gpo0_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo1_inactive_state_high_en = + init_param->gpo1_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo2_inactive_state_high_en = + init_param->gpo2_inactive_state_high_enable; + phy->pdata->gpo_ctrl.gpo3_inactive_state_high_en = + init_param->gpo3_inactive_state_high_enable; + + phy->pdata->gpo_ctrl.gpo0_slave_rx_en = init_param->gpo0_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo0_slave_tx_en = init_param->gpo0_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_rx_en = init_param->gpo1_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo1_slave_tx_en = init_param->gpo1_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_rx_en = init_param->gpo2_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo2_slave_tx_en = init_param->gpo2_slave_tx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_rx_en = init_param->gpo3_slave_rx_enable; + phy->pdata->gpo_ctrl.gpo3_slave_tx_en = init_param->gpo3_slave_tx_enable; + + phy->pdata->gpo_ctrl.gpo0_rx_delay_us = init_param->gpo0_rx_delay_us; + phy->pdata->gpo_ctrl.gpo0_tx_delay_us = init_param->gpo0_tx_delay_us; + phy->pdata->gpo_ctrl.gpo1_rx_delay_us = init_param->gpo1_rx_delay_us; + phy->pdata->gpo_ctrl.gpo1_tx_delay_us = init_param->gpo1_tx_delay_us; + phy->pdata->gpo_ctrl.gpo2_rx_delay_us = init_param->gpo2_rx_delay_us; + phy->pdata->gpo_ctrl.gpo2_tx_delay_us = init_param->gpo2_tx_delay_us; + phy->pdata->gpo_ctrl.gpo3_rx_delay_us = init_param->gpo3_rx_delay_us; + phy->pdata->gpo_ctrl.gpo3_tx_delay_us = init_param->gpo3_tx_delay_us; + + /* Tx Monitor Control */ + phy->pdata->txmon_ctrl.low_high_gain_threshold_mdB = + init_param->low_high_gain_threshold_mdB; + phy->pdata->txmon_ctrl.low_gain_dB = init_param->low_gain_dB; + phy->pdata->txmon_ctrl.high_gain_dB = init_param->high_gain_dB; + phy->pdata->txmon_ctrl.tx_mon_track_en = init_param->tx_mon_track_en; + phy->pdata->txmon_ctrl.one_shot_mode_en = init_param->one_shot_mode_en; + phy->pdata->txmon_ctrl.tx_mon_delay = init_param->tx_mon_delay; + phy->pdata->txmon_ctrl.tx_mon_duration = init_param->tx_mon_duration; + phy->pdata->txmon_ctrl.tx1_mon_front_end_gain = + init_param->tx1_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx2_mon_front_end_gain = + init_param->tx2_mon_front_end_gain; + phy->pdata->txmon_ctrl.tx1_mon_lo_cm = init_param->tx1_mon_lo_cm; + phy->pdata->txmon_ctrl.tx2_mon_lo_cm = init_param->tx2_mon_lo_cm; + + phy->pdata->debug_mode = true; + + gpio_get(&phy->gpio_desc_resetb, &init_param->gpio_resetb); + /* Optional: next three GPIOs are used for MCS synchronization */ + gpio_get_optional(&phy->gpio_desc_sync, &init_param->gpio_sync); + gpio_get_optional(&phy->gpio_desc_cal_sw1, &init_param->gpio_cal_sw1); + gpio_get_optional(&phy->gpio_desc_cal_sw2, &init_param->gpio_cal_sw2); + + gpio_direction_output(phy->gpio_desc_resetb, 0); + + spi_init(&phy->spi, &init_param->spi_param); + + phy->pdata->port_ctrl.digital_io_ctrl = 0; + phy->pdata->port_ctrl.lvds_invert[0] = init_param->lvds_invert1_control; + phy->pdata->port_ctrl.lvds_invert[1] = init_param->lvds_invert2_control; + + if (AD9364_DEVICE) { + phy->pdata->rx2tx2 = false; + phy->pdata->rx1tx1_mode_use_rx_num = 1; + phy->pdata->rx1tx1_mode_use_tx_num = 1; + } + + phy->rx_eq_2tx = false; + + phy->current_table = -1; + phy->bypass_tx_fir = true; + phy->bypass_rx_fir = true; + phy->rate_governor = 1; + phy->rfdc_track_en = true; + phy->bbdc_track_en = true; + phy->quad_track_en = true; + + phy->gt_info = ad9361_adi_gt_info; + + phy->bist_loopback_mode = 0; + phy->bist_config = 0; + phy->bist_prbs_mode = BIST_DISABLE; + phy->bist_tone_mode = BIST_DISABLE; + phy->bist_tone_freq_Hz = 0; + phy->bist_tone_level_dB = 0; + phy->bist_tone_mask = 0; + + ad9361_reset(phy); + + ret = ad9361_spi_read(phy->spi, REG_PRODUCT_ID); + if ((ret & PRODUCT_ID_MASK) != PRODUCT_ID_9361) { + printf("%s : Unsupported PRODUCT_ID 0x%X", __func__, (unsigned int)ret); + ret = -ENODEV; + goto out; + } + rev = ret & REV_MASK; + + phy->ad9361_rfpll_ext_recalc_rate = init_param->ad9361_rfpll_ext_recalc_rate; + phy->ad9361_rfpll_ext_round_rate = init_param->ad9361_rfpll_ext_round_rate; + phy->ad9361_rfpll_ext_set_rate = init_param->ad9361_rfpll_ext_set_rate; + + ret = ad9361_register_clocks(phy); + if (ret < 0) + goto out; + + ret = ad9361_setup(phy); + if (ret < 0) + goto out_clk; + + printf("%s : AD936x Rev %d successfully initialized\n", __func__, (int)rev); + + *ad9361_phy = phy; + + return 0; + +out_clk: + ad9361_unregister_clocks(phy); +out: + free(phy->clk_refin); + free(phy->pdata); + free(phy); + printf("%s : AD936x initialization error\n", __func__); + + return -ENODEV; +} + +/** + * Free the allocated resources. + * @param phy The AD9361 current state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy) +{ + ad9361_unregister_clocks(phy); + spi_remove(phy->spi); + gpio_remove(phy->gpio_desc_resetb); + gpio_remove(phy->gpio_desc_sync); + gpio_remove(phy->gpio_desc_cal_sw1); + gpio_remove(phy->gpio_desc_cal_sw2); + free(phy->clk_refin); + free(phy->pdata); + free(phy); + + return 0; +} + +/** + * Set the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode The ENSM mode. + * Accepted values: + * ENSM_MODE_TX + * ENSM_MODE_RX + * ENSM_MODE_ALERT + * ENSM_MODE_FDD + * ENSM_MODE_WAIT + * ENSM_MODE_SLEEP + * ENSM_MODE_PINCTRL + * ENSM_MODE_PINCTRL_FDD_INDEP + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + uint8_t ensm_state; + bool pinctrl = false; + + phy->pdata->fdd_independent_mode = false; + + switch (mode) { + case ENSM_MODE_TX: + ensm_state = ENSM_STATE_TX; + break; + case ENSM_MODE_RX: + ensm_state = ENSM_STATE_RX; + break; + case ENSM_MODE_ALERT: + ensm_state = ENSM_STATE_ALERT; + break; + case ENSM_MODE_FDD: + ensm_state = ENSM_STATE_FDD; + break; + case ENSM_MODE_WAIT: + ensm_state = ENSM_STATE_SLEEP_WAIT; + break; + case ENSM_MODE_SLEEP: + ensm_state = ENSM_STATE_SLEEP; + break; + case ENSM_MODE_PINCTRL: + ensm_state = ENSM_STATE_SLEEP_WAIT; + pinctrl = true; + break; + case ENSM_MODE_PINCTRL_FDD_INDEP: + ensm_state = ENSM_STATE_FDD; + phy->pdata->fdd_independent_mode = true; + break; + default: + return -EINVAL; + } + + ad9361_set_ensm_mode(phy, phy->pdata->fdd, pinctrl); + ret = ad9361_ensm_set_state(phy, ensm_state, pinctrl); + + return ret; +} + +/** + * Get the Enable State Machine (ENSM) mode. + * @param phy The AD9361 current state structure. + * @param mode A variable to store the selected ENSM mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + uint8_t ensm_state; + bool pinctrl = false; + int32_t ret; + + ensm_state = ad9361_spi_read(phy->spi, REG_STATE); + ensm_state &= ENSM_STATE(~0); + ret = ad9361_spi_read(phy->spi, REG_ENSM_CONFIG_1); + if ((ret & ENABLE_ENSM_PIN_CTRL) == ENABLE_ENSM_PIN_CTRL) + pinctrl = true; + + switch (ensm_state) { + case ENSM_STATE_TX: + *mode = ENSM_MODE_TX; + break; + case ENSM_STATE_RX: + *mode = ENSM_MODE_RX; + break; + case ENSM_STATE_ALERT: + *mode = ENSM_MODE_ALERT; + break; + case ENSM_STATE_FDD: + if (phy->pdata->fdd_independent_mode) + *mode = ENSM_MODE_PINCTRL_FDD_INDEP; + else + *mode = ENSM_MODE_FDD; + break; + case ENSM_STATE_SLEEP_WAIT: + if (pinctrl) + *mode = ENSM_MODE_PINCTRL; + else + *mode = ENSM_MODE_WAIT; + break; + case ENSM_STATE_SLEEP: + *mode = ENSM_MODE_SLEEP; + break; + default: + return -EINVAL; + } + + return 0; +} + +/** + * Set the receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db The RF gain (dB). + * Example: + * 10 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + rx_gain.gain_db = gain_db; + ret = ad9361_set_rx_gain(phy, + ad9361_1rx1tx_channel_map(phy, false, + ch + 1), &rx_gain); + + return ret; +} + +/** + * Get current receive RF gain for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gain_db A variable to store the RF gain (dB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, + uint8_t ch, int32_t *gain_db) +{ + struct rf_rx_gain rx_gain = {0, 0, 0, 0, 0, 0, 0, 0, 0}; + int32_t ret = 0; + + ret = ad9361_get_rx_gain(phy, ad9361_1rx1tx_channel_map(phy, + false, ch + 1), &rx_gain); + + *gain_db = rx_gain.gain_db; + + return ret; +} + +/** + * Set the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_rx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, bandwidth_hz, + phy->current_tx_bw_Hz); + else + ret = 0; + + return ret; +} + +/** + * Get the RX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_rx_bw_Hz; + + return 0; +} + +/** + * Set the RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current RX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[RX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[RX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current RX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[RX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_rx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[RX_RFPLL], int_ext); +} + +/** + * Get the RSSI for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param rssi A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, struct rf_rssi *rssi) +{ + int32_t ret; + + rssi->ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + rssi->duration = 1; + ret = ad9361_read_rssi(phy, rssi); + + return ret; +} + +/** + * Set the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values in 2x2 mode: + * RX1 (0) + * RX2 (1) + * Accepted values in 1x1 mode: + * RX1 (0) + * @param gc_mode The gain control mode (manual, fast_attack, slow_attack, + * hybrid). + * Accepted values: + * RF_GAIN_MGC (manual) + * RF_GAIN_FASTATTACK_AGC (fast_attack) + * RF_GAIN_SLOWATTACK_AGC (slow_attack) + * RF_GAIN_HYBRID_AGC (hybrid) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t gc_mode) +{ + struct rf_gain_ctrl gc = {0, 0}; + + gc.ant = ad9361_1rx1tx_channel_map(phy, false, ch + 1); + gc.mode = phy->agc_mode[ch] = gc_mode; + + ad9361_set_gain_ctrl_mode(phy, &gc); + + return 0; +} + +/** + * Get the gain control mode for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param gc_mode A variable to store the gain control mode. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, + uint8_t ch, uint8_t *gc_mode) +{ + *gc_mode = phy->agc_mode[ch]; + + return 0; +} + +/** + * Set the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->rx_fir_dec = fir_cfg.rx_dec; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)(fir_cfg.rx | FIR_IS_RX), + fir_cfg.rx_gain, fir_cfg.rx_coef_size, fir_cfg.rx_coef); + + return ret; +} + +/** + * Get the RX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param rx_ch The selected RX channel (RX1, RX2). + * Accepted values: + * RX1 (0) + * RX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + rx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_CONFIG); + if(ret < 0) + return ret; + fir_conf = ret; + + fir_cfg->rx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_GAIN); + if(ret < 0) + return ret; + fir_cfg->rx_gain = -6 * (ret & FILTER_GAIN(3)) + 6; + fir_cfg->rx = rx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(rx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_RX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_RX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->rx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_RX_FILTER_CONFIG, fir_conf); + + fir_cfg->rx_dec = phy->rx_fir_dec; + + return 0; +} + +/** + * Enable/disable the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_rx_fir == !en_dis) + return ret; + + phy->bypass_rx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + } + + return ret; +} + +/** + * Get the status of the RX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_rx_fir; + + return 0; +} + +/** + * Enable/disable the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->rfdc_track_en == en_dis) + return ret; + + phy->rfdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX RFDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->rfdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bbdc_track_en == en_dis) + return ret; + + phy->bbdc_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX BasebandDC Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->bbdc_track_en; + + return 0; +} + +/** + * Enable/disable the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->quad_track_en == en_dis) + return ret; + + phy->quad_track_en = en_dis; + ret = ad9361_tracking_control(phy, phy->bbdc_track_en, + phy->rfdc_track_en, phy->quad_track_en); + + return ret; +} + +/** + * Get the status of the RX Quadrature Tracking. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->quad_track_en; + + return 0; +} + +/** + * Set the RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * A_BALANCED (0 - (RX1A_N & RX1A_P) and (RX2A_N & RX2A_P) enabled; balanced) + * B_BALANCED (1 - (RX1B_N & RX1B_P) and (RX2B_N & RX2B_P) enabled; balanced) + * C_BALANCED (2 - (RX1C_N & RX1C_P) and (RX2C_N & RX2C_P) enabled; balanced) + * A_N (3 - RX1A_N and RX2A_N enabled; unbalanced) + * A_P (4 - RX1A_P and RX2A_P enabled; unbalanced) + * B_N (5 - RX1B_N and RX2B_N enabled; unbalanced) + * B_P (6 - RX1B_P and RX2B_P enabled; unbalanced) + * C_N (7 - RX1C_N and RX2C_N enabled; unbalanced) + * C_P (8 - RX1C_P and RX2C_P enabled; unbalanced) + * TX_MON1 (9 - TX_MONITOR1) + * TX_MON2 (10 - TX_MONITOR2) + * TX_MON1_2 (11 - TX_MONITOR1 & TX_MONITOR2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_rx_input_sel = mode; + + ret = ad9361_rf_port_setup(phy, false, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected RX RF input port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_rx_input_sel; + + return 0; +} + +/** + * Store RX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_rx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 0, profile); +} + +/** + * Recall specified RX fastlock profile. + * When in fastlock pin select mode (init_param->rx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 0, profile); +} + +/** + * Load RX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 0, profile, values); +} + +/** + * Save RX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 0, profile, values); +} + +/** + * Power down the RX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, option ? LO_OFF : LO_ON, LO_DONTCARE); +} + +/** + * Get the RX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[1] & RX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb The attenuation (mdB). + * Example: + * 10000 (10 dB) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t attenuation_mdb) +{ + int32_t ret; + int32_t channel; + + channel = ad9361_1rx1tx_channel_map(phy, true, ch); + ret = ad9361_set_tx_atten(phy, attenuation_mdb, + channel == 0, channel == 1, + !phy->pdata->update_tx_gain_via_alert); + + return ret; +} + +/** + * Get current transmit attenuation for the selected channel. + * @param phy The AD9361 current state structure. + * @param ch The desired channel number (TX1, TX2). + * Accepted values in 2x2 mode: + * TX1 (0) + * TX2 (1) + * Accepted values in 1x1 mode: + * TX1 (0) + * @param attenuation_mdb A variable to store the attenuation value (mdB). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, + uint8_t ch, uint32_t *attenuation_mdb) +{ + int32_t ret; + + ret = ad9361_get_tx_atten(phy, + ad9361_1rx1tx_channel_map(phy, true, + ch + 1)); + + if(ret < 0) + return ret; + *attenuation_mdb = ret; + + return 0; +} + +/** + * Set the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz The desired bandwidth (Hz). + * Example: + * 18000000 (18 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz) +{ + int32_t ret = 0; + + bandwidth_hz = ad9361_validate_rf_bw(phy, bandwidth_hz); + + if (phy->current_tx_bw_Hz != bandwidth_hz) + ret = ad9361_update_rf_bandwidth(phy, + phy->current_rx_bw_Hz, bandwidth_hz); + else + ret = 0; + + return ret; +} + +/** + * Get the TX RF bandwidth. + * @param phy The AD9361 current state structure. + * @param bandwidth_hz A variable to store the bandwidth value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz) +{ + *bandwidth_hz = phy->current_tx_bw_Hz; + + return 0; +} + +/** + * Set the TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz The desired frequency (Hz). + * Example: + * 30720000 (30.72 MHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz) +{ + int32_t ret; + uint32_t rx[6], tx[6]; + + ret = ad9361_calculate_rf_clock_chain(phy, sampling_freq_hz, + phy->rate_governor, rx, tx); + if (ret < 0) + return ret; + + ad9361_set_trx_clock_chain(phy, rx, tx); + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get current TX sampling frequency. + * @param phy The AD9361 current state structure. + * @param sampling_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz) +{ + *sampling_freq_hz = (uint32_t)clk_get_rate(phy, + phy->ref_clk_scale[TX_SAMPL_CLK]); + + return 0; +} + +/** + * Set the TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz The desired frequency (Hz). + * Example: + * 2400000000 (2.4 GHz) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t lo_freq_hz) +{ + int32_t ret; + + ret = clk_set_rate(phy, phy->ref_clk_scale[TX_RFPLL], + ad9361_to_clk(lo_freq_hz)); + + return ret; +} + +/** + * Get current TX LO frequency. + * @param phy The AD9361 current state structure. + * @param lo_freq_hz A variable to store the frequency value (Hz). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, + uint64_t *lo_freq_hz) +{ + *lo_freq_hz = ad9361_from_clk(clk_get_rate(phy, + phy->ref_clk_scale[TX_RFPLL])); + + return 0; +} + +/** + * Switch between internal and external LO. + * @param phy The AD9361 state structure. + * @param int_ext The selected lo (INT_LO, EXT_LO). + * Accepted values: + * INT_LO + * EXT_LO + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext) +{ + if ((phy->dev_sel == ID_AD9363A) && (int_ext == EXT_LO)) { + printf("%s : EXT_LO is not supported by AD9363!\n", __func__); + return -1; + } + + phy->pdata->use_ext_tx_lo = int_ext; + + return ad9361_clk_mux_set_parent(phy->ref_clk_scale[TX_RFPLL], int_ext); +} + +/** + * Set the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param fir_cfg FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg) +{ + int32_t ret; + + phy->tx_fir_int = fir_cfg.tx_int; + ret = ad9361_load_fir_filter_coef(phy, (enum fir_dest)fir_cfg.tx, + fir_cfg.tx_gain, fir_cfg.tx_coef_size, fir_cfg.tx_coef); + + return ret; +} + +/** + * Get the TX FIR filter configuration. + * @param phy The AD9361 current state structure. + * @param tx_ch The selected TX channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param fir_cfg FIR filter configuration output file. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg) +{ + int32_t ret; + uint32_t fir_conf; + uint8_t index; + + tx_ch += 1; + + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_CONF); + if(ret < 0) + return ret; + fir_conf = ret; + fir_cfg->tx_coef_size = (((fir_conf & FIR_NUM_TAPS(7)) >> 5) + 1) * 16; + fir_cfg->tx_gain = -6 * (fir_conf & TX_FIR_GAIN_6DB); + fir_cfg->tx = tx_ch; + + fir_conf &= ~FIR_SELECT(3); + fir_conf |= FIR_SELECT(tx_ch) | FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + for(index = 0; index < 128; index++) { + ad9361_spi_write(phy->spi, REG_TX_FILTER_COEF_ADDR, index); + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_1); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] = ret; + ret = ad9361_spi_read(phy->spi, REG_TX_FILTER_COEF_READ_DATA_2); + if(ret < 0) + return ret; + fir_cfg->tx_coef[index] |= (ret << 8); + } + + fir_conf &= ~FIR_START_CLK; + ad9361_spi_write(phy->spi, REG_TX_FILTER_CONF, fir_conf); + + fir_cfg->tx_int = phy->tx_fir_int; + + return 0; +} + +/** + * Enable/disable the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if(phy->bypass_tx_fir == !en_dis) + return ret; + + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Get the status of the TX FIR filter. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = !phy->bypass_tx_fir; + + return 0; +} + +/** + * Get the TX RSSI for the selected channel (TX_MON should be enabled). + * @param phy The AD9361 current state structure. + * @param ch The desired channel (TX1, TX2). + * Accepted values: + * TX1 (0) + * TX2 (1) + * @param rssi_db_x_1000 A variable to store the RSSI. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, + uint8_t ch, + uint32_t *rssi_db_x_1000) +{ + uint8_t reg_val_buf[3]; + uint32_t val; + int32_t ret; + + ret = ad9361_spi_readm(phy->spi, REG_TX_RSSI_LSB, + reg_val_buf, ARRAY_SIZE(reg_val_buf)); + if (ret < 0) { + return ret; + } + + switch (ch) { + case 0: + val = (reg_val_buf[2] << 1) | (reg_val_buf[0] & TX_RSSI_1); + break; + case 1: + val = (reg_val_buf[1] << 1) | ((reg_val_buf[0] & TX_RSSI_2) >> 1); + break; + default: + return -EINVAL; + } + + val *= RSSI_RESOLUTION; + + *rssi_db_x_1000 = ((val / RSSI_MULTIPLIER) * 1000) + + (val % RSSI_MULTIPLIER); + + return 0; +} + +/** + * Set the TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * Accepted values: + * TXA (0) + * TXB (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t mode) +{ + int32_t ret; + + phy->pdata->rf_tx_output_sel = mode; + + ret = ad9361_rf_port_setup(phy, true, + phy->pdata->rf_rx_input_sel, + phy->pdata->rf_tx_output_sel); + + return ret; +} + +/** + * Get the selected TX RF output port. + * @param phy The AD9361 current state structure. + * @param mode The RF port. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode) +{ + *mode = phy->pdata->rf_tx_output_sel; + + return 0; +} + +/** + * Enable/disable the auto calibration. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + if (en_dis == 0) + phy->auto_cal_en = 0; + else + phy->auto_cal_en = 1; + + return 0; +} + +/** + * Get the status of the auto calibration flag. + * @param phy The AD9361 current state structure. + * @param en_dis The enable/disable status buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis) +{ + *en_dis = phy->auto_cal_en; + + return 0; +} + +/** + * Store TX fastlock profile. + * To create a profile tune the synthesizer (ad9361_set_tx_lo_freq()) and then + * call this function specifying the target profile number. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_store(phy, 1, profile); +} + +/** + * Recall specified TX fastlock profile. + * When in fastlock pin select mode (init_param->tx_fastlock_pincontrol_enable), + * the function needs to be called before then the pin-control can be used. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile) +{ + return ad9361_fastlock_recall(phy, 1, profile); +} + +/** + * Load TX fastlock profile. A previously saved profile can be loaded in any + * of the 8 available slots. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * Example: + * val0,val1,val2,…,val15 + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_load(phy, 1, profile, values); +} + +/** + * Save TX fastlock profile. In order to use more than 8 Profiles, an existing + * profile can be read back and stored by the user application. + * @param phy The AD9361 state structure. + * @param profile The profile number (0 - 7). + * Accepted values: + * 0 - 7 + * @param values Fastlock profile program data. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values) +{ + return ad9361_fastlock_save(phy, 1, profile, values); +} + +/** + * Power down the TX Local Oscillator. + * @param phy The AD9361 state structure. + * @param option The option (ON, OFF). + * Accepted values: + * ON (0) + * OFF (1) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option) +{ + return ad9361_synth_lo_powerdown(phy, LO_DONTCARE, option ? LO_OFF : LO_ON); +} + +/** + * Get the TX Local Oscillator power status. + * @param phy The AD9361 state structure. + * @param option Store the option (ON, OFF). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option) +{ + *option = !(phy->cached_synth_pd[0] & TX_LO_POWER_DOWN) ? OFF : ON; + + return 0; +} + +/** + * Set the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + int32_t ret; + + ret = ad9361_set_trx_clock_chain(phy, rx_path_clks, tx_path_clks); + if (ret < 0) + return ret; + + ret = ad9361_update_rf_bandwidth(phy, phy->current_rx_bw_Hz, + phy->current_tx_bw_Hz); + + return ret; +} + +/** + * Get the RX and TX path rates. + * @param phy The AD9361 state structure. + * @param rx_path_clks RX path rates buffer. + * @param tx_path_clks TX path rates buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, + uint32_t *tx_path_clks) +{ + return ad9361_get_trx_clock_chain(phy, rx_path_clks, tx_path_clks); +} + +/** + * Set the number of channels mode. + * @param phy The AD9361 state structure. + * Note: This function also resets the device, some additional + * configurations might be necessary + * @param no_ch_mode Number of channels mode (MODE_1x1, MODE_2x2). + * Accepted values: + * MODE_1x1 (1) + * MODE_2x2 (2) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode) +{ + switch (no_ch_mode) { + case 1: + phy->pdata->rx2tx2 = 0; + break; + case 2: + phy->pdata->rx2tx2 = 1; + break; + default: + return -EINVAL; + } + + ad9361_reset(phy); + ad9361_spi_write(phy->spi, REG_SPI_CONF, SOFT_RESET | _SOFT_RESET); + ad9361_spi_write(phy->spi, REG_SPI_CONF, 0x0); + + ad9361_clear_state(phy); + + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[TX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_REFCLK], phy->clk_refin->rate); + phy->clks[RX_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_REFCLK], phy->clk_refin->rate); + phy->clks[BB_REFCLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[BB_REFCLK], phy->clk_refin->rate); + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate( + phy->ref_clk_scale[BBPLL_CLK], phy->clks[BB_REFCLK]->rate); + phy->clks[ADC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[ADC_CLK], phy->clks[BBPLL_CLK]->rate); + phy->clks[R2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R2_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[R1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[R1_CLK], phy->clks[R2_CLK]->rate); + phy->clks[CLKRF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKRF_CLK], phy->clks[R1_CLK]->rate); + phy->clks[RX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[RX_SAMPL_CLK], phy->clks[CLKRF_CLK]->rate); + phy->clks[DAC_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[DAC_CLK], phy->clks[ADC_CLK]->rate); + phy->clks[T2_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T2_CLK], phy->clks[DAC_CLK]->rate); + phy->clks[T1_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[T1_CLK], phy->clks[T2_CLK]->rate); + phy->clks[CLKTF_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[CLKTF_CLK], phy->clks[T1_CLK]->rate); + phy->clks[TX_SAMPL_CLK]->rate = ad9361_clk_factor_recalc_rate( + phy->ref_clk_scale[TX_SAMPL_CLK], phy->clks[CLKTF_CLK]->rate); + phy->clks[RX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_INT], phy->clks[RX_REFCLK]->rate); + phy->clks[TX_RFPLL_INT]->rate = ad9361_rfpll_int_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_INT], phy->clks[TX_REFCLK]->rate); + phy->clks[RX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[RX_RFPLL_DUMMY]); + phy->clks[TX_RFPLL_DUMMY]->rate = ad9361_rfpll_dummy_recalc_rate( + phy->ref_clk_scale[TX_RFPLL_DUMMY]); + phy->clks[RX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[RX_RFPLL]); + phy->clks[TX_RFPLL]->rate = ad9361_rfpll_recalc_rate( + phy->ref_clk_scale[TX_RFPLL]); + + ad9361_setup(phy); +#ifndef AXI_ADC_NOT_PRESENT + /* platform specific wrapper to call ad9361_post_setup() */ + ad9361_post_setup(phy); +#endif + + return 0; +} + +/** + * Do multi chip synchronization. + * @param phy_master The AD9361 Master state structure. + * @param phy_slave The AD9361 Slave state structure. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave) +{ + uint32_t ensm_mode; + int32_t step; + int32_t reg; + + if ((phy_master->dev_sel == ID_AD9363A) || + (phy_slave->dev_sel == ID_AD9363A)) { + printf("%s : MCS is not supported by AD9363!\n", __func__); + return -1; + } + + reg = ad9361_spi_read(phy_master->spi, REG_RX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_RX_CLOCK_DATA_DELAY, reg); + reg = ad9361_spi_read(phy_master->spi, REG_TX_CLOCK_DATA_DELAY); + ad9361_spi_write(phy_slave->spi, REG_TX_CLOCK_DATA_DELAY, reg); + + ad9361_get_en_state_machine_mode(phy_master, &ensm_mode); + + ad9361_set_en_state_machine_mode(phy_master, ENSM_MODE_ALERT); + ad9361_set_en_state_machine_mode(phy_slave, ENSM_MODE_ALERT); + + for (step = 0; step <= 5; step++) { + ad9361_mcs(phy_slave, step); + ad9361_mcs(phy_master, step); + mdelay(100); + } + + ad9361_set_en_state_machine_mode(phy_master, ensm_mode); + ad9361_set_en_state_machine_mode(phy_slave, ensm_mode); + + return 0; +} + +/** + * Enable/disable the TRX FIR filters. + * @param phy The AD9361 current state structure. + * @param en_dis The option (ENABLE, DISABLE). + * Accepted values: + * ENABLE (1) + * DISABLE (0) + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis) +{ + int32_t ret = 0; + + if ((phy->bypass_rx_fir == phy->bypass_tx_fir) && + (phy->bypass_rx_fir == !en_dis)) + return ret; + + phy->bypass_rx_fir = !en_dis; + phy->bypass_tx_fir = !en_dis; + ret = ad9361_validate_enable_fir(phy); + if (ret < 0) { + phy->bypass_rx_fir = true; + phy->bypass_tx_fir = true; + } + + return ret; +} + +/** + * Set the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov OSR rate governor (highest, nominal). + * Accepted values: + * HIGHEST_OSR (0 - highest OSR) + * NOMINAL_OSR (1 - nominal) + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov) +{ + if (rate_gov == 0) + phy->rate_governor = 0; + else + phy->rate_governor = 1; + + return 0; +} + +/** + * Get the OSR rate governor. + * @param phy The AD9361 current state structure. + * @param rate_gov Option buffer. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov) +{ + *rate_gov = phy->rate_governor; + + return 0; +} + +/** + * Perform the selected calibration. + * @param phy The AD9361 state structure. + * @param cal The selected calibration (TX_QUAD_CAL, RFDC_CAL). + * Accepted values: + * TX_QUAD_CAL + * RFDC_CAL + * @param arg For TX_QUAD_CAL - the optional RX phase value overwrite (set to zero). + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg) +{ + return ad9361_do_calib_run(phy, cal, arg); +} + +/** + * Load and enable TRX FIR filters configurations. + * @param phy The AD9361 current state structure. + * @param rx_fir_cfg RX FIR filter configuration. + * @param tx_fir_cfg TX FIR filter configuration. + * @return 0 in case of success, negative error code otherwise. + * + * Note: This function will/may affect the data path. + */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg) +{ + int32_t rtx = -1, rrx = -1; + + phy->filt_rx_bw_Hz = 0; + phy->filt_tx_bw_Hz = 0; + phy->filt_valid = false; + + if (tx_fir_cfg.tx_path_clks[TX_SAMPL_FREQ]) { + memcpy(phy->filt_tx_path_clks, tx_fir_cfg.tx_path_clks, + sizeof(phy->filt_tx_path_clks)); + rtx = 0; + } + + if (rx_fir_cfg.rx_path_clks[RX_SAMPL_FREQ]) { + memcpy(phy->filt_rx_path_clks, rx_fir_cfg.rx_path_clks, + sizeof(phy->filt_rx_path_clks)); + rrx = 0; + } + + if (tx_fir_cfg.tx_bandwidth) { + phy->filt_tx_bw_Hz = tx_fir_cfg.tx_bandwidth; + } + + if (rx_fir_cfg.rx_bandwidth) { + phy->filt_rx_bw_Hz = rx_fir_cfg.rx_bandwidth; + } + + ad9361_set_tx_fir_config(phy, tx_fir_cfg); + ad9361_set_rx_fir_config(phy, rx_fir_cfg); + + if (!(rrx | rtx)) + phy->filt_valid = true; + + ad9361_set_trx_fir_en_dis(phy, 1); + + return 0; +} + +/** + * Do DCXO coarse tuning. + * @param phy The AD9361 current state structure. + * @param coarse The DCXO coarse tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse) +{ + phy->pdata->dcxo_coarse = coarse; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Do DCXO fine tuning. + * @param phy The AD9361 current state structure. + * @param fine The DCXO fine tuning value. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine) +{ + phy->pdata->dcxo_fine = fine; + + return ad9361_set_dcxo_tune(phy, phy->pdata->dcxo_coarse, + phy->pdata->dcxo_fine); +} + +/** + * Get the temperature. + * @param phy The AD9361 current state structure. + * @param temp The temperature (degrees C * 1000). + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp) +{ + *temp = ad9361_get_temp(phy); + return 0; +} diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.h b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.h new file mode 100644 index 0000000..4879c60 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_api.h @@ -0,0 +1,552 @@ +/***************************************************************************//** + * @file ad9361_api.h + * @brief Header file of AD9361 API Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef AD9361_API_H_ +#define AD9361_API_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_util.h" +#include "gpio.h" +#include "spi.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +typedef struct { + /* Device selection */ + enum dev_id dev_sel; + /* Reference Clock */ + uint32_t reference_clk_rate; + /* Base Configuration */ + uint8_t two_rx_two_tx_mode_enable; /* adi,2rx-2tx-mode-enable */ + uint8_t one_rx_one_tx_mode_use_rx_num; /* adi,1rx-1tx-mode-use-rx-num */ + uint8_t one_rx_one_tx_mode_use_tx_num; /* adi,1rx-1tx-mode-use-tx-num */ + uint8_t frequency_division_duplex_mode_enable; /* adi,frequency-division-duplex-mode-enable */ + uint8_t frequency_division_duplex_independent_mode_enable; /* adi,frequency-division-duplex-independent-mode-enable */ + uint8_t tdd_use_dual_synth_mode_enable; /* adi,tdd-use-dual-synth-mode-enable */ + uint8_t tdd_skip_vco_cal_enable; /* adi,tdd-skip-vco-cal-enable */ + uint32_t tx_fastlock_delay_ns; /* adi,tx-fastlock-delay-ns */ + uint32_t rx_fastlock_delay_ns; /* adi,rx-fastlock-delay-ns */ + uint8_t rx_fastlock_pincontrol_enable; /* adi,rx-fastlock-pincontrol-enable */ + uint8_t tx_fastlock_pincontrol_enable; /* adi,tx-fastlock-pincontrol-enable */ + uint8_t external_rx_lo_enable; /* adi,external-rx-lo-enable */ + uint8_t external_tx_lo_enable; /* adi,external-tx-lo-enable */ + uint8_t dc_offset_tracking_update_event_mask; /* adi,dc-offset-tracking-update-event-mask */ + uint8_t dc_offset_attenuation_high_range; /* adi,dc-offset-attenuation-high-range */ + uint8_t dc_offset_attenuation_low_range; /* adi,dc-offset-attenuation-low-range */ + uint8_t dc_offset_count_high_range; /* adi,dc-offset-count-high-range */ + uint8_t dc_offset_count_low_range; /* adi,dc-offset-count-low-range */ + uint8_t split_gain_table_mode_enable; /* adi,split-gain-table-mode-enable */ + uint32_t trx_synthesizer_target_fref_overwrite_hz; /* adi,trx-synthesizer-target-fref-overwrite-hz */ + uint8_t qec_tracking_slow_mode_enable; /* adi,qec-tracking-slow-mode-enable */ + /* ENSM Control */ + uint8_t ensm_enable_pin_pulse_mode_enable; /* adi,ensm-enable-pin-pulse-mode-enable */ + uint8_t ensm_enable_txnrx_control_enable; /* adi,ensm-enable-txnrx-control-enable */ + /* LO Control */ + uint64_t rx_synthesizer_frequency_hz; /* adi,rx-synthesizer-frequency-hz */ + uint64_t tx_synthesizer_frequency_hz; /* adi,tx-synthesizer-frequency-hz */ + uint8_t tx_lo_powerdown_managed_enable; /* adi,tx-lo-powerdown-managed-enable */ + /* Rate & BW Control */ + uint32_t rx_path_clock_frequencies[6]; /* adi,rx-path-clock-frequencies */ + uint32_t tx_path_clock_frequencies[6]; /* adi,tx-path-clock-frequencies */ + uint32_t rf_rx_bandwidth_hz; /* adi,rf-rx-bandwidth-hz */ + uint32_t rf_tx_bandwidth_hz; /* adi,rf-tx-bandwidth-hz */ + /* RF Port Control */ + uint32_t rx_rf_port_input_select; /* adi,rx-rf-port-input-select */ + uint32_t tx_rf_port_input_select; /* adi,tx-rf-port-input-select */ + /* TX Attenuation Control */ + int32_t tx_attenuation_mdB; /* adi,tx-attenuation-mdB */ + uint8_t update_tx_gain_in_alert_enable; /* adi,update-tx-gain-in-alert-enable */ + /* Reference Clock Control */ + uint8_t xo_disable_use_ext_refclk_enable; /* adi,xo-disable-use-ext-refclk-enable */ + uint32_t dcxo_coarse_and_fine_tune[2]; /* adi,dcxo-coarse-and-fine-tune */ + uint32_t clk_output_mode_select; /* adi,clk-output-mode-select */ + /* Gain Control */ + uint8_t gc_rx1_mode; /* adi,gc-rx1-mode */ + uint8_t gc_rx2_mode; /* adi,gc-rx2-mode */ + uint8_t gc_adc_large_overload_thresh; /* adi,gc-adc-large-overload-thresh */ + uint8_t gc_adc_ovr_sample_size; /* adi,gc-adc-ovr-sample-size */ + uint8_t gc_adc_small_overload_thresh; /* adi,gc-adc-small-overload-thresh */ + uint16_t gc_dec_pow_measurement_duration; /* adi,gc-dec-pow-measurement-duration */ + uint8_t gc_dig_gain_enable; /* adi,gc-dig-gain-enable */ + uint16_t gc_lmt_overload_high_thresh; /* adi,gc-lmt-overload-high-thresh */ + uint16_t gc_lmt_overload_low_thresh; /* adi,gc-lmt-overload-low-thresh */ + uint8_t gc_low_power_thresh; /* adi,gc-low-power-thresh */ + uint8_t gc_max_dig_gain; /* adi,gc-max-dig-gain */ + uint8_t gc_use_rx_fir_out_for_dec_pwr_meas_enable; /* adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable */ + /* Gain MGC Control */ + uint8_t mgc_dec_gain_step; /* adi,mgc-dec-gain-step */ + uint8_t mgc_inc_gain_step; /* adi,mgc-inc-gain-step */ + uint8_t mgc_rx1_ctrl_inp_enable; /* adi,mgc-rx1-ctrl-inp-enable */ + uint8_t mgc_rx2_ctrl_inp_enable; /* adi,mgc-rx2-ctrl-inp-enable */ + uint8_t mgc_split_table_ctrl_inp_gain_mode; /* adi,mgc-split-table-ctrl-inp-gain-mode */ + /* Gain AGC Control */ + uint8_t agc_adc_large_overload_exceed_counter; /* adi,agc-adc-large-overload-exceed-counter */ + uint8_t agc_adc_large_overload_inc_steps; /* adi,agc-adc-large-overload-inc-steps - Name is misleading should be dec-steps*/ + uint8_t agc_adc_lmt_small_overload_prevent_gain_inc_enable; /* adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable */ + uint8_t agc_adc_small_overload_exceed_counter; /* adi,agc-adc-small-overload-exceed-counter */ + uint8_t agc_dig_gain_step_size; /* adi,agc-dig-gain-step-size */ + uint8_t agc_dig_saturation_exceed_counter; /* adi,agc-dig-saturation-exceed-counter */ + uint32_t agc_gain_update_interval_us; /* adi,agc-gain-update-interval-us */ + uint8_t agc_immed_gain_change_if_large_adc_overload_enable; /* adi,agc-immed-gain-change-if-large-adc-overload-enable */ + uint8_t agc_immed_gain_change_if_large_lmt_overload_enable; /* adi,agc-immed-gain-change-if-large-lmt-overload-enable */ + uint8_t agc_inner_thresh_high; /* adi,agc-inner-thresh-high */ + uint8_t agc_inner_thresh_high_dec_steps; /* adi,agc-inner-thresh-high-dec-steps */ + uint8_t agc_inner_thresh_low; /* adi,agc-inner-thresh-low */ + uint8_t agc_inner_thresh_low_inc_steps; /* adi,agc-inner-thresh-low-inc-steps */ + uint8_t agc_lmt_overload_large_exceed_counter; /* adi,agc-lmt-overload-large-exceed-counter */ + uint8_t agc_lmt_overload_large_inc_steps; /* adi,agc-lmt-overload-large-inc-steps */ + uint8_t agc_lmt_overload_small_exceed_counter; /* adi,agc-lmt-overload-small-exceed-counter */ + uint8_t agc_outer_thresh_high; /* adi,agc-outer-thresh-high */ + uint8_t agc_outer_thresh_high_dec_steps; /* adi,agc-outer-thresh-high-dec-steps */ + uint8_t agc_outer_thresh_low; /* adi,agc-outer-thresh-low */ + uint8_t agc_outer_thresh_low_inc_steps; /* adi,agc-outer-thresh-low-inc-steps */ + uint32_t agc_attack_delay_extra_margin_us; /* adi,agc-attack-delay-extra-margin-us */ + uint8_t agc_sync_for_gain_counter_enable; /* adi,agc-sync-for-gain-counter-enable */ + /* Fast AGC */ + uint32_t fagc_dec_pow_measuremnt_duration; /* adi,fagc-dec-pow-measurement-duration */ + uint32_t fagc_state_wait_time_ns; /* adi,fagc-state-wait-time-ns */ + /* Fast AGC - Low Power */ + uint8_t fagc_allow_agc_gain_increase; /* adi,fagc-allow-agc-gain-increase-enable */ + uint32_t fagc_lp_thresh_increment_time; /* adi,fagc-lp-thresh-increment-time */ + uint32_t fagc_lp_thresh_increment_steps; /* adi,fagc-lp-thresh-increment-steps */ + /* Fast AGC - Lock Level (Lock Level is set via slow AGC inner high threshold) */ + uint8_t fagc_lock_level_lmt_gain_increase_en; /* adi,fagc-lock-level-lmt-gain-increase-enable */ + uint32_t fagc_lock_level_gain_increase_upper_limit; /* adi,fagc-lock-level-gain-increase-upper-limit */ + /* Fast AGC - Peak Detectors and Final Settling */ + uint32_t fagc_lpf_final_settling_steps; /* adi,fagc-lpf-final-settling-steps */ + uint32_t fagc_lmt_final_settling_steps; /* adi,fagc-lmt-final-settling-steps */ + uint32_t fagc_final_overrange_count; /* adi,fagc-final-overrange-count */ + /* Fast AGC - Final Power Test */ + uint8_t fagc_gain_increase_after_gain_lock_en; /* adi,fagc-gain-increase-after-gain-lock-enable */ + /* Fast AGC - Unlocking the Gain */ + uint32_t fagc_gain_index_type_after_exit_rx_mode; /* adi,fagc-gain-index-type-after-exit-rx-mode */ + uint8_t fagc_use_last_lock_level_for_set_gain_en; /* adi,fagc-use-last-lock-level-for-set-gain-enable */ + uint8_t fagc_rst_gla_stronger_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable */ + uint32_t fagc_optimized_gain_offset; /* adi,fagc-optimized-gain-offset */ + uint32_t fagc_rst_gla_stronger_sig_thresh_above_ll; /* adi,fagc-rst-gla-stronger-sig-thresh-above-ll */ + uint8_t fagc_rst_gla_engergy_lost_sig_thresh_exceeded_en; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable */ + uint8_t fagc_rst_gla_engergy_lost_goto_optim_gain_en; /* adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable */ + uint32_t fagc_rst_gla_engergy_lost_sig_thresh_below_ll; /* adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll */ + uint32_t fagc_energy_lost_stronger_sig_gain_lock_exit_cnt; /* adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt */ + uint8_t fagc_rst_gla_large_adc_overload_en; /* adi,fagc-rst-gla-large-adc-overload-enable */ + uint8_t fagc_rst_gla_large_lmt_overload_en; /* adi,fagc-rst-gla-large-lmt-overload-enable */ + uint8_t fagc_rst_gla_en_agc_pulled_high_en; /* adi,fagc-rst-gla-en-agc-pulled-high-enable */ + uint32_t fagc_rst_gla_if_en_agc_pulled_high_mode; /* adi,fagc-rst-gla-if-en-agc-pulled-high-mode */ + uint32_t fagc_power_measurement_duration_in_state5; /* adi,fagc-power-measurement-duration-in-state5 */ + uint32_t fagc_large_overload_inc_steps; /* adi,fagc-adc-large-overload-inc-steps - Name is misleading should be dec-steps */ + /* RSSI Control */ + uint32_t rssi_delay; /* adi,rssi-delay */ + uint32_t rssi_duration; /* adi,rssi-duration */ + uint8_t rssi_restart_mode; /* adi,rssi-restart-mode */ + uint8_t rssi_unit_is_rx_samples_enable; /* adi,rssi-unit-is-rx-samples-enable */ + uint32_t rssi_wait; /* adi,rssi-wait */ + /* Aux ADC Control */ + uint32_t aux_adc_decimation; /* adi,aux-adc-decimation */ + uint32_t aux_adc_rate; /* adi,aux-adc-rate */ + /* AuxDAC Control */ + uint8_t aux_dac_manual_mode_enable; /* adi,aux-dac-manual-mode-enable */ + uint32_t aux_dac1_default_value_mV; /* adi,aux-dac1-default-value-mV */ + uint8_t aux_dac1_active_in_rx_enable; /* adi,aux-dac1-active-in-rx-enable */ + uint8_t aux_dac1_active_in_tx_enable; /* adi,aux-dac1-active-in-tx-enable */ + uint8_t aux_dac1_active_in_alert_enable; /* adi,aux-dac1-active-in-alert-enable */ + uint32_t aux_dac1_rx_delay_us; /* adi,aux-dac1-rx-delay-us */ + uint32_t aux_dac1_tx_delay_us; /* adi,aux-dac1-tx-delay-us */ + uint32_t aux_dac2_default_value_mV; /* adi,aux-dac2-default-value-mV */ + uint8_t aux_dac2_active_in_rx_enable; /* adi,aux-dac2-active-in-rx-enable */ + uint8_t aux_dac2_active_in_tx_enable; /* adi,aux-dac2-active-in-tx-enable */ + uint8_t aux_dac2_active_in_alert_enable; /* adi,aux-dac2-active-in-alert-enable */ + uint32_t aux_dac2_rx_delay_us; /* adi,aux-dac2-rx-delay-us */ + uint32_t aux_dac2_tx_delay_us; /* adi,aux-dac2-tx-delay-us */ + /* Temperature Sensor Control */ + uint32_t temp_sense_decimation; /* adi,temp-sense-decimation */ + uint16_t temp_sense_measurement_interval_ms; /* adi,temp-sense-measurement-interval-ms */ + int8_t temp_sense_offset_signed; /* adi,temp-sense-offset-signed */ + uint8_t temp_sense_periodic_measurement_enable; /* adi,temp-sense-periodic-measurement-enable */ + /* Control Out Setup */ + uint8_t ctrl_outs_enable_mask; /* adi,ctrl-outs-enable-mask */ + uint8_t ctrl_outs_index; /* adi,ctrl-outs-index */ + /* External LNA Control */ + uint32_t elna_settling_delay_ns; /* adi,elna-settling-delay-ns */ + uint32_t elna_gain_mdB; /* adi,elna-gain-mdB */ + uint32_t elna_bypass_loss_mdB; /* adi,elna-bypass-loss-mdB */ + uint8_t elna_rx1_gpo0_control_enable; /* adi,elna-rx1-gpo0-control-enable */ + uint8_t elna_rx2_gpo1_control_enable; /* adi,elna-rx2-gpo1-control-enable */ + uint8_t elna_gaintable_all_index_enable; /* adi,elna-gaintable-all-index-enable */ + /* Digital Interface Control */ + uint8_t digital_interface_tune_skip_mode; /* adi,digital-interface-tune-skip-mode */ + uint8_t digital_interface_tune_fir_disable; /* adi,digital-interface-tune-fir-disable */ + uint8_t pp_tx_swap_enable; /* adi,pp-tx-swap-enable */ + uint8_t pp_rx_swap_enable; /* adi,pp-rx-swap-enable */ + uint8_t tx_channel_swap_enable; /* adi,tx-channel-swap-enable */ + uint8_t rx_channel_swap_enable; /* adi,rx-channel-swap-enable */ + uint8_t rx_frame_pulse_mode_enable; /* adi,rx-frame-pulse-mode-enable */ + uint8_t two_t_two_r_timing_enable; /* adi,2t2r-timing-enable */ + uint8_t invert_data_bus_enable; /* adi,invert-data-bus-enable */ + uint8_t invert_data_clk_enable; /* adi,invert-data-clk-enable */ + uint8_t fdd_alt_word_order_enable; /* adi,fdd-alt-word-order-enable */ + uint8_t invert_rx_frame_enable; /* adi,invert-rx-frame-enable */ + uint8_t fdd_rx_rate_2tx_enable; /* adi,fdd-rx-rate-2tx-enable */ + uint8_t swap_ports_enable; /* adi,swap-ports-enable */ + uint8_t single_data_rate_enable; /* adi,single-data-rate-enable */ + uint8_t lvds_mode_enable; /* adi,lvds-mode-enable */ + uint8_t half_duplex_mode_enable; /* adi,half-duplex-mode-enable */ + uint8_t single_port_mode_enable; /* adi,single-port-mode-enable */ + uint8_t full_port_enable; /* adi,full-port-enable */ + uint8_t full_duplex_swap_bits_enable; /* adi,full-duplex-swap-bits-enable */ + uint32_t delay_rx_data; /* adi,delay-rx-data */ + uint32_t rx_data_clock_delay; /* adi,rx-data-clock-delay */ + uint32_t rx_data_delay; /* adi,rx-data-delay */ + uint32_t tx_fb_clock_delay; /* adi,tx-fb-clock-delay */ + uint32_t tx_data_delay; /* adi,tx-data-delay */ + uint32_t lvds_bias_mV; /* adi,lvds-bias-mV */ + uint8_t lvds_rx_onchip_termination_enable; /* adi,lvds-rx-onchip-termination-enable */ + uint8_t rx1rx2_phase_inversion_en; /* adi,rx1-rx2-phase-inversion-enable */ + uint8_t lvds_invert1_control; /* adi,lvds-invert1-control */ + uint8_t lvds_invert2_control; /* adi,lvds-invert2-control */ + /* GPO Control */ + uint8_t gpo_manual_mode_enable; /* adi,gpo-manual-mode-enable */ + uint32_t gpo_manual_mode_enable_mask; /* adi,gpo-manual-mode-enable-mask */ + uint8_t gpo0_inactive_state_high_enable; /* adi,gpo0-inactive-state-high-enable */ + uint8_t gpo1_inactive_state_high_enable; /* adi,gpo1-inactive-state-high-enable */ + uint8_t gpo2_inactive_state_high_enable; /* adi,gpo2-inactive-state-high-enable */ + uint8_t gpo3_inactive_state_high_enable; /* adi,gpo3-inactive-state-high-enable */ + uint8_t gpo0_slave_rx_enable; /* adi,gpo0-slave-rx-enable */ + uint8_t gpo0_slave_tx_enable; /* adi,gpo0-slave-tx-enable */ + uint8_t gpo1_slave_rx_enable; /* adi,gpo1-slave-rx-enable */ + uint8_t gpo1_slave_tx_enable; /* adi,gpo1-slave-tx-enable */ + uint8_t gpo2_slave_rx_enable; /* adi,gpo2-slave-rx-enable */ + uint8_t gpo2_slave_tx_enable; /* adi,gpo2-slave-tx-enable */ + uint8_t gpo3_slave_rx_enable; /* adi,gpo3-slave-rx-enable */ + uint8_t gpo3_slave_tx_enable; /* adi,gpo3-slave-tx-enable */ + uint8_t gpo0_rx_delay_us; /* adi,gpo0-rx-delay-us */ + uint8_t gpo0_tx_delay_us; /* adi,gpo0-tx-delay-us */ + uint8_t gpo1_rx_delay_us; /* adi,gpo1-rx-delay-us */ + uint8_t gpo1_tx_delay_us; /* adi,gpo1-tx-delay-us */ + uint8_t gpo2_rx_delay_us; /* adi,gpo2-rx-delay-us */ + uint8_t gpo2_tx_delay_us; /* adi,gpo2-tx-delay-us */ + uint8_t gpo3_rx_delay_us; /* adi,gpo3-rx-delay-us */ + uint8_t gpo3_tx_delay_us; /* adi,gpo3-tx-delay-us */ + /* Tx Monitor Control */ + uint32_t low_high_gain_threshold_mdB; /* adi,txmon-low-high-thresh */ + uint32_t low_gain_dB; /* adi,txmon-low-gain */ + uint32_t high_gain_dB; /* adi,txmon-high-gain */ + uint8_t tx_mon_track_en; /* adi,txmon-dc-tracking-enable */ + uint8_t one_shot_mode_en; /* adi,txmon-one-shot-mode-enable */ + uint32_t tx_mon_delay; /* adi,txmon-delay */ + uint32_t tx_mon_duration; /* adi,txmon-duration */ + uint32_t tx1_mon_front_end_gain; /* adi,txmon-1-front-end-gain */ + uint32_t tx2_mon_front_end_gain; /* adi,txmon-2-front-end-gain */ + uint32_t tx1_mon_lo_cm; /* adi,txmon-1-lo-cm */ + uint32_t tx2_mon_lo_cm; /* adi,txmon-2-lo-cm */ + /* GPIO definitions */ + struct gpio_init_param gpio_resetb; /* reset-gpios */ + /* MCS Sync */ + struct gpio_init_param gpio_sync; /* sync-gpios */ + struct gpio_init_param gpio_cal_sw1; /* cal-sw1-gpios */ + struct gpio_init_param gpio_cal_sw2; /* cal-sw2-gpios */ + + struct spi_init_param spi_param; + + /* External LO clocks */ + uint32_t (*ad9361_rfpll_ext_recalc_rate)(struct refclk_scale *clk_priv); + int32_t (*ad9361_rfpll_ext_round_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + int32_t (*ad9361_rfpll_ext_set_rate)(struct refclk_scale *clk_priv, + uint32_t rate); + +} AD9361_InitParam; + +typedef struct { + uint32_t rx; /* 1, 2, 3(both) */ + int32_t rx_gain; /* -12, -6, 0, 6 */ + uint32_t rx_dec; /* 1, 2, 4 */ + int16_t rx_coef[128]; + uint8_t rx_coef_size; + uint32_t rx_path_clks[6]; + uint32_t rx_bandwidth; +} AD9361_RXFIRConfig; + +typedef struct { + uint32_t tx; /* 1, 2, 3(both) */ + int32_t tx_gain; /* -6, 0 */ + uint32_t tx_int; /* 1, 2, 4 */ + int16_t tx_coef[128]; + uint8_t tx_coef_size; + uint32_t tx_path_clks[6]; + uint32_t tx_bandwidth; +} AD9361_TXFIRConfig; + +enum ad9361_ensm_mode { + ENSM_MODE_TX, + ENSM_MODE_RX, + ENSM_MODE_ALERT, + ENSM_MODE_FDD, + ENSM_MODE_WAIT, + ENSM_MODE_SLEEP, + ENSM_MODE_PINCTRL, + ENSM_MODE_PINCTRL_FDD_INDEP, +}; + +#define ENABLE 1 +#define DISABLE 0 + +#define RX1 0 +#define RX2 1 + +#define TX1 0 +#define TX2 1 + +#define A_BALANCED 0 +#define B_BALANCED 1 +#define C_BALANCED 2 +#define A_N 3 +#define A_P 4 +#define B_N 5 +#define B_P 6 +#define C_N 7 +#define C_P 8 +#define TX_MON1 9 +#define TX_MON2 10 +#define TX_MON1_2 11 + +#define TXA 0 +#define TXB 1 + +#define MODE_1x1 1 +#define MODE_2x2 2 + +#define HIGHEST_OSR 0 +#define NOMINAL_OSR 1 + +#define INT_LO 0 +#define EXT_LO 1 + +#define ON 0 +#define OFF 1 + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +/* Initialize the AD9361 part. */ +int32_t ad9361_init (struct ad9361_rf_phy **ad9361_phy, + AD9361_InitParam *init_param); +/* Free the allocated resources. */ +int32_t ad9361_remove(struct ad9361_rf_phy *phy); +/* Set the Enable State Machine (ENSM) mode. */ +int32_t ad9361_set_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t mode); +/* Get the Enable State Machine (ENSM) mode. */ +int32_t ad9361_get_en_state_machine_mode (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Set the receive RF gain for the selected channel. */ +int32_t ad9361_set_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t gain_db); +/* Get current receive RF gain for the selected channel. */ +int32_t ad9361_get_rx_rf_gain (struct ad9361_rf_phy *phy, uint8_t ch, + int32_t *gain_db); +/* Set the RX RF bandwidth. */ +int32_t ad9361_set_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the RX RF bandwidth. */ +int32_t ad9361_get_rx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the RX sampling frequency. */ +int32_t ad9361_set_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current RX sampling frequency. */ +int32_t ad9361_get_rx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the RX LO frequency. */ +int32_t ad9361_set_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current RX LO frequency. */ +int32_t ad9361_get_rx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_rx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Get the RSSI for the selected channel. */ +int32_t ad9361_get_rx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + struct rf_rssi *rssi); +/* Set the gain control mode for the selected channel. */ +int32_t ad9361_set_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t gc_mode); +/* Get the gain control mode for the selected channel. */ +int32_t ad9361_get_rx_gain_control_mode (struct ad9361_rf_phy *phy, uint8_t ch, + uint8_t *gc_mode); +/* Set the RX FIR filter configuration. */ +int32_t ad9361_set_rx_fir_config (struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig fir_cfg); +/* Get the RX FIR filter configuration. */ +int32_t ad9361_get_rx_fir_config(struct ad9361_rf_phy *phy, uint8_t rx_ch, + AD9361_RXFIRConfig *fir_cfg); +/* Enable/disable the RX FIR filter. */ +int32_t ad9361_set_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the RX FIR filter. */ +int32_t ad9361_get_rx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Enable/disable the RX RFDC Tracking. */ +int32_t ad9361_set_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX RFDC Tracking. */ +int32_t ad9361_get_rx_rfdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX BasebandDC Tracking. */ +int32_t ad9361_set_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX BasebandDC Tracking. */ +int32_t ad9361_get_rx_bbdc_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Enable/disable the RX Quadrature Tracking. */ +int32_t ad9361_set_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the RX Quadrature Tracking. */ +int32_t ad9361_get_rx_quad_track_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Set the RX RF input port. */ +int32_t ad9361_set_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected RX RF input port. */ +int32_t ad9361_get_rx_rf_port_input (struct ad9361_rf_phy *phy, uint32_t *mode); +/* Store RX fastlock profile. */ +int32_t ad9361_rx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall RX fastlock profile. */ +int32_t ad9361_rx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load RX fastlock profile. */ +int32_t ad9361_rx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save RX fastlock profile. */ +int32_t ad9361_rx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the RX Local Oscillator. */ +int32_t ad9361_rx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the RX Local Oscillator power status. */ +int32_t ad9361_get_rx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the transmit attenuation for the selected channel. */ +int32_t ad9361_set_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t attenuation_mdb); +/* Get current transmit attenuation for the selected channel. */ +int32_t ad9361_get_tx_attenuation (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *attenuation_mdb); +/* Set the TX RF bandwidth. */ +int32_t ad9361_set_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t bandwidth_hz); +/* Get the TX RF bandwidth. */ +int32_t ad9361_get_tx_rf_bandwidth (struct ad9361_rf_phy *phy, + uint32_t *bandwidth_hz); +/* Set the TX sampling frequency. */ +int32_t ad9361_set_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t sampling_freq_hz); +/* Get current TX sampling frequency. */ +int32_t ad9361_get_tx_sampling_freq (struct ad9361_rf_phy *phy, + uint32_t *sampling_freq_hz); +/* Set the TX LO frequency. */ +int32_t ad9361_set_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t lo_freq_hz); +/* Get current TX LO frequency. */ +int32_t ad9361_get_tx_lo_freq (struct ad9361_rf_phy *phy, uint64_t *lo_freq_hz); +/* Switch between internal and external LO. */ +int32_t ad9361_set_tx_lo_int_ext(struct ad9361_rf_phy *phy, uint8_t int_ext); +/* Set the TX FIR filter configuration. */ +int32_t ad9361_set_tx_fir_config (struct ad9361_rf_phy *phy, + AD9361_TXFIRConfig fir_cfg); +/* Get the TX FIR filter configuration. */ +int32_t ad9361_get_tx_fir_config(struct ad9361_rf_phy *phy, uint8_t tx_ch, + AD9361_TXFIRConfig *fir_cfg); +/* Enable/disable the TX FIR filter. */ +int32_t ad9361_set_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Get the status of the TX FIR filter. */ +int32_t ad9361_get_tx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t *en_dis); +/* Get the TX RSSI for the selected channel. */ +int32_t ad9361_get_tx_rssi (struct ad9361_rf_phy *phy, uint8_t ch, + uint32_t *rssi_db_x_1000); +/* Set the TX RF output port. */ +int32_t ad9361_set_tx_rf_port_output (struct ad9361_rf_phy *phy, uint32_t mode); +/* Get the selected TX RF output port. */ +int32_t ad9361_get_tx_rf_port_output (struct ad9361_rf_phy *phy, + uint32_t *mode); +/* Enable/disable the auto calibration. */ +int32_t ad9361_set_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t en_dis); +/* Get the status of the auto calibration flag. */ +int32_t ad9361_get_tx_auto_cal_en_dis (struct ad9361_rf_phy *phy, + uint8_t *en_dis); +/* Store TX fastlock profile. */ +int32_t ad9361_tx_fastlock_store(struct ad9361_rf_phy *phy, uint32_t profile); +/* Recall TX fastlock profile. */ +int32_t ad9361_tx_fastlock_recall(struct ad9361_rf_phy *phy, uint32_t profile); +/* Load TX fastlock profile. */ +int32_t ad9361_tx_fastlock_load(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Save TX fastlock profile. */ +int32_t ad9361_tx_fastlock_save(struct ad9361_rf_phy *phy, uint32_t profile, + uint8_t *values); +/* Power down the TX Local Oscillator. */ +int32_t ad9361_tx_lo_powerdown(struct ad9361_rf_phy *phy, uint8_t option); +/* Get the TX Local Oscillator power status. */ +int32_t ad9361_get_tx_lo_power(struct ad9361_rf_phy *phy, uint8_t *option); +/* Set the RX and TX path rates. */ +int32_t ad9361_set_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Get the RX and TX path rates. */ +int32_t ad9361_get_trx_path_clks(struct ad9361_rf_phy *phy, + uint32_t *rx_path_clks, uint32_t *tx_path_clks); +/* Set the number of channels mode. */ +int32_t ad9361_set_no_ch_mode(struct ad9361_rf_phy *phy, uint8_t no_ch_mode); +/* Do multi chip synchronization. */ +int32_t ad9361_do_mcs(struct ad9361_rf_phy *phy_master, + struct ad9361_rf_phy *phy_slave); +/* Enable/disable the TRX FIR filters. */ +int32_t ad9361_set_trx_fir_en_dis (struct ad9361_rf_phy *phy, uint8_t en_dis); +/* Set the OSR rate governor. */ +int32_t ad9361_set_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t rate_gov); +/* Get the OSR rate governor. */ +int32_t ad9361_get_trx_rate_gov (struct ad9361_rf_phy *phy, uint32_t *rate_gov); +/* Perform the selected calibration. */ +int32_t ad9361_do_calib(struct ad9361_rf_phy *phy, uint32_t cal, int32_t arg); +/* Load and enable TRX FIR filters configurations. */ +int32_t ad9361_trx_load_enable_fir(struct ad9361_rf_phy *phy, + AD9361_RXFIRConfig rx_fir_cfg, + AD9361_TXFIRConfig tx_fir_cfg); +/* Do DCXO coarse tuning. */ +int32_t ad9361_do_dcxo_tune_coarse(struct ad9361_rf_phy *phy, + uint32_t coarse); +/* Do DCXO fine tuning. */ +int32_t ad9361_do_dcxo_tune_fine(struct ad9361_rf_phy *phy, + uint32_t fine); +/* Get the temperature. */ +int32_t ad9361_get_temperature(struct ad9361_rf_phy *phy, + int32_t *temp); +#endif diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_conv.c b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_conv.c new file mode 100644 index 0000000..bbcfee5 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_conv.c @@ -0,0 +1,86 @@ + +/***************************************************************************//** + * @file ad9361_conv.c + * @brief Implementation of AD9361 Conv Driver. +******************************************************************************** + * Copyright 2014-2015(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include "ad9361.h" +#include "ad9361_util.h" +#include "delay.h" +#include "../../../config/app_config.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + +/** + * HDL loopback enable/disable. + * @param phy The AD9361 state structure. + * @param enable Enable/disable option. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_hdl_loopback(struct ad9361_rf_phy *phy, bool enable) +{ + return -ENODEV; +} + +/** + * Digital tune. + * @param phy The AD9361 state structure. + * @param max_freq Maximum frequency. + * @param flags Flags: BE_VERBOSE, BE_MOREVERBOSE, DO_IDELAY, DO_ODELAY. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_dig_tune(struct ad9361_rf_phy *phy, uint32_t max_freq, + enum dig_tune_flags flags) +{ + return 0; +} + +/** +* Setup the AD9361 device. +* @param phy The AD9361 state structure. +* @return 0 in case of success, negative error code otherwise. +*/ +int32_t ad9361_post_setup(struct ad9361_rf_phy *phy) +{ + return 0; +} diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.c b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.c new file mode 100644 index 0000000..a49e146 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.c @@ -0,0 +1,335 @@ +/***************************************************************************//** + * @file ad9361_util.c + * @brief AD9361 Implementation of Util Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "ad9361_util.h" +#include "../../../include/delay.h" + +/******************************************************************************/ +/*************************** Macros Definitions *******************************/ +/******************************************************************************/ +#define BITS_PER_LONG 32 + +/***************************************************************************//** + * @brief clk_prepare_enable +*******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk) +{ + if (clk) { + // Unused variable - fix compiler warning + } + + return 0; +} + +/***************************************************************************//** + * @brief clk_get_rate +*******************************************************************************/ +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv) +{ + uint32_t rate = 0; + uint32_t source; + + source = clk_priv->source; + + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + rate = ad9361_rfpll_dummy_recalc_rate(clk_priv); + break; + case TX_RFPLL: + case RX_RFPLL: + rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + + return rate; +} + +/***************************************************************************//** + * @brief clk_set_rate +*******************************************************************************/ +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate) +{ + uint32_t source; + int32_t i; + uint32_t round_rate; + + source = clk_priv->source; + if(phy->clks[source]->rate != rate) + { + switch (source) { + case TX_REFCLK: + case RX_REFCLK: + case BB_REFCLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clk_refin->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clk_refin->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clk_refin->rate); + break; + case TX_RFPLL_INT: + case RX_RFPLL_INT: + round_rate = ad9361_rfpll_int_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_rfpll_int_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_rfpll_int_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + case RX_RFPLL_DUMMY: + case TX_RFPLL_DUMMY: + ad9361_rfpll_dummy_set_rate(clk_priv, rate); + break; + case TX_RFPLL: + case RX_RFPLL: + round_rate = ad9361_rfpll_round_rate(clk_priv, rate); + ad9361_rfpll_set_rate(clk_priv, round_rate); + phy->clks[source]->rate = ad9361_rfpll_recalc_rate(clk_priv); + break; + case BBPLL_CLK: + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + break; + case ADC_CLK: + case R2_CLK: + case R1_CLK: + case CLKRF_CLK: + case RX_SAMPL_CLK: + case DAC_CLK: + case T2_CLK: + case T1_CLK: + case CLKTF_CLK: + case TX_SAMPL_CLK: + round_rate = ad9361_clk_factor_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_clk_factor_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_clk_factor_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + break; + default: + break; + } + for(i = BB_REFCLK; i < BBPLL_CLK; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clk_refin->rate); + } + phy->clks[BBPLL_CLK]->rate = ad9361_bbpll_recalc_rate(phy->ref_clk_scale[BBPLL_CLK], + phy->clks[phy->ref_clk_scale[BBPLL_CLK]->parent_source]->rate); + for(i = ADC_CLK; i < RX_RFPLL_INT; i++) + { + phy->clks[i]->rate = ad9361_clk_factor_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_INT; i < RX_RFPLL_DUMMY; i++) + { + phy->clks[i]->rate = ad9361_rfpll_int_recalc_rate(phy->ref_clk_scale[i], + phy->clks[phy->ref_clk_scale[i]->parent_source]->rate); + } + for(i = RX_RFPLL_DUMMY; i < RX_RFPLL; i++) + { + phy->clks[i]->rate = ad9361_rfpll_dummy_recalc_rate(phy->ref_clk_scale[i]); + } + for(i = RX_RFPLL; i < NUM_AD9361_CLKS; i++) + { + phy->clks[i]->rate = ad9361_rfpll_recalc_rate(phy->ref_clk_scale[i]); + } + } else { + if ((source == BBPLL_CLK) && !phy->bbpll_initialized) { + round_rate = ad9361_bbpll_round_rate(clk_priv, rate, + &phy->clks[clk_priv->parent_source]->rate); + ad9361_bbpll_set_rate(clk_priv, round_rate, + phy->clks[clk_priv->parent_source]->rate); + phy->clks[source]->rate = ad9361_bbpll_recalc_rate(clk_priv, + phy->clks[clk_priv->parent_source]->rate); + phy->bbpll_initialized = true; + } + } + + return 0; +} + +/***************************************************************************//** + * @brief int_sqrt +*******************************************************************************/ +uint32_t int_sqrt(uint32_t x) +{ + uint32_t b, m, y = 0; + + if (x <= 1) + return x; + + m = 1UL << (BITS_PER_LONG - 2); + while (m != 0) { + b = y + m; + y >>= 1; + + if (x >= b) { + x -= b; + y += m; + } + m >>= 2; + } + + return y; +} + +/***************************************************************************//** + * @brief ilog2 +*******************************************************************************/ +int32_t ilog2(int32_t x) +{ + int32_t A = !(!(x >> 16)); + int32_t count = 0; + int32_t x_copy = x; + + count = count + (A << 4); + + x_copy = (((~A + 1) & (x >> 16)) + (~(~A + 1) & x)); + + A = !(!(x_copy >> 8)); + count = count + (A << 3); + x_copy = (((~A + 1) & (x_copy >> 8)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 4)); + count = count + (A << 2); + x_copy = (((~A + 1) & (x_copy >> 4)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 2)); + count = count + (A << 1); + x_copy = (((~A + 1) & (x_copy >> 2)) + (~(~A + 1) & x_copy)); + + A = !(!(x_copy >> 1)); + count = count + A; + + return count; +} + +/***************************************************************************//** + * @brief find_first_bit +*******************************************************************************/ +uint32_t find_first_bit(uint32_t word) +{ + int32_t num = 0; + + if ((word & 0xffff) == 0) { + num += 16; + word >>= 16; + } + if ((word & 0xff) == 0) { + num += 8; + word >>= 8; + } + if ((word & 0xf) == 0) { + num += 4; + word >>= 4; + } + if ((word & 0x3) == 0) { + num += 2; + word >>= 2; + } + if ((word & 0x1) == 0) + num += 1; + return num; +} + +/***************************************************************************//** + * @brief ERR_PTR +*******************************************************************************/ +void * ERR_PTR(long error) +{ + return (void *) error; +} + +/***************************************************************************//** + * @brief zmalloc +*******************************************************************************/ +void *zmalloc(size_t size) +{ + void *ptr = malloc(size); + if (ptr) + memset(ptr, 0, size); + mdelay(1); + + return ptr; +} diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.h b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.h new file mode 100644 index 0000000..cabb6dc --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/ad9361_util.h @@ -0,0 +1,120 @@ +/***************************************************************************//** + * @file ad9361_util.h + * @brief AD9361 Header file of Util driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_UTIL_H__ +#define __AD9361_UTIL_H__ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include +#include +#include +#include "ad9361.h" +#include "common.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ +#define CLK_IGNORE_UNUSED BIT(3) +#define CLK_GET_RATE_NOCACHE BIT(6) + +#if defined(HAVE_VERBOSE_MESSAGES) +#define dev_err(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#define dev_warn(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#if defined(HAVE_DEBUG_MESSAGES) +#define dev_dbg(dev, format, ...) ({printf(format, ## __VA_ARGS__);printf("\n"); }) +#else +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif +#define printk(format, ...) printf(format, ## __VA_ARGS__) +#else +#define dev_err(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_warn(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define dev_dbg(dev, format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#define printk(format, ...) ({ if (0) printf(format, ## __VA_ARGS__); }) +#endif + +struct device { +}; + +struct spi_device { + struct device dev; + uint8_t id_no; +}; + +struct axiadc_state { + struct ad9361_rf_phy *phy; + uint32_t pcore_version; +}; + +struct axiadc_chip_info { + char *name; + int32_t num_channels; +}; + +struct axiadc_converter { + struct axiadc_chip_info *chip_info; + uint32_t scratch_reg[16]; +}; + +#ifdef WIN32 +#include "basetsd.h" +typedef SSIZE_T ssize_t; +#define strsep(s, ct) 0 +#define snprintf(s, n, format, ...) 0 +#define __func__ __FUNCTION__ +#endif + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ +int32_t clk_prepare_enable(struct clk *clk); +uint32_t clk_get_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv); +int32_t clk_set_rate(struct ad9361_rf_phy *phy, + struct refclk_scale *clk_priv, + uint32_t rate); +uint32_t int_sqrt(uint32_t x); +int32_t ilog2(int32_t x); +uint32_t find_first_bit(uint32_t word); +void * ERR_PTR(long error); +void *zmalloc(size_t size); + +#endif diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361/common.h b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/common.h new file mode 100644 index 0000000..6093230 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361/common.h @@ -0,0 +1,66 @@ +/***************************************************************************//** + * @file common.h + * @brief Header file of Common Driver. + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2013(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ +#ifndef __AD9361_COMMON_H_ +#define __AD9361_COMMON_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "../../../include/error.h" + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +#if defined (__STDC__) && (__STDC_VERSION__ >= 199901L) +#include +#else +typedef enum { false, true } bool; +#endif + +struct clk { + const char *name; + uint32_t rate; +}; + +struct clk_hw { + struct clk *clk; +}; + +#endif // __AD9361_COMMON_H_ diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c b/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c new file mode 100644 index 0000000..7498038 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.c @@ -0,0 +1,151 @@ +/***************************************************************************//** + * @file ad9361_reg.c + * @brief Implementation of AD9680 Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include "ad9361_reg.h" + +#include +#include +#include "../../../include/error.h" + +/***************************************************************************//** + * @brief ad9361_reg_read + *******************************************************************************/ +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data) +{ + uint8_t tx_buf[2]; + uint8_t rx_buf[1]; + int32_t ret; + + tx_buf[0] = reg_addr >> 8; + tx_buf[1] = reg_addr & 0xFF; + + + ret = spi_write_and_read_3wire(dev->spi_desc, + tx_buf, rx_buf, 2, 1); + + *reg_data = rx_buf[0]; + + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_write + *******************************************************************************/ +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data) +{ + uint8_t buf[3]; + + int32_t ret; + + buf[0] = 0x80 | reg_addr >> 8; + buf[1] = reg_addr & 0xFF; + buf[2] = reg_data; + + ret = spi_write_and_read_3wire(dev->spi_desc, + buf, NULL, 3, 0); + return ret; +} + +/***************************************************************************//** + * @brief ad9361_reg_init + *******************************************************************************/ +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param) +{ + int ret = SUCCESS; + struct ad9361_reg_dev *dev; + + dev = (struct ad9361_reg_dev *)malloc(sizeof(*dev)); + if (!dev) + return FAILURE; + + /* SPI */ + ret = spi_init(&dev->spi_desc, init_param->spi_init); + ret |= gpio_get(&dev->gpio_desc_resetb, init_param->gpio_resetb); + + gpio_direction_output(dev->gpio_desc_resetb, 0); + + ad9361_reg_reset(dev); + + *device = dev; + + return ret; +} + +/** + * AD9361 Device Reset + * @param phy The AD9361 state structure. + * @return 0 in case of success, negative error code otherwise. + */ +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev) +{ + if (dev->gpio_desc_resetb) { + gpio_set_value(dev->gpio_desc_resetb, 0); + mdelay(10); + gpio_set_value(dev->gpio_desc_resetb, 1); + mdelay(10); + return 0; + } + return 0; +} + +/***************************************************************************//** + * @brief Free the resources allocated by ad9361_reg_setup(). + * + * @param dev - The device structure. + * + * @return SUCCESS in case of success, negative error code otherwise. +*******************************************************************************/ +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev) +{ + int32_t ret; + + ret = spi_remove(dev->spi_desc); + + free(dev); + + return ret; +} diff --git a/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h b/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h new file mode 100644 index 0000000..c3039c5 --- /dev/null +++ b/df_datalink_ge/src/drivers/rf-transceiver/ad9361_reg/ad9361_reg.h @@ -0,0 +1,104 @@ +/***************************************************************************//** + * @file ad9361_reg.h + * @brief Header file of ad9361_reg Driver. + * @author DBogdan (dragos.bogdan@analog.com) + ******************************************************************************** + * Copyright 2014-2016(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + *******************************************************************************/ +#ifndef ad9361_reg_H_ +#define ad9361_reg_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ +#include +#include "delay.h" +#include "spi.h" +#include "gpio.h" + +/******************************************************************************/ +/********************** Macros and Constants Definitions **********************/ +/******************************************************************************/ + + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ +struct ad9361_reg_dev { + /* SPI */ + struct spi_desc *spi_desc; + struct gpio_desc *gpio_desc_resetb; +}; + +struct ad9361_reg_init_param { + /* SPI */ + struct spi_init_param *spi_init; + struct gpio_init_param *gpio_resetb; +}; + +enum Operation_Type{ + AD9361_WRITE, + AD9361_READ, + AD9361_WAIT, + AD9361_WHEN +}; + +struct ad9361_reg_config { + int operation; + uint16_t val1; + uint16_t val2; +}; + + + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +int32_t ad9361_reg_read(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t *reg_data); + +int32_t ad9361_reg_write(struct ad9361_reg_dev *dev, + uint16_t reg_addr, + uint8_t reg_data); + +int32_t ad9361_reg_init(struct ad9361_reg_dev **device, + const struct ad9361_reg_init_param *init_param); + +int32_t ad9361_reg_reset(struct ad9361_reg_dev *dev); + +int32_t ad9361_reg_remove(struct ad9361_reg_dev *dev); + +#endif diff --git a/df_datalink_ge/src/hardware/common.c b/df_datalink_ge/src/hardware/common.c deleted file mode 100644 index c4323b2..0000000 --- a/df_datalink_ge/src/hardware/common.c +++ /dev/null @@ -1,275 +0,0 @@ -/** - * \file common.c - * \brief Contains Mykonos API common wrapper functions for user hardware platform drivers - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -#include -#include -#include -#include -#include "common.h" -#include "platform_drivers.h" -#include "parameters.h" - -ADI_LOGLEVEL CMB_LOGLEVEL = ADIHAL_LOG_NONE; - -static uint32_t _desired_time_to_elapse_us = 0; -struct spi_desc *spi_ad_desc; -struct gpio_desc *gpio_ad9371_resetb; -struct gpio_desc *gpio_ad9528_resetb; -struct gpio_desc *gpio_ad9528_sysref_req; - -commonErr_t CMB_initPlatform(void) -{ - struct spi_init_param spi_param; - int32_t status = COMMONERR_OK; - - status |= gpio_get(&gpio_ad9371_resetb, AD9371_RESET_B); - status |= gpio_get(&gpio_ad9528_resetb, AD9528_RESET_B); - status |= gpio_get(&gpio_ad9528_sysref_req, AD9528_SYSREF_REQ); - - spi_param.id = 0; - spi_param.mode = SPI_MODE_0; - spi_param.chip_select = AD9371_CS; - spi_param.max_speed_hz = 25000000u; - - status |= spi_init(&spi_ad_desc, &spi_param); - - if (status != SUCCESS) { - return COMMONERR_FAILED; - } - - return COMMONERR_OK; -} - -commonErr_t CMB_closeHardware(void) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_setGPIO(uint32_t GPIO) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_hardReset(uint8_t spiChipSelectIndex) -{ - struct gpio_desc *reset_gpio; - - switch (spiChipSelectIndex) { - case AD9371_CS: - reset_gpio = gpio_ad9371_resetb; - break; - case AD9528_CS: - reset_gpio = gpio_ad9528_resetb; - break; - default: - return(COMMONERR_FAILED); - } - - gpio_direction_output(reset_gpio, 1); - CMB_wait_ms(1); - gpio_direction_output(reset_gpio, 0); - CMB_wait_ms(1); - gpio_direction_output(reset_gpio, 1); - CMB_wait_ms(1); - - return(COMMONERR_OK); -} - -commonErr_t CMB_setSPIOptions(spiSettings_t *spiSettings) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_setSPIChannel(uint16_t chipSelectIndex ) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_SPIWriteByte(spiSettings_t *spiSettings, uint16_t addr, - uint8_t data) -{ - uint8_t buf[3]; - - spi_ad_desc->chip_select = spiSettings->chipSelectIndex - 1; - - buf[0] = (uint8_t) ((addr >> 8) & 0x7f); - buf[1] = (uint8_t) (addr & 0xff); - buf[2] = (uint8_t) data; - - spi_write_and_read(spi_ad_desc, buf, 3); - - return(COMMONERR_OK); -} - -commonErr_t CMB_SPIWriteBytes(spiSettings_t *spiSettings, uint16_t *addr, - uint8_t *data, uint32_t count) -{ - uint32_t index; - - for (index = 0; index < count; index++) - if (CMB_SPIWriteByte(spiSettings, *(addr + index), - *(data + index)) != COMMONERR_OK) - return(COMMONERR_FAILED); - - return(COMMONERR_OK); -} - -commonErr_t CMB_SPIReadByte(spiSettings_t *spiSettings, uint16_t addr, - uint8_t *readdata) -{ - uint8_t buf[3]; - - spi_ad_desc->chip_select = spiSettings->chipSelectIndex - 1; - - buf[0] = (uint8_t) ((addr >> 8) | 0x80); - buf[1] = (uint8_t) (addr & 0xff); - buf[2] = (uint8_t) 0x00; - - spi_write_and_read(spi_ad_desc, buf, 3); - *readdata = buf[2]; - - return(COMMONERR_OK); -} - -commonErr_t CMB_SPIWriteField(spiSettings_t *spiSettings, uint16_t addr, - uint8_t field_val, uint8_t mask, uint8_t start_bit) -{ - uint8_t data; - - if (CMB_SPIReadByte(spiSettings, addr, &data) != COMMONERR_OK) - return(COMMONERR_FAILED); - - data = (data & ~mask) | ((field_val << start_bit) & mask); - - if (CMB_SPIWriteByte(spiSettings, addr, data) != COMMONERR_OK) - return(COMMONERR_FAILED); - - return(COMMONERR_OK); -} - -/* read a field in a single register space (not multibyte fields) */ -commonErr_t CMB_SPIReadField(spiSettings_t *spiSettings, uint16_t addr, - uint8_t *field_val, uint8_t mask, uint8_t start_bit) -{ - uint8_t data; - - if (CMB_SPIReadByte(spiSettings, addr, &data) != COMMONERR_OK) - return(COMMONERR_FAILED); - - data = (data & mask) >> start_bit; - *field_val = data; - - return(COMMONERR_OK); -} - - -commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, - uint32_t errorCode, const char *comment) -{ - - if((CMB_LOGLEVEL & ADIHAL_LOG_ERROR) && (level == ADIHAL_LOG_ERROR)) { - printf("ERROR: %d: %s", (int)errorCode, comment); - } else if((CMB_LOGLEVEL & ADIHAL_LOG_WARNING) - && (level == ADIHAL_LOG_WARNING)) { - printf("WARNING: %d: %s",(int)errorCode, comment); - } else if((CMB_LOGLEVEL & ADIHAL_LOG_MESSAGE) - && (level == ADIHAL_LOG_MESSAGE)) { - printf("MESSAGE: %d: %s",(int)errorCode, comment); - } else if(CMB_LOGLEVEL == ADIHAL_LOG_NONE ) { - //printf("MESSAGE: %d: %s",(int)errorCode, comment); - } else { - printf("Undefined Log Level: 0x%X", level); - } - - return(COMMONERR_OK); -} - -/* if filename null, a default path will be used in logging.c */ -commonErr_t CMB_openLog(const char *filename) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_closeLog(void) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_flushLog(void) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_wait_ms(uint32_t time_ms) -{ - mdelay(time_ms); - - return(COMMONERR_OK); -} - -commonErr_t CMB_wait_us(uint32_t time_us) -{ - udelay(time_us); - - return(COMMONERR_OK); -} - -commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms) -{ -#ifdef _XPARAMETERS_PS_H_ - _desired_time_to_elapse_us = timeOut_ms * 1000; -#else - _desired_time_to_elapse_us = timeOut_ms * 50; // FIXME -#endif - - return(COMMONERR_OK); -} - -commonErr_t CMB_setTimeout_us(uint32_t timeOut_us) -{ - _desired_time_to_elapse_us = timeOut_us; - - return(COMMONERR_OK); -} - - -commonErr_t CMB_hasTimeoutExpired() -{ - udelay(1); - - _desired_time_to_elapse_us--; - if (_desired_time_to_elapse_us > 0) - return(COMMONERR_OK); - - return(COMMONERR_FAILED); -} - -commonErr_t CMB_regRead(uint32_t offset, uint32_t *data) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_regWrite(uint32_t offset, uint32_t data) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_memRead(uint32_t offset, uint32_t *data, uint32_t len) -{ - return(COMMONERR_OK); -} - -commonErr_t CMB_memWrite(uint32_t offset, uint32_t *data, uint32_t len) -{ - return(COMMONERR_OK); -} diff --git a/df_datalink_ge/src/hardware/common.h b/df_datalink_ge/src/hardware/common.h deleted file mode 100644 index 785217d..0000000 --- a/df_datalink_ge/src/hardware/common.h +++ /dev/null @@ -1,131 +0,0 @@ -/** - * \file common.h - * \brief Contains type definitions and prototype declarations for common.c - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _COMMON_H_ -#define _COMMON_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* build project settings include the path to the desired platform folder for correct includes */ -#include "stdint.h" - -#define THROW_ERROR() - -#define SPIARRAYSIZE 1024 - -/* assuming 3 byte SPI message - integer math enforces floor() */ -#define SPIARRAYTRIPSIZE ((SPIARRAYSIZE / 3) * 3) - -/*======================================== - * Enums and structures - *=======================================*/ -/* proposed to increase number of error return values to make unique for each return */ -typedef enum -{ - ADIERR_OK=0, - ADIERR_INV_PARM, - ADIERR_FAILED -} ADI_ERR; - -/*!< \brief COMMON layer error reporting enumerated types */ -typedef enum -{ - COMMONERR_OK=0, - COMMONERR_FAILED -} commonErr_t; - -/* bit 0 is MESSAGE, bit 1 is WARNING, bit 2 is ERROR */ -typedef enum -{ - ADIHAL_LOG_NONE = 0x0, - ADIHAL_LOG_MESSAGE = 0x1, - ADIHAL_LOG_WARNING = 0x2, - ADIHAL_LOG_ERROR = 0x4, - ADIHAL_LOG_SPI = 0x8, - ADIHAL_LOG_AXI_REG = 0x10, - ADIHAL_LOG_AXI_MEM = 0x20, - ADIHAL_LOG_ALL = 0x3F -} ADI_LOGLEVEL; - -/** - * \brief Data structure to hold SPI settings for all system device types - */ -typedef struct -{ - uint8_t chipSelectIndex; ///< valid 1~8 - uint8_t writeBitPolarity; ///< the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation - uint8_t longInstructionWord; ///< 1 = 16bit instruction word, 0 = 8bit instruction word - uint8_t MSBFirst; ///< 1 = MSBFirst, 0 = LSBFirst - uint8_t CPHA; ///< clock phase, sets which clock edge the data updates (valid 0 or 1) - uint8_t CPOL; ///< clock polarity 0 = clock starts low, 1 = clock starts high - uint8_t enSpiStreaming; ///< Not implemented. SW feature to improve SPI throughput. - uint8_t autoIncAddrUp; ///< Not implemented. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr = addr-1 - uint8_t fourWireMode; ///< 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode. - uint32_t spiClkFreq_Hz; ///< SPI Clk frequency in Hz (default 25000000), platform will use next lowest frequency that it's baud rate generator can create */ - -} spiSettings_t; - -/* global variable so application layer can set the log level */ -extern ADI_LOGLEVEL CMB_LOGLEVEL; -extern struct spi_desc *spi_ad_desc; -extern struct gpio_desc *gpio_ad9371_resetb; -extern struct gpio_desc *gpio_ad9528_resetb; -extern struct gpio_desc *gpio_ad9528_sysref_req; - -/* initialize hardware platform */ -commonErr_t CMB_initPlatform(void); - -/* close hardware pointers */ -commonErr_t CMB_closeHardware(void); - -/* GPIO function */ -commonErr_t CMB_setGPIO(uint32_t GPIO); - -/* hardware reset function */ -commonErr_t CMB_hardReset(uint8_t spiChipSelectIndex); - -/* SPI read/write functions */ -commonErr_t CMB_setSPIOptions(spiSettings_t *spiSettings); /* allows the platform HAL to work with devices with various SPI settings */ -commonErr_t CMB_setSPIChannel(uint16_t chipSelectIndex ); /* value of 0 deasserts all chip selects */ -commonErr_t CMB_SPIWriteByte(spiSettings_t *spiSettings, uint16_t addr, uint8_t data); /* single SPI byte write function */ -commonErr_t CMB_SPIWriteBytes(spiSettings_t *spiSettings, uint16_t *addr, uint8_t *data, uint32_t count); -commonErr_t CMB_SPIReadByte (spiSettings_t *spiSettings, uint16_t addr, uint8_t *readdata); /* single SPI byte read function */ -commonErr_t CMB_SPIWriteField(spiSettings_t *spiSettings, uint16_t addr, uint8_t field_val, uint8_t mask, uint8_t start_bit); /* write a field in a single register */ -commonErr_t CMB_SPIReadField (spiSettings_t *spiSettings, uint16_t addr, uint8_t *field_val, uint8_t mask, uint8_t start_bit); /* read a field in a single register */ - -/* platform timer functions */ -commonErr_t CMB_wait_ms(uint32_t time_ms); -commonErr_t CMB_wait_us(uint32_t time_us); -commonErr_t CMB_setTimeout_ms(uint32_t timeOut_ms); -commonErr_t CMB_setTimeout_us(uint32_t timeOut_us); -commonErr_t CMB_hasTimeoutExpired(); - -/* platform logging functions */ -commonErr_t CMB_openLog(const char *filename); -commonErr_t CMB_closeLog(void); -commonErr_t CMB_writeToLog(ADI_LOGLEVEL level, uint8_t deviceIndex, uint32_t errorCode, const char *comment); -commonErr_t CMB_flushLog(void); - -/* platform FPGA AXI register read/write functions */ -commonErr_t CMB_regRead(uint32_t offset, uint32_t *data); -commonErr_t CMB_regWrite(uint32_t offset, uint32_t data); - -/* platform DDR3 memory read/write functions */ -commonErr_t CMB_memRead(uint32_t offset, uint32_t *data, uint32_t len); -commonErr_t CMB_memWrite(uint32_t offset, uint32_t *data, uint32_t len); - -#ifdef __cplusplus -} -#endif -#endif diff --git a/df_datalink_ge/src/hardware/headless.c b/df_datalink_ge/src/hardware/headless.c deleted file mode 100644 index 642e7bc..0000000 --- a/df_datalink_ge/src/hardware/headless.c +++ /dev/null @@ -1,1177 +0,0 @@ -/******************************************************************************* * @file ad9371/src/app/headless.c - * @brief Implementation of Main Function. - ******************************************************************************** - * Copyright 2017(c) Analog Devices, Inc. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Analog Devices, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - The use of this software may or may not infringe the patent rights - * of one or more patent holders. This license does not release you - * from the requirement that you obtain separate licenses from these - * patent holders to use this software. - * - Use of the software either in source or binary form, must be run - * on or directly connected to an Analog Devices Inc. component. - * - * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *******************************************************************************/ - -/***************************** Include Files ********************************/ -#include "headless.h" - -/************************** Constant Definitions *****************************/ - -/**************************** Type Definitions *******************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ - -/************************** Variable Definitions *****************************/ - -// XGpio GpioFreqCtrl; -// XGpio GpioGainCtrl; -// XGpio GpioAttnCtrl; -XScuGic Intc; - -/************************** Function Prototypes ******************************/ - -int HARDWARE_initialize() -{ - int Status; - - // use configuration - mykDevice.rx->rxPllLoFrequency_Hz = 2500000000u; - mykDevice.tx->txPllLoFrequency_Hz = 2500000000u; - mykDevice.tx->tx1Atten_mdB = 20000; - mykDevice.tx->tx2Atten_mdB = 20000; - - Status = HARDWARE_ad9371Config(); - - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - // /**********************************************************/ - // /************ AD9371 Dynamical Reconfiguration ************/ - // /**********************************************************/ - // Status = HW_ad9371DynamicCfgInit(); - // if (Status != ADIERR_OK){ - // HW_PRINT("HW:: AD9371 dynamic configuration initialization failed!\n"); - // return ADIERR_FAILED; - // } - // - // HW_PRINT("HW:: AD9371 ready to be reconfigured!\n"); - // - // // main loop - // while(1); - - // never reach - return ADIERR_OK; -} - -// this function is NOT safe -int HARDWARE_ad9371Config(void) -{ - int Status; - uint8_t reg508; - uint8_t framerStatus; - uint8_t obsFramerStatus; - uint8_t deframerStatus; - - /**********************************************************/ - /*********** Initialize Configuration Interface ***********/ - /**********************************************************/ - Status = CMB_initPlatform(); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - Status = HW_adiCfgProfileInit(); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - HW_PRINT("HW:: Initialize configuration interface done!\n"); - - /**********************************************************/ - /****************** AD9528 Configuration ******************/ - /**********************************************************/ - Status = HW_9528Config(ad9528Init); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - HW_PRINT("HW:: AD9528 configuration done!\n"); - - Status = HW_9528GetLockStatus(ad9528Init, ®508); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - HW_PRINT("HW:: AD9528 REG508: 0x%02x\n", reg508); - - /**********************************************************/ - /****************** AD9371 Configuration ******************/ - /**********************************************************/ - Status = HW_9371Config(ad9528Init, &mykDevice); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - - Status = HW_9371CheckJesdStatus(&mykDevice, &framerStatus, - &obsFramerStatus, &deframerStatus); - if (Status != ADIERR_OK) - { - return ADIERR_FAILED; - } - else - { - // typical value: 0x3E - HW_PRINT("HW:: RxFramerStatus = 0x%x\n", framerStatus); - // typical value: 0x3E - HW_PRINT("HW:: OrxFramerStatus = 0x%x\n", obsFramerStatus); - // typical value: 0x28 - HW_PRINT("HW:: DeframerStatus = 0x%x\n", deframerStatus); - } - - HW_PRINT("HW:: All configuration done!\n"); - - return ADIERR_OK; -} - -// this function is NOT safe -// int HW_ad9371DynamicCfgInit(void) -//{ -// int Status; -// -// Status = HW_setupIntrSystem(INTC_DEVICE_ID, &Intc); -// if (Status != XST_SUCCESS) { -// HW_PRINT("HW: HW_setupIntrSystem() failed!\n"); -// return XST_FAILURE; -// } -// -// Status = XGpio_Initialize(&GpioFreqCtrl, FREQ_CTRL_DEVICE_ID); -// Status |= XGpio_Initialize(&GpioGainCtrl, GAIN_CTRL_DEVICE_ID); -// Status |= XGpio_Initialize(&GpioAttnCtrl, ATTN_CTRL_DEVICE_ID); -// if (Status != XST_SUCCESS) { -// HW_PRINT("HW: GPIO init failed!\n"); -// return XST_FAILURE; -// } -// -// /* Set the direction for all signals as inputs. */ -// XGpio_SetDataDirection(&GpioFreqCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); -// XGpio_SetDataDirection(&GpioFreqCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); -// -// XGpio_SetDataDirection(&GpioGainCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); -// XGpio_SetDataDirection(&GpioGainCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); -// -// XGpio_SetDataDirection(&GpioAttnCtrl, AXI_GPIO_BANK_1, 0xFFFFFFFF); -// XGpio_SetDataDirection(&GpioAttnCtrl, AXI_GPIO_BANK_2, 0xFFFFFFFF); -// -// Status = HW_connectIntr(&Intc, FREQ_CTRL_INTR_ID, -// (Xil_InterruptHandler)FreqIntrHandler, &GpioFreqCtrl, 0xA0, 0x3); -// Status |= HW_connectIntr(&Intc, GAIN_CTRL_INTR_ID, -// (Xil_InterruptHandler)GainIntrHandler, &GpioGainCtrl, 0xA0, 0x3); -// Status |= HW_connectIntr(&Intc, ATTN_CTRL_INTR_ID, -// (Xil_InterruptHandler)AttnIntrHandler, &GpioAttnCtrl, 0xA0, 0x3); -// -// XGpio_InterruptEnable(&GpioFreqCtrl, XGPIO_IR_MASK); -// XGpio_InterruptGlobalEnable(&GpioFreqCtrl); -// -// XGpio_InterruptEnable(&GpioGainCtrl, XGPIO_IR_MASK); -// XGpio_InterruptGlobalEnable(&GpioGainCtrl); -// -// XGpio_InterruptEnable(&GpioAttnCtrl, XGPIO_IR_MASK); -// XGpio_InterruptGlobalEnable(&GpioAttnCtrl); -// -// return XST_SUCCESS; -//} - -/*****************************************************************************/ -/* - * - * This function setups the interrupt system. - * - * @param DeviceId is the unique identifier for a GIC device. - * @param GicPtr is a pointer to the instance of the INTC. - * - * @return - * - XST_SUCCESS if successful, - * - XST_FAILURE.if not succesful - * - * @note None. - * - ******************************************************************************/ -int HW_setupIntrSystem(u16 DeviceId, XScuGic *GicPtr) -{ - int Status; - XScuGic_Config *CfgPtr; - - /* - * Initialize the interrupt controller driver so that it is ready to - * use. - */ - CfgPtr = XScuGic_LookupConfig(DeviceId); - if (!CfgPtr) - { - HW_PRINT("No interrupt config found for %d\n", DeviceId); - return XST_FAILURE; - } - - Status = XScuGic_CfgInitialize(GicPtr, CfgPtr, CfgPtr->CpuBaseAddress); - if (Status != XST_SUCCESS) - { - HW_PRINT("No interrupt config found for %d\n", DeviceId); - return XST_FAILURE; - } - - Xil_ExceptionInit(); - Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, - (Xil_ExceptionHandler)XScuGic_InterruptHandler, - (void *)GicPtr); - Xil_ExceptionEnable(); - - return XST_SUCCESS; -} - -int HW_connectIntr(XScuGic *GicPtr, u32 IntrId, Xil_InterruptHandler Handler, - void *CallBackRef, u8 Priority, u8 Trigger) -{ - int Status; - // Register interrupt handler - Status = XScuGic_Connect(GicPtr, IntrId, (Xil_InterruptHandler)Handler, - CallBackRef); - if (Status != XST_SUCCESS) - { - return XST_FAILURE; - } - XScuGic_SetPriorityTriggerType(GicPtr, IntrId, Priority, Trigger); - - XScuGic_Enable(GicPtr, IntrId); - - return XST_SUCCESS; -} - -int HW_adiCfgProfileInit(void) -{ - if (!ad9528Init) - { - HW_PRINT("Cannot find ad9528 configuration profile with name 'ad9528Init'!"); - return ADIERR_FAILED; - } - - if (!&mykDevice) - { - HW_PRINT("Cannot find ad9371 configuration profile with name 'mykDevice'!"); - return ADIERR_FAILED; - } - - ad9528Init->spiSettings->chipSelectIndex = AD9528_CS; - mykDevice.spiSettings->chipSelectIndex = AD9371_CS; - - mykDevice.rx->framer->serializerLanesEnabled = 0x03; - mykDevice.rx->framer->serializerLaneCrossbar = 0xE4; - mykDevice.obsRx->framer->serializerLanesEnabled = 0x04; - mykDevice.tx->deframer->deserializerLanesEnabled = 0x03; - mykDevice.tx->deframer->deserializerLaneCrossbar = 0xE4; - - return ADIERR_OK; -} - -int HW_9528Config(ad9528Device_t *clockAD9528_device) -{ - ADI_ERR error; - /**************************************************************************/ - /***** System Clocks Initialization Initialization Sequence *****/ - /**************************************************************************/ - - /* Perform a hard reset on the AD9528 DUT */ - error = AD9528_resetDevice(clockAD9528_device); - if (error != ADIERR_OK) - { - HW_PRINT("AD9528_resetDevice() failed\n"); - return ADIERR_FAILED; - } - - error = AD9528_initDeviceDataStruct(clockAD9528_device, - clockAD9528_device->pll1Settings->vcxo_Frequency_Hz, - clockAD9528_device->pll1Settings->refA_Frequency_Hz, - clockAD9528_device->outputSettings->outFrequency_Hz[1]); - if (error != ADIERR_OK) - { - HW_PRINT("AD9528_initDeviceDataStruct() failed\n"); - return ADIERR_FAILED; - } - - /* Initialize the AD9528 by writing all SPI registers */ - error = AD9528_initialize(clockAD9528_device); - if (error != ADIERR_OK) - { - HW_PRINT("WARNING: AD9528_initialize() issues.\n"); - } - - return ADIERR_OK; -} - -int HW_9528GetLockStatus(ad9528Device_t *device, uint8_t *reg508) -{ - ADI_ERR error; - - error = CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, reg508); - if (error != ADIERR_OK) - { - HW_PRINT("HW_9528GetLockStatus failed.\n"); - return ADIERR_FAILED; - } - - return ADIERR_OK; -} - -int HW_9371Config(ad9528Device_t *clockAD9528_device, mykonosDevice_t *mykDevice) -{ - ADI_ERR error; - mykonosErr_t mykError; - const char *errorString; - uint8_t pllLockStatus; - uint8_t mcsStatus; - uint8_t arm_major; - uint8_t arm_minor; - uint8_t arm_release; - uint32_t initCalMask = TX_BB_FILTER | ADC_TUNER | TIA_3DB_CORNER | DC_OFFSET | - TX_ATTENUATION_DELAY | RX_GAIN_DELAY | FLASH_CAL | - PATH_DELAY | TX_LO_LEAKAGE_INTERNAL | TX_QEC_INIT | - LOOPBACK_RX_LO_DELAY | LOOPBACK_RX_RX_QEC_INIT | - RX_LO_DELAY | RX_QEC_INIT; - uint8_t errorFlag = 0; - uint8_t errorCode = 0; - uint32_t initCalsCompleted; - uint32_t trackingCalMask = TRACK_ORX1_QEC | TRACK_ORX2_QEC | TRACK_RX1_QEC | - TRACK_RX2_QEC | TRACK_TX1_QEC | TRACK_TX2_QEC; - - /* Allocating memory for the errorString */ - errorString = NULL; - - /*************************************************************************/ - /***** Mykonos Initialization Sequence *****/ - /*************************************************************************/ - - /* Perform a hard reset on the MYKONOS DUT (Toggle RESETB pin on device) */ - if ((mykError = MYKONOS_resetDevice(mykDevice)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_initialize(mykDevice)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /*************************************************************************/ - /***** Mykonos CLKPLL Status Check *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_checkPllsLockStatus(mykDevice, - &pllLockStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /*************************************************************************/ - /***** Mykonos Perform MultiChip Sync *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_enableMultichipSync(mykDevice, 1, - &mcsStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /* Minimum 3 SYSREF pulses from Clock Device has to be produced for MulticChip Sync */ - - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - - /*************************************************************************/ - /***** Mykonos Verify MultiChip Sync *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_enableMultichipSync(mykDevice, 0, - &mcsStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mcsStatus & 0x0B) == 0x0B) - HW_PRINT("MCS successful\n"); - else - HW_PRINT("MCS failed\n"); - - /*************************************************************************/ - /***** Mykonos Load ARM file *****/ - /*************************************************************************/ - - if (pllLockStatus & 0x01) - { - HW_PRINT("CLKPLL locked\n"); - if ((mykError = MYKONOS_initArm(mykDevice)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_loadArmFromBinary(mykDevice, - &firmware_Mykonos_M3_bin[0], firmware_Mykonos_M3_bin_len)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - } - else - { - HW_PRINT("CLKPLL not locked (0x%x)\n", pllLockStatus); - error = ADIERR_FAILED; - goto error_2; - } - - /* Read back the version of the ARM binary loaded into the Mykonos ARM memory */ - if ((mykError = MYKONOS_getArmVersion(mykDevice, &arm_major, &arm_minor, - &arm_release, NULL)) == MYKONOS_ERR_OK) - HW_PRINT("AD9371 ARM version %d.%d.%d\n", arm_major, arm_minor, arm_release); - - /*************************************************************************/ - /***** Mykonos Set RF PLL Frequencies *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, RX_PLL, - mykDevice->rx->rxPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, - mykDevice->tx->txPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, SNIFFER_PLL, - mykDevice->obsRx->snifferPllLoFrequency_Hz)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /* Wait 200ms for PLLs to lock */ - mdelay(200); - - if ((mykError = MYKONOS_checkPllsLockStatus(mykDevice, - &pllLockStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((pllLockStatus & 0x0F) == 0x0F) - HW_PRINT("PLLs locked\n"); - else - { - HW_PRINT("PLLs not locked (0x%x)\n", pllLockStatus); - error = ADIERR_FAILED; - goto error_2; - } - - // /*************************************************************************/ - // /***** Mykonos Set GPIOs *****/ - // /*************************************************************************/ - // - // if ((mykGpioErr = MYKONOS_setRx1GainCtrlPin(mykDevice, 0, 0, 0, 0, - // 0)) != MYKONOS_ERR_GPIO_OK) { - // errorString = getGpioMykonosErrorMessage(mykGpioErr); - // goto error_11; - // } - // - // if ((mykGpioErr = MYKONOS_setRx2GainCtrlPin(mykDevice, 0, 0, 0, 0, - // 0)) != MYKONOS_ERR_GPIO_OK) { - // errorString = getGpioMykonosErrorMessage(mykGpioErr); - // goto error_11; - // } - // - // if ((mykGpioErr = MYKONOS_setTx1AttenCtrlPin(mykDevice, 0, 0, 0, 0, - // 0)) != MYKONOS_ERR_GPIO_OK) { - // errorString = getGpioMykonosErrorMessage(mykGpioErr); - // goto error_11; - // } - // - // if ((mykGpioErr = MYKONOS_setTx2AttenCtrlPin(mykDevice, 0, 0, 0, - // 0)) != MYKONOS_ERR_GPIO_OK) { - // errorString = getGpioMykonosErrorMessage(mykGpioErr); - // goto error_11; - // } - // - // if ((mykGpioErr = MYKONOS_setupGpio(mykDevice)) != MYKONOS_ERR_GPIO_OK) { - // errorString = getGpioMykonosErrorMessage(mykGpioErr); - // goto error_11; - // } - // - // /*************************************************************************/ - // /***** Mykonos Set manual gains values *****/ - // /*************************************************************************/ - // - // if ((mykError = MYKONOS_setRx1ManualGain(mykDevice, 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setRx2ManualGain(mykDevice, 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_RX1_TXLO, - // 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_RX2_TXLO, - // 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_A, - // 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_B, - // 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // if ((mykError = MYKONOS_setObsRxManualGain(mykDevice, OBS_SNIFFER_C, - // 255)) != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // /*************************************************************************/ - // /***** Mykonos Initialize attenuations *****/ - // /*************************************************************************/ - // - // mykError = MYKONOS_setTx1Attenuation(mykDevice, 10000); - // if (mykError != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - // - // mykError = MYKONOS_setTx2Attenuation(mykDevice, 10000); - // if (mykError != MYKONOS_ERR_OK) { - // errorString = getMykonosErrorMessage(mykError); - // goto error_11; - // } - - /*************************************************************************/ - /***** Mykonos ARM Initialization Calibrations *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_runInitCals(mykDevice, - (initCalMask & ~TX_LO_LEAKAGE_EXTERNAL))) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, - &errorCode)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((errorFlag != 0) || (errorCode != 0)) - { - /*** < Info: abort init cals > ***/ - if ((mykError = MYKONOS_abortInitCals(mykDevice, - &initCalsCompleted)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - if (initCalsCompleted) - HW_PRINT("Completed calibrations: %x\n", (unsigned int)initCalsCompleted); - } - else - HW_PRINT("Calibrations completed successfully\n"); - - /*************************************************************************/ - /***** Mykonos ARM Initialization External LOL Calibrations with PA *****/ - /*************************************************************************/ - - /* Please ensure PA is enabled operational at this time */ - if (initCalMask & TX_LO_LEAKAGE_EXTERNAL) - { - if ((mykError = MYKONOS_runInitCals(mykDevice, - TX_LO_LEAKAGE_EXTERNAL)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, - &errorCode)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((errorFlag != 0) || (errorCode != 0)) - { - /*** < Info: abort init cals > ***/ - if ((mykError = MYKONOS_abortInitCals(mykDevice, - &initCalsCompleted)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - } - else - HW_PRINT("External LOL Calibrations completed successfully\n"); - } - - /*************************************************************************/ - /***** SYSTEM JESD bring up procedure *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_enableSysrefToRxFramer(mykDevice, - 1)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the RxFramer> ***/ - - if ((mykError = MYKONOS_enableSysrefToObsRxFramer(mykDevice, - 1)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - /*** < Info: Mykonos is waiting for sysref in order to start - * transmitting CGS from the ObsRxFramer> ***/ - - if ((mykError = MYKONOS_enableSysrefToDeframer(mykDevice, - 0)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_resetDeframer(mykDevice)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - if ((mykError = MYKONOS_enableSysrefToDeframer(mykDevice, 1)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /*************************************************************************/ - /***** Enable SYSREF to Mykonos and BBIC *****/ - /*************************************************************************/ - - /* Request a SYSREF from the AD9528 */ - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - - /*** < Info: Mykonos is actively transmitting CGS from the RxFramer> ***/ - - /*** < Info: Mykonos is actively transmitting CGS from the ObsRxFramer> ***/ - - /* Request two SYSREFs from the AD9528 */ - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(1); - AD9528_requestSysref(clockAD9528_device, 1); - mdelay(5); - - /*************************************************************************/ - /***** Mykonos enable tracking calibrations *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_enableTrackingCals(mykDevice, - trackingCalMask)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /*** < Info: Allow Rx1/2 QEC tracking and Tx1/2 QEC tracking to run when in the radioOn state - * Tx calibrations will only run if radioOn and the obsRx path is set to OBS_INTERNAL_CALS > ***/ - - /*** < Info: Function to turn radio on, Enables transmitters and receivers - * that were setup during MYKONOS_initialize() > ***/ - if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - /*** < Info: Allow TxQEC to run when User: is not actively using ORx receive path > ***/ - if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, - OBS_RXOFF)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, - OBS_INTERNALCALS)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - mdelay(1000); - - if ((mykError = MYKONOS_setObsRxPathSource(mykDevice, - OBS_RX1_SNIFFERLO)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - goto error_11; - } - - Xil_DCacheInvalidateRange(DDR_MEM_BASEADDR + 0x800000, 16384 * 8); - - HW_PRINT("Done\n"); - - return 0; - -error_11: - HW_PRINT("%s", errorString); - -error_2: - // axi_clkgen_remove(rx_clkgen); - return FAILURE; -} - -int HW_9371CheckJesdStatus(mykonosDevice_t *mykDevice, uint8_t *framerStatus, - uint8_t *obsFramerStatus, uint8_t *deframerStatus) -{ - mykonosErr_t mykError; - const char *errorString; - /* Allocating memory for the errorString */ - errorString = NULL; - - /*************************************************************************/ - /***** Check Mykonos Framer Status *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_readRxFramerStatus(mykDevice, - framerStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - return ADIERR_FAILED; - } - else - { - // typical value: 0x3E - } - - if ((mykError = MYKONOS_readOrxFramerStatus(mykDevice, - obsFramerStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - return ADIERR_FAILED; - } - else - { - // typical value: 0x3E - } - - /*************************************************************************/ - /***** Check Mykonos Deframer Status *****/ - /*************************************************************************/ - - if ((mykError = MYKONOS_readDeframerStatus(mykDevice, - deframerStatus)) != MYKONOS_ERR_OK) - { - errorString = getMykonosErrorMessage(mykError); - return ADIERR_FAILED; - } - else - { - // typical value: 0x28 - } - - return ADIERR_OK; -} - -int HW_9371SmallFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz) -{ - mykonosErr_t mykError = MYKONOS_ERR_OK; - uint8_t pllLockStatus = 0; - /* - * Move the device into the radio off state. - */ - if ((mykError = MYKONOS_radioOff(mykDevice)) != MYKONOS_ERR_OK) - { - HW_PRINT("Turn radio off failed!\n\r"); - return ADIERR_FAILED; - } - - /* - * Program the new local oscillator (LO) frequency. Check if PLL is locked. - */ - if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, - freq_Hz)) != MYKONOS_ERR_OK) - { - HW_PRINT("Set TX PLL failed!\n\r"); - return ADIERR_FAILED; - } - mykError = MYKONOS_checkPllsLockStatus(mykDevice, &pllLockStatus); - if ((pllLockStatus & 0x07) != 0x07) - { - /*** < Info: Clock, Rx and Tx PLLs not locked > ***/ - HW_PRINT("Not all PLLs locked, lock status: 0x%02x\n", pllLockStatus); - } - - /* - * Reset the external channel. - */ - // If((mykError = MYKONOS_resetExtTxLolChannel(mykDevice, TX1_TX2)) - // != MYKONOS_ERR_OK) ; //where TX1_TX2 is part of the enum mykonosTxChannels_t - // { - // HW_PRINT("Reset external channel FAILED!"); - // } - - /* - * Move the device back into the radio on state. - */ - if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) - { - HW_PRINT("Turn radio on failed!\n\r"); - return ADIERR_FAILED; - } - - /* - * Reenable tracking calibrations. - */ - // If((mykError = MYKONOS_MYKONOS_setObsRxPathSource(mykDevice, OBS_INTERNALCALS)) - // != MYKONOS_ERR_OK) ; //where TX1_TX2 is part of the enum mykonosTxChannels_t - // { - // HW_PRINT("Reenable tracking calibrations FAILED!"); - // } - return ADIERR_OK; -} - -int HW_9371LargeFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz) -{ - mykonosErr_t mykError = MYKONOS_ERR_OK; - uint8_t pllLockStatus = 0; - uint8_t errorFlag = 0; - uint8_t errorCode = 0; - uint32_t initCalsCompleted = 0; - uint16_t errorWord = 0; - uint16_t statusWord = 0; - uint8_t status = 0; - mykonosInitCalStatus_t initCalStatus = {0}; - - /* - * Move the device into the radio off state. - */ - if ((mykError = MYKONOS_radioOff(mykDevice)) != MYKONOS_ERR_OK) - { - HW_PRINT("Turn radio off failed!\n\r"); - return ADIERR_FAILED; - } - - /* - * Program the new local oscillator (LO) frequency. Check if PLL is locked. - */ - if ((mykError = MYKONOS_setRfPllFrequency(mykDevice, TX_PLL, - freq_Hz)) != MYKONOS_ERR_OK) - { - HW_PRINT("Set TX PLL failed!\n\r"); - return ADIERR_FAILED; - } - mykError = MYKONOS_checkPllsLockStatus(mykDevice, &pllLockStatus); - if ((pllLockStatus & 0x07) != 0x07) - { - /*** < Info: Clock, Rx and Tx PLLs not locked > ***/ - HW_PRINT("Not all PLLs locked, lock status: 0x%02x\n", pllLockStatus); - } - - /* - * Rerun the initialization calibrations. - */ - uint32_t initCalMask = TX_QEC_INIT | LOOPBACK_RX_LO_DELAY | - LOOPBACK_RX_RX_QEC_INIT | RX_LO_DELAY | RX_QEC_INIT; - if ((mykError = MYKONOS_runInitCals(mykDevice, initCalMask)) != MYKONOS_ERR_OK) - { - HW_PRINT("Rerun the initialization calibrations FAILED!"); - return ADIERR_FAILED; - } - if ((mykError = MYKONOS_waitInitCals(mykDevice, 60000, &errorFlag, - &errorCode)) != MYKONOS_ERR_OK) - { - HW_PRINT("Initialize calibration TIME OUT!"); - return ADIERR_FAILED; - } - if ((errorFlag != 0) || (errorCode != 0)) - { - HW_PRINT("initial cals error!\n\r"); - - if ((mykError = MYKONOS_getInitCalStatus(mykDevice, &initCalStatus)) != MYKONOS_ERR_OK) - { - /*** < User log error return value to debug why init failed > ***/ - } - - // abort init calibrations - if ((mykError = MYKONOS_abortInitCals(mykDevice, &initCalsCompleted)) != MYKONOS_ERR_OK) - { - /*** < User log error return value to debug why init failed > ***/ - } - if (initCalsCompleted) - { - /*** < which calls had completed, per the mask > ***/ - } - if ((mykError = MYKONOS_readArmCmdStatus(mykDevice, &errorWord, - &statusWord)) != MYKONOS_ERR_OK) - { - /*** < User log error return value to debug why init failed > ***/ - } - if ((mykError = MYKONOS_readArmCmdStatusByte(mykDevice, 2, &status)) != MYKONOS_ERR_OK) - { - } - if (status != 0) - { - /*** < Arm Mailbox Status Error errorWord > ***/ - /*** < Pending Flag per opcode statusWord, this follows the mask > ***/ - } - } - - /* - * Move the device back into the radio on state. - */ - if ((mykError = MYKONOS_radioOn(mykDevice)) != MYKONOS_ERR_OK) - { - HW_PRINT("Turn radio on failed!\n\r"); - return ADIERR_FAILED; - } - - return ADIERR_OK; -} - -// void FreqIntrHandler(void *CallbackRef) -// { -// XGpio *GpioPtr = (XGpio *)CallbackRef; -// uint8_t IntrStatus; -// uint32_t NewFreqHz; -// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); - -// if (IntrStatus & XGPIO_IR_CH1_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); - -// NewFreqHz = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); -// if (NewFreqHz != mykDevice.tx->txPllLoFrequency_Hz) -// { -// if (NewFreqHz > 300000000 && NewFreqHz < 6000000000) -// { -// if (abs(NewFreqHz - mykDevice.tx->txPllLoFrequency_Hz) <= 100000000) -// { -// HW_9371SmallFrequencyChange(&mykDevice, NewFreqHz); -// } -// else -// { -// HW_9371LargeFrequencyChange(&mykDevice, NewFreqHz); -// } -// mykDevice.tx->txPllLoFrequency_Hz = NewFreqHz; -// HW_PRINT("New Tx frequency set to %d Hz!\n", NewFreqHz); -// } -// else -// { -// HW_PRINT("The desired Tx Frequency is out of range(300 ~ 6000 MHz)!\n"); -// } -// } -// } - -// if (IntrStatus & XGPIO_IR_CH2_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); - -// NewFreqHz = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); -// if (NewFreqHz != mykDevice.rx->rxPllLoFrequency_Hz) -// { -// if (NewFreqHz > 300000000 && NewFreqHz < 6000000000) -// { -// if (abs(NewFreqHz - mykDevice.rx->rxPllLoFrequency_Hz) <= 100000000) -// { -// HW_9371SmallFrequencyChange(&mykDevice, NewFreqHz); -// } -// else -// { -// HW_9371LargeFrequencyChange(&mykDevice, NewFreqHz); -// } -// mykDevice.rx->rxPllLoFrequency_Hz = NewFreqHz; -// HW_PRINT("New Rx frequency set to %d Hz!\n", NewFreqHz); -// } -// else -// { -// HW_PRINT("The desired Rx Frequency is out of range(300 ~ 6000 MHz)!\n"); -// } -// } -// } -// } - -// void GainIntrHandler(void *CallbackRef) -// { -// XGpio *GpioPtr = (XGpio *)CallbackRef; -// uint8_t IntrStatus; -// uint32_t NewRxGain; -// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); - -// if (IntrStatus & XGPIO_IR_CH1_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); - -// NewRxGain = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); -// if (NewRxGain != mykDevice.rx->rxGainCtrl->rx1GainIndex) -// { -// if ((NewRxGain >= 195) && (NewRxGain <= 255)) -// { -// MYKONOS_setRx1ManualGain(&mykDevice, NewRxGain); -// mykDevice.rx->rxGainCtrl->rx1GainIndex = NewRxGain; -// char buf[BUFSIZ]; -// sHW_PRINT(buf, "%u", NewRxGain); -// HW_PRINT("New Rx1 gain index set to %s!\n", buf); -// } -// else -// { -// HW_PRINT("The desired Rx1 gain index is out of range(195 ~ 255), 0.5dB per stage!\n"); -// } -// } -// } - -// if (IntrStatus & XGPIO_IR_CH2_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); - -// NewRxGain = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); -// if (NewRxGain != mykDevice.rx->rxGainCtrl->rx2GainIndex) -// { -// if ((NewRxGain >= 195) && (NewRxGain <= 255)) -// { -// MYKONOS_setRx2ManualGain(&mykDevice, NewRxGain); -// mykDevice.rx->rxGainCtrl->rx2GainIndex = NewRxGain; -// char buf[BUFSIZ]; -// sHW_PRINT(buf, "%u", NewRxGain); -// HW_PRINT("New Rx2 gain index set to %s!\n", buf); -// } -// else -// { -// HW_PRINT("The desired Rx2 gain index is out of range(195 ~ 255), 0.5dB per stage!\n"); -// } -// } -// } -// } - -// void AttnIntrHandler(void *CallbackRef) -// { -// XGpio *GpioPtr = (XGpio *)CallbackRef; -// uint8_t IntrStatus; -// uint32_t NewTxAttn; -// IntrStatus = XGpio_InterruptGetStatus(GpioPtr); - -// if (IntrStatus & XGPIO_IR_CH1_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH1_MASK); - -// NewTxAttn = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_1); -// if (NewTxAttn != mykDevice.tx->tx1Atten_mdB) -// { -// if ((NewTxAttn >= 0) && (NewTxAttn <= 41950)) -// { -// MYKONOS_setTx1Attenuation(&mykDevice, NewTxAttn); -// mykDevice.tx->tx1Atten_mdB = NewTxAttn; -// char buf[BUFSIZ]; -// sHW_PRINT(buf, "%u", NewTxAttn); -// HW_PRINT("New Tx1 attenuation set to %s dBm!\n", buf); -// } -// else -// { -// HW_PRINT("The desired Tx1 attenuation is out of range(0 ~ 41950 dBm), 50 dBm step!\n"); -// } -// } -// } - -// if (IntrStatus & XGPIO_IR_CH2_MASK) -// { -// /* Clear the Interrupt */ -// XGpio_InterruptClear(GpioPtr, XGPIO_IR_CH2_MASK); - -// NewTxAttn = XGpio_DiscreteRead(GpioPtr, AXI_GPIO_BANK_2); -// if (NewTxAttn != mykDevice.tx->tx2Atten_mdB) -// { -// if ((NewTxAttn >= 0) && (NewTxAttn <= 41950)) -// { -// MYKONOS_setTx2Attenuation(&mykDevice, NewTxAttn); -// mykDevice.tx->tx2Atten_mdB = NewTxAttn; -// char buf[BUFSIZ]; -// sHW_PRINT(buf, "%u", NewTxAttn); -// HW_PRINT("New Tx2 attenuation set to %s dBm!\n", buf); -// } -// else -// { -// HW_PRINT("The desired Tx2 attenuation is out of range(0 ~ 41950 dBm), 50 dBm step!\n"); -// } -// } -// } -// } diff --git a/df_datalink_ge/src/hardware/headless.h b/df_datalink_ge/src/hardware/headless.h deleted file mode 100644 index 384f8cf..0000000 --- a/df_datalink_ge/src/hardware/headless.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - * headless.h - * - * Created on: 2021��6��8�� - * Author: Josh - */ - -#ifndef SRC_HEADLESS_H_ -#define SRC_HEADLESS_H_ - -/***************************** Include Files ********************************/ -#include -#include -#include "xil_cache.h" -#include "xscugic.h" -//#include "xgpio.h" - -#include "common.h" -#include "./mykonos/ad9528.h" -#include "./mykonos/mykonos.h" -#include "./mykonos/Mykonos_M3.h" -#include "./mykonos/mykonos_gpio.h" -#include "myk_ad9528init.h" -#include "myk_init.h" - -#include "parameters.h" - -/************************** Constant Definitions *****************************/ - -/**************************** Type Definitions *******************************/ - -/***************** Macros (Inline Functions) Definitions *********************/ -#define HW_PRINT(...) __asm__("nop") -// #define HW_PRINT(...) printf(__VA_ARGS__) -/************************** Variable Definitions *****************************/ - -/************************** Function Prototypes ******************************/ - -/*****************************************************************************/ -/* -* -* This function setups ad9528 and ad9371 via spi. -* -* @param None. -* -* @return -* - ADIERR_FAILED if successful, -* - ADIERR_OK if not succesful -* -* @note None. -* -******************************************************************************/ -int HARDWARE_initialize(); - -int HARDWARE_ad9371Config(void); - -/*****************************************************************************/ -/* -* -* Setup up Axi Gpio, through which ad9371 can be reconfigured. Axi Gpio -* instance and interrupt system initialization are included. -* -* @param None. -* -* @return -* - ADIERR_FAILED if successful, -* - ADIERR_OK if not succesful -* -* @note None. -* -******************************************************************************/ -int HW_ad9371DynamicCfgInit(void); - -/*****************************************************************************/ -/* -* -* Setup up interrupt system, initialize exception handlers. -* -* @param DeviceId is the unique identifier for a device. -* @param GicPtr is a pointer to the XScuGic instance. -* -* @return -* - XST_SUCCESS if successful, -* - XST_FAILURE if not succesful -* -* @note None. -* -******************************************************************************/ -int HW_setupIntrSystem(u16 DeviceId, XScuGic * GicPtr); - -/*****************************************************************************/ -/* -* -* Make the connection between the Int_Id of the interrupt source and the -* associated handler. Set the interrupt priority and trigger type for the -* specified IRQ source.. -* -* @param GicPtr is a pointer to the XScuGic instance. -* @param Int_Id contains the ID of the interrupt source and should be -* in the range of 0 to XSCUGIC_MAX_NUM_INTR_INPUTS - 1 -* @param Handler to the handler for that interrupt. -* @param CallBackRef is the callback reference, usually the instance -* pointer of the connecting driver. -* @param Priority is the new priority for the IRQ source. 0 is highest -* priority, 0xF8(248) is lowest. There are 32 priority levels -* supported with a step of 8. Hence the supported priorities are -* 0, 8, 16, 32, 40 ..., 248. -* @param Trigger is the new trigger type for the IRQ source. -* Each bit pair describes the configuration for an INT_ID. -* SFI Read Only b10 always -* PPI Read Only depending on how the PPIs are configured. -* b01 Active HIGH level sensitive -* b11 Rising edge sensitive -* SPI LSB is read only. -* b01 Active HIGH level sensitive -* b11 Rising edge sensitive/ -* -* @return -* - XST_SUCCESS if successful, -* - XST_FAILURE if not succesful -* -* @note None. -* -******************************************************************************/ -int HW_connectIntr(XScuGic *GicPtr,u32 IntrId,Xil_InterruptHandler Handler, - void *CallBackRef, u8 Priority, u8 Trigger); - -/*****************************************************************************/ -/* -* -* Initialize Analog Device related configuration profile. This is a HARDWARE- -* ASSOTIATED function, which may differ between different board. -* -* @param None. -* -* @return -* - ADIERR_OK if configuration profile exists, -* - ADIERR_FAILED if onfiguration profile does not exist -* -* @note None. -* -******************************************************************************/ -int HW_adiCfgProfileInit(void); - -/******************************************************************************/ -/** -* -* This function conducts AD9528 device configuration initializing procedure. -* -* @param clockAD9528_device is a pointer to the data structure holding -* AD9528 settings, which contains basic AD9528 settings such as -* spi and gpio. -* -* @return -* - ADIERR_OK if successful. -* - ADIERR_FAILED if not successful. -* -* @note None. -* -*******************************************************************************/ -int HW_9528Config(ad9528Device_t *clockAD9528_device); - -/******************************************************************************/ -/** -* -* This function read AD9528 reg508 status, to check whether ad9528 is locked or -* not. -* -* @param clockAD9528_device is a pointer to the data structure holding -* AD9528 settings, which contains basic AD9528 settings. -* -* @return -* - ADIERR_OK if successful. -* - ADIERR_FAILED if not successful. -* -* @note None. -* -*******************************************************************************/ -int HW_9528GetLockStatus(ad9528Device_t *device, uint8_t *reg508); - -/******************************************************************************/ -/** -* -* Conduct AD9371 device configuration initializing procedure. -* -* @param clockAD9528_device is a pointer to the data structure holding -* AD9528 settings, which contains basic AD9528 settings. -* @param mykDevice is ADI hardware layer settings pointer specific to -* a Mykonos instance which contains basic settings such as spi, -* gpio, tx/rx and jesd configurations. -* -* @return -* - ADIERR_OK if successful. -* - ADIERR_FAILED if not successful. -* -* @note None. -* -*******************************************************************************/ -int HW_9371Config(ad9528Device_t *clockAD9528_device, mykonosDevice_t *mykDevice); - -/******************************************************************************/ -/** -* -* Read AD9371's RX framer, ORX framer and TX deframer status, to check jesd204b -* sync status. -* -* @param mykDevice is ADI hardware layer settings pointer specific to -* a Mykonos instance which contains basic settings such as spi, -* gpio, tx/rx and jesd configurations. -* @param framerStatus is the RX framer status byte read -* framerStatus | Description -* -------------|----------------------------------------------------------------------------- -* [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. -* [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. -* [5] | Framer has received the SYSREF and has retimed its LMFC -* [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete -* [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data -* @param obsFramerStatus is the ORX framer status byte read -* obsFramerStatus | Description -* ----------------|----------------------------------------------------------------------------- -* [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. -* [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. -* [5] | Framer has received the SYSREF and has retimed its LMFC -* [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete -* [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data -* @param deframerStatus is the TX deframer status byte read -* deframerStatus | Bit Name | Description -* ----------------|--------------------------|--------------------------------------------- -* [7] | Unused | Unused -* [6] | Deframer IRQ | This bit indicates that the IRQ interrupt was asserted. -* [5] | Deframer SYSREF Received | When this bit is set, it indicates that the SYSREF pulse was received by the deframer IP -* [4] | Deframer Receiver Error | This bit is set when PRBS has received an error. -* [3] | Valid Checksum | This bit is set when the received ILAS checksum is valid. -* [2] | EOF Event | This bit captures the internal status of the framer End of Frame event. Value =1 if framing error during ILAS -* [1] | EOMF Event | This bit captures the internal status of the framer End of Multi-Frame event. Value =1 if framing error during ILAS -* [0] | FS Lost | This bit captures the internal status of the framer Frame Symbol event. Value =1 if framing error during ILAS or user data (invalid replacement characters) -* -* @return -* - ADIERR_OK if successful. -* - ADIERR_FAILED if not successful. -* -* @note None. -* -*******************************************************************************/ -int HW_9371CheckJesdStatus(mykonosDevice_t *mykDevice, uint8_t *framerStatus, - uint8_t *obsFramerStatus, uint8_t *deframerStatus); - -/******************************************************************************/ -/** -* -* This function conducts AD9371/9375 samll RF PLL frequcny change procedure. The -* procedure is performed as follows: -* 1. Move the device into the radio off state. -* 2. Program the new local oscillator (LO) frequency. -* 3. Reset the external channel.(ignored) -* 4. Move the device back into the radio on state. -* 5. Reenable tracking calibrations.(ignored) -* -* @param mykDevice is ADI hardware layer settings pointer specific to -* a Mykonos instance which contains basic settings such as spi, -* gpio, tx/rx and jesd configurations. -* @param freq_Hz is the target frequancy in Hz. -* -* @return None. -* -* @note The procedure is used when a radio frequency (RF) phased-lock loop -* (PLL) change is required with the following conditions: -* - A desire to change the Rx, Tx, and ORx frequencies. -* - The frequency step change is less than 100 MHz. -* - The frequency step does not cross the divide by 2 boundaries outlined -* in AD9371/9375-UG-992-Rev.B-Table 96. -* -*******************************************************************************/ -int HW_9371SmallFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz); - -/******************************************************************************/ -/** -* -* This function conducts AD9371/9375 large RF PLL frequcny change procedure. The -* procedure is performed as follows: -* 1. Move the device into the radio off state. -* 2. Program the new local oscillator (LO) frequency. -* 3. Rerun the initialization calibrations. -* 4. Move the device back into the radio on state. -* 5. Reenable tracking calibrations.(ignored) -* -* @param mykDevice is ADI hardware layer settings pointer specific to -* a Mykonos instance which contains basic settings such as spi, -* gpio, tx/rx and jesd configurations. -* @param freq_Hz is the target frequancy in Hz. -* -* @return None. -* -* @note The procedure is used when a radio frequency (RF) phased-lock loop -* (PLL) change is required with the following conditions: -* - A desire to change the Rx, Tx, and ORx frequencies. -* - The frequency step change is more than 100 MHz. -* - The frequency step does cross the divide by 2 boundaries outlined -* in AD9371/9375-UG-992-Rev.B-Table 96. -* -*******************************************************************************/ -int HW_9371LargeFrequencyChange(mykonosDevice_t *mykDevice, uint64_t freq_Hz); - -/******************************************************************************/ -/** -* -* Handles AD9371 TX & RX frequency change axi gpio interruput. -* -* @param CallBackRef is the callback reference, usually the instance -* pointer of the connecting driver. -* -* @return None. -* -* @note None. -* -*******************************************************************************/ -void FreqIntrHandler(void *CallbackRef); - -/******************************************************************************/ -/** -* -* Handles AD9371 Rx gain index change axi gpio interruput. -* -* @param CallBackRef is the callback reference, usually the instance -* pointer of the connecting driver. -* -* @return None. -* -* @note None. -* -*******************************************************************************/ -void GainIntrHandler(void *CallbackRef); - -/******************************************************************************/ -/** -* -* Handles AD9371 Tx attenuation change axi gpio interruput. -* -* @param CallBackRef is the callback reference, usually the instance -* pointer of the connecting driver. -* -* @return None. -* -* @note None. -* -*******************************************************************************/ -void AttnIntrHandler(void *CallbackRef); - -#endif /* SRC_HEADLESS_H_ */ diff --git a/df_datalink_ge/src/hardware/myk_ad9528init.c b/df_datalink_ge/src/hardware/myk_ad9528init.c deleted file mode 100644 index 0cb935d..0000000 --- a/df_datalink_ge/src/hardware/myk_ad9528init.c +++ /dev/null @@ -1,189 +0,0 @@ -///* -// * myk_clock_init.c -// * -// */ -// -///** -//* \page Disclaimer Legal Disclaimer -//* Copyright 2015-2017 Analog Devices Inc. -//* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -//* -//*/ -// -//#ifndef MYK_CLOCK_INIT_C_ -//#define MYK_CLOCK_INIT_C_ -//#include -//#include -//#include -//#include "common.h" -// -//#include "ad9528.h" -//#include "t_ad9528.h" -//#include "myk_ad9528init.h" -//#include "parameters.h" -// -//static ad9528pll1Settings_t clockPll1Settings = -//{ -// .refA_Frequency_Hz = 30720000, -// .refA_Divider = 1, -// .refA_bufferCtrl = DISABLED, -// .refB_Frequency_Hz = 0, -// .refB_Divider = 1, -// .refB_bufferCtrl = DISABLED, -// .vcxo_Frequency_Hz = 122880000, -// .vcxoBufferCtrl = NEG_SINGLE_ENDED, -// .nDivider = 4, -// .bypassPll1 = 0 -//}; -// -//static ad9528pll2Settings_t clockPll2Settings = -//{ -// .rfDivider = 4, -// .n2Divider = 10, -// .totalNdiv = 30 -//}; -// -//static ad9528outputSettings_t clockOutputSettings = -//{ -// .outPowerDown = 53237, // 0xCFF5 -// .outSource = { -// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, SYSREF, -// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, -// CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, -// SYSREF, CHANNEL_DIV}, -// .outBufferCtrl = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -// .outAnalogDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -// .outDigitalDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, -// .outChannelDiv = {10,10,10,10,10,10,10,10,10,10,10,10,10,10}, -// .outFrequency_Hz = {122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000, 122880000} -//}; -// -//static ad9528sysrefSettings_t clockSysrefSettings = -//{ -// .sysrefRequestMethod = PIN, -// .sysrefSource = INTERNAL, -// .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, -// .sysrefPinBufferMode = DISABLED, -// .sysrefPatternMode = NSHOT, -// .sysrefNshotMode = ONE_PULSE, -// .sysrefDivide = 512 -//}; -// -//static spiSettings_t clockSpiSettings = -//{ -// .chipSelectIndex = AD9528_CS, //chip select Index -// .writeBitPolarity = 0, //Write bit polarity -// .longInstructionWord = 1, //16bit instruction word -// .MSBFirst = 1, //MSB first -// .CPHA = 0, //Clock phase -// .CPOL = 0, //Clock polarity -// .enSpiStreaming = 0, //uint8_t enSpiStreaming; -// .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; -// .fourWireMode = 1 //uint8_t fourWireMode; -//}; -// -//ad9528Device_t clockAD9528_ = -//{ -// &clockSpiSettings, -// &clockPll1Settings, -// &clockPll2Settings, -// &clockOutputSettings, -// &clockSysrefSettings -//}; -// -//ad9528Device_t *ad9528Init = &clockAD9528_; -// -//#endif /* MYK_CLOCK_INIT_C_ */ - - -/* AD9528 data structure initialization file */ -#include -#include -#include -#include "common.h" - -#include "./mykonos/ad9528.h" -#include "./mykonos/t_ad9528.h" -#include "myk_ad9528init.h" -#include "parameters.h" - -static ad9528pll1Settings_t clockPll1Settings = { - .refA_Frequency_Hz = 122880000, - .refA_Divider = 1, - .refA_bufferCtrl = SINGLE_ENDED, - .refB_Frequency_Hz = 0, - .refB_Divider = 1, - .refB_bufferCtrl = DISABLED, - .vcxo_Frequency_Hz = 122880000, - .vcxoBufferCtrl = DIFFERENTIAL, - .nDivider = 1, - .bypassPll1 = 0 -}; - -static ad9528pll2Settings_t clockPll2Settings = { - .rfDivider = 3, - .n2Divider = 10, - .totalNdiv = 30 -}; - -/******************************************************************* - * Output Distribution Settings - * 9369CE02A uses the following clock outputs - * OUT 1: FPGA_REF_CLK - * OUT 2: FPGA_AUX_CLK - * OUT 3: FPGA_SYSREF - * OUT 12: SYSREF_IN - * OUT 13: DEV_CLK_IN - ******************************************************************* - */ -static ad9528outputSettings_t clockOutputSettings = { - .outPowerDown = 0x0, - .outSource = { - SYSREF, SYSREF, CHANNEL_DIV, SYSREF, - CHANNEL_DIV, CHANNEL_DIV, SYSREF, SYSREF, - CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, CHANNEL_DIV, - SYSREF , CHANNEL_DIV - }, - .outBufferCtrl = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - .outAnalogDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - .outDigitalDelay = {0,0,0,0,0,0,0,0,0,0,0,0,0,0}, - .outChannelDiv = {10,10,10,10,10,10,10,10,10,10,10,10,10,10}, - .outFrequency_Hz = { - 122880000, 122880000, 122880000, 122880000, - 122880000, 122880000, 122880000, 122880000, - 122880000, 122880000, 122880000, 122880000, - 122880000, 122880000 - } -}; - -static ad9528sysrefSettings_t clockSysrefSettings = { - .sysrefRequestMethod = SPI, - .sysrefSource = INTERNAL, - .sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH, - .sysrefPinBufferMode = DISABLED, - .sysrefPatternMode = CONTINUOUS, - .sysrefNshotMode = FOUR_PULSES, - .sysrefDivide = 512 -}; - -static spiSettings_t clockSpiSettings = { - .chipSelectIndex = 2, //chip select Index - .writeBitPolarity = 0, //Write bit polarity - .longInstructionWord = 1, //16bit instruction word - .MSBFirst = 1, //MSB first - .CPHA = 0, //Clock phase - .CPOL = 0, //Clock polarity - .enSpiStreaming = 0, //uint8_t enSpiStreaming; - .autoIncAddrUp = 1, //uint8_t autoIncAddrUp; - .fourWireMode = 1 //uint8_t fourWireMode; -}; - -ad9528Device_t clockAD9528_ = { - &clockSpiSettings, - &clockPll1Settings, - &clockPll2Settings, - &clockOutputSettings, - &clockSysrefSettings -}; - -ad9528Device_t *ad9528Init = &clockAD9528_; diff --git a/df_datalink_ge/src/hardware/myk_ad9528init.h b/df_datalink_ge/src/hardware/myk_ad9528init.h deleted file mode 100644 index 53e8be6..0000000 --- a/df_datalink_ge/src/hardware/myk_ad9528init.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * myk_clock_init.h - * - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef MYK_CLOCK_INIT_H_ -#define MYK_CLOCK_INIT_H_ - -#include "./mykonos/ad9528.h" - -extern ad9528Device_t *ad9528Init; - -#endif /* MYK_CLOCK_INIT_H_ */ diff --git a/df_datalink_ge/src/hardware/myk_init.c b/df_datalink_ge/src/hardware/myk_init.c deleted file mode 100644 index d585d1a..0000000 --- a/df_datalink_ge/src/hardware/myk_init.c +++ /dev/null @@ -1,558 +0,0 @@ -/** - * \file myk_init.c - * - * \brief Contains init setting structure declarations for the _instance API - * - * The top level structure mykonosDevice_t mykDevice uses keyword - * extern to allow the application layer main() to have visibility - * to these settings. - * - * All data structures required for operation have been initialized with values which reflect - * these settings: - * - * Device Clock = $122.88$ Mhz - * Rx enabled channels = $2$ - * Tx enabled channels = $2$ - * - * Mykonos Framer: - * Lane Rate = $4915.2$ Mbs - * L = $2$ - * K = $32$ - * M = $4$ - * F = $4$ - * - * Mykonos Deframer: - * Lane Rate = $4915.2$ Mbs - * L = $2$ - * K = $32$ - * M = $4$ - * F = $4$ - * - * Mykonos Observation framer: - * Lane Rate = $4915.2$ Mbs - * L = $2$ - * K = $32$ - * M = $4$ - * F = $4$ - * - * Using these profiles: - * $Rx 100Mhz, IQrate 122.88Mhz, Dec5$ - * $Tx 100/100Mhz, IQrate 122.88Mhz, Dec5$ - * $ORX 100Mhz, IQrate 122.88Mhz, Dec5$ - * $SRx 20Mhz, IQrate 30.72Mhz, Dec5$ - * - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -#include "./mykonos/t_mykonos.h" -#include "myk_init.h" -#include "parameters.h" -#include "./mykonos/mykonos_gpio.h" - -static int16_t txFirCoefs[] = {-94,-26,282,177,-438,-368,756,732,-1170,-1337,1758,2479,-2648,-5088,4064,16760,16759,4110,-4881,-2247,2888,1917,-1440,-1296,745,828,-358,-474,164,298,-16,-94}; - -static mykonosFir_t txFir = -{ - 6, /* Filter gain in dB*/ - 32, /* Number of coefficients in the FIR filter*/ - &txFirCoefs[0] /* A pointer to an array of filter coefficients*/ -}; - -static int16_t rxFirCoefs[] = {-20,6,66,22,-128,-54,240,126,-402,-248,634,444,-956,-756,1400,1244,-2028,-2050,2978,3538,-4646,-7046,9536,30880,30880,9536,-7046,-4646,3538,2978,-2050,-2028,1244,1400,-756,-956,444,634,-248,-402,126,240,-54,-128,22,66,6,-20}; - -static mykonosFir_t rxFir = -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &rxFirCoefs[0] /* A pointer to an array of filter coefficients*/ -}; - -static int16_t obsrxFirCoefs[] = {-14,-19,44,41,-89,-95,175,178,-303,-317,499,527,-779,-843,1184,1317,-1781,-2059,2760,3350,-4962,-7433,9822,32154,32154,9822,-7433,-4962,3350,2760,-2059,-1781,1317,1184,-843,-779,527,499,-317,-303,178,175,-95,-89,41,44,-19,-14}; -static mykonosFir_t obsrxFir = -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &obsrxFirCoefs[0]/* A pointer to an array of filter coefficients*/ -}; - -static int16_t snifferFirCoefs[] = {-1,-5,-14,-23,-16,24,92,137,80,-120,-378,-471,-174,507,1174,1183,98,-1771,-3216,-2641,942,7027,13533,17738,17738,13533,7027,942,-2641,-3216,-1771,98,1183,1174,507,-174,-471,-378,-120,80,137,92,24,-16,-23,-14,-5,-1}; -static mykonosFir_t snifferRxFir= -{ - -6, /* Filter gain in dB*/ - 48, /* Number of coefficients in the FIR filter*/ - &snifferFirCoefs[0]/* A pointer to an array of filter coefficients*/ -}; - -static mykonosJesd204bFramerConfig_t rxFramer = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 4, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 0, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x03, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* serializerLaneCrossbar*/ - 22, /* serializerAmplitude - default 22 (valid (0-31)*/ - 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 0, /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ - 0 /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/ -}; - -static mykonosJesd204bFramerConfig_t obsRxFramer = -{ - 0, /* JESD204B Configuration Bank ID -extension to Device ID (Valid 0..15)*/ - 0, /* JESD204B Configuration Device ID - link identification number. (Valid 0..255)*/ - 0, /* JESD204B Configuration starting Lane ID. If more than one lane used, each lane will increment from the Lane0 ID. (Valid 0..31)*/ - 2, /* number of ADCs (0, 2, or 4) - 2 ADCs per receive chain*/ - 32, /* number of frames in a multiframe (default=32), F*K must be a multiple of 4. (F=2*M/numberOfLanes)*/ - 0, /* scrambling off if framerScramble= 0, if framerScramble>0 scramble is enabled.*/ - 1, /* 0=use internal SYSREF, 1= use external SYSREF*/ - 0x04, /* serializerLanesEnabled - bit per lane, [0] = Lane0 enabled, [1] = Lane1 enabled*/ - 0xE4, /* Lane crossbar to map framer lane outputs to physical lanes*/ - 22, /* serializerAmplitude - default 22 (valid (0-31)*/ - 4, /* preEmphasis - < default 4 (valid 0 - 7)*/ - 0, /* invertLanePolarity - default 0 ([0] will invert lane [0], bit1 will invert lane1)*/ - 0, /* lmfcOffset - LMFC_Offset offset value for deterministic latency setting*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 1, /* Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer*/ - 0, /* Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 0, /* Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples)*/ - 0 /* Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used*/ -}; - -static mykonosJesd204bDeframerConfig_t deframer = -{ - 0, /* bankId extension to Device ID (Valid 0..15)*/ - 0, /* deviceId link identification number. (Valid 0..255)*/ - 0, /* lane0Id Lane0 ID. (Valid 0..31)*/ - 4, /* M number of DACss (0, 2, or 4) - 2 DACs per transmit chain */ - 32, /* K #frames in a multiframe (default=32), F*K=multiple of 4. (F=2*M/numberOfLanes)*/ - 0, /* scramble scrambling off if scramble= 0.*/ - 1, /* External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF*/ - 0x03, /* Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ - 0xE4, /* Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ - 1, /* Equalizer setting. Applied to all deserializer lanes. Range is 0..4*/ - 0, /* PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc).*/ - 0, /* LMFC_Offset offset value to adjust deterministic latency. Range is 0..31*/ - 0, /* Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set*/ - 0, /* Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS*/ - 0 /* Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used*/ -}; - -static mykonosRxGainControl_t rxGainControl = -{ - MGC, /* Current Rx gain control mode setting*/ - 255, /* Rx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Rx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded Rx1 Gain table*/ - 195, /* Min gain index for the currently loaded Rx1 Gain table*/ - 255, /* Max gain index for the currently loaded Rx2 Gain table*/ - 195, /* Min gain index for the currently loaded Rx2 Gain table*/ - 0, /* Stores Rx1 RSSI value read back from the Mykonos*/ - 0 /* Stores Rx2 RSSI value read back from the Mykonos*/ -}; - - -static mykonosORxGainControl_t orxGainControl = -{ - MGC, /* Current ORx gain control mode setting*/ - 255, /* ORx1 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* ORx2 Gain Index, can be used in different ways for manual and AGC gain control*/ - 255, /* Max gain index for the currently loaded ORx Gain table*/ - 237 /* Min gain index for the currently loaded ORx Gain table*/ -}; - -static mykonosSnifferGainControl_t snifferGainControl = -{ - MGC, /* Current Sniffer gain control mode setting*/ - 255, /* Current Sniffer gain index. Can be used differently for MANUAL Gain control/AGC*/ - 255, /* Max gain index for the currently loaded Sniffer Gain table*/ - 203 /* Min gain index for the currently loaded Sniffer Gain table*/ -}; - -static mykonosPeakDetAgcCfg_t rxPeakAgc = -{ - 0x0C, /* apdHighThresh: */ - 0x08, /* apdLowThresh */ - 0xB5, /* hb2HighThresh */ - 0x80, /* hb2LowThresh */ - 0x40, /* hb2VeryLowThresh */ - 0x06, /* apdHighThreshExceededCnt */ - 0x04, /* apdLowThreshExceededCnt */ - 0x06, /* hb2HighThreshExceededCnt */ - 0x04, /* hb2LowThreshExceededCnt */ - 0x04, /* hb2VeryLowThreshExceededCnt */ - 0x4, /* apdHighGainStepAttack */ - 0x2, /* apdLowGainStepRecovery */ - 0x4, /* hb2HighGainStepAttack */ - 0x2, /* hb2LowGainStepRecovery */ - 0x4, /* hb2VeryLowGainStepRecovery */ - 0x1, /* apdFastAttack */ - 0x1, /* hb2FastAttack */ - 0x1, /* hb2OverloadDetectEnable */ - 0x1, /* hb2OverloadDurationCnt */ - 0x1 /* hb2OverloadThreshCnt */ -}; - -static mykonosPowerMeasAgcCfg_t rxPwrAgc = -{ - 0x01, /* pmdUpperHighThresh */ - 0x03, /* pmdUpperLowThresh */ - 0x0C, /* pmdLowerHighThresh */ - 0x00, /* pmdLowerLowThresh */ - 0x4, /* pmdUpperHighGainStepAttack */ - 0x2, /* pmdUpperLowGainStepAttack */ - 0x2, /* pmdLowerHighGainStepRecovery */ - 0x4, /* pmdLowerLowGainStepRecovery */ - 0x08, /* pmdMeasDuration */ - 0x02 /* pmdMeasConfig */ -}; - -static mykonosAgcCfg_t rxAgcConfig = -{ - 255, /* agcRx1MaxGainIndex */ - 195, /* agcRx1MinGainIndex */ - 255, /* agcRx2MaxGainIndex */ - 195, /* agcRx2MinGainIndex: */ - 255, /* agcObsRxMaxGainIndex */ - 203, /* agcObsRxMinGainIndex */ - 1, /* agcObsRxSelect */ - 1, /* agcPeakThresholdMode */ - 1, /* agcLowThsPreventGainIncrease */ - 30720, /* agcGainUpdateCounter */ - 3, /* agcSlowLoopSettlingDelay */ - 2, /* agcPeakWaitTime */ - 1, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - &rxPeakAgc, - &rxPwrAgc -}; - -static mykonosPeakDetAgcCfg_t obsRxPeakAgc = -{ - 0x1F, /* apdHighThresh: */ - 0x16, /* apdLowThresh */ - 0xB5, /* hb2HighThresh */ - 0x80, /* hb2LowThresh */ - 0x40, /* hb2VeryLowThresh */ - 0x06, /* apdHighThreshExceededCnt */ - 0x04, /* apdLowThreshExceededCnt */ - 0x06, /* hb2HighThreshExceededCnt */ - 0x04, /* hb2LowThreshExceededCnt */ - 0x04, /* hb2VeryLowThreshExceededCnt */ - 0x4, /* apdHighGainStepAttack */ - 0x2, /* apdLowGainStepRecovery */ - 0x4, /* hb2HighGainStepAttack */ - 0x2, /* hb2LowGainStepRecovery */ - 0x4, /* hb2VeryLowGainStepRecovery */ - 0x1, /* apdFastAttack */ - 0x1, /* hb2FastAttack */ - 0x1, /* hb2OverloadDetectEnable */ - 0x1, /* hb2OverloadDurationCnt */ - 0x1 /* hb2OverloadThreshCnt */ -}; - -static mykonosPowerMeasAgcCfg_t obsRxPwrAgc = -{ - 0x01, /* pmdUpperHighThresh */ - 0x03, /* pmdUpperLowThresh */ - 0x0C, /* pmdLowerHighThresh */ - 0x00, /* pmdLowerLowThresh */ - 0x4, /* pmdUpperHighGainStepAttack */ - 0x2, /* pmdUpperLowGainStepAttack */ - 0x2, /* pmdLowerHighGainStepRecovery */ - 0x4, /* pmdLowerLowGainStepRecovery */ - 0x08, /* pmdMeasDuration */ - 0x02 /* pmdMeasConfig */ -}; - -static mykonosAgcCfg_t obsRxAgcConfig = -{ - 255, /* agcRx1MaxGainIndex */ - 195, /* agcRx1MinGainIndex */ - 255, /* agcRx2MaxGainIndex */ - 195, /* agcRx2MinGainIndex: */ - 255, /* agcObsRxMaxGainIndex */ - 203, /* agcObsRxMinGainIndex */ - 1, /* agcObsRxSelect */ - 1, /* agcPeakThresholdMode */ - 1, /* agcLowThsPreventGainIncrease */ - 30720, /* agcGainUpdateCounter */ - 3, /* agcSlowLoopSettlingDelay */ - 2, /* agcPeakWaitTime */ - 1, /* agcResetOnRxEnable */ - 0, /* agcEnableSyncPulseForGainCounter */ - &obsRxPeakAgc, - &obsRxPwrAgc -}; - - -static mykonosRxProfile_t rxProfile = -{/* Rx 100MHz, IQrate 122.88MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &rxFir, /* Pointer to Rx FIR filter structure*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 1, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 122880, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 100000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - -static mykonosRxProfile_t orxProfile = -{/* ORX 100MHz, IQrate 122.88MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &obsrxFir, /* Pointer to Rx FIR filter structure or NULL*/ - 2, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 1, /* RX Half band 1 decimation (1 or 2)*/ - 122880, /* Rx IQ data rate in kHz*/ - 100000000, /* The Rx RF passband bandwidth for the profile*/ - 100000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - - -static mykonosRxProfile_t snifferProfile = -{ /* SRx 20MHz, IQrate 30.72MSPS, Dec5 */ - 1, /* The divider used to generate the ADC clock*/ - &snifferRxFir, /* Pointer to Rx FIR filter structure or NULL*/ - 4, /* Rx FIR decimation (1,2,4)*/ - 5, /* Decimation of Dec5 or Dec4 filter (5,4)*/ - 0, /* If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter (1=Enabled, 0=Disabled)*/ - 2, /* RX Half band 1 decimation (1 or 2)*/ - 30720, /* Rx IQ data rate in kHz*/ - 10000000, /* The Rx RF passband bandwidth for the profile*/ - 100000, /* Rx BBF 3dB corner in kHz*/ - NULL /* pointer to custom ADC profile*/ -}; - - - -static mykonosTxProfile_t txProfile = -{ /* Tx 20/100MHz, IQrate 122.88MSPS, Dec5 */ - DACDIV_2p5, /* The divider used to generate the DAC clock*/ - &txFir, /* Pointer to Tx FIR filter structure*/ - 2, /* The Tx digital FIR filter interpolation (1,2,4)*/ - 2, /* Tx Halfband1 filter interpolation (1,2)*/ - 1, /* Tx Halfband2 filter interpolation (1,2)*/ - 1, /* TxInputHbInterpolation (1,2)*/ - 122880, /* Tx IQ data rate in kHz*/ - 100000000, /* Primary Signal BW*/ - 100000000, /* The Tx RF passband bandwidth for the profile*/ - 710539, /* The DAC filter 3dB corner in kHz*/ - 50000, /* Tx BBF 3dB corner in kHz*/ - 0 /* Enable DPD, only valid for AD9373*/ -}; - -static mykonosDigClocks_t mykonosClocks = -{ - 122880, /* CLKPLL and device reference clock frequency in kHz*/ - 9830400, /* CLKPLL VCO frequency in kHz*/ - VCODIV_2, /* CLKPLL VCO divider*/ - 4 /* CLKPLL high speed clock divider*/ -}; - -static mykonosRxSettings_t rxSettings = -{ - &rxProfile, /* Rx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &rxFramer, /* Rx JESD204b framer configuration structure*/ - &rxGainControl, /* Rx Gain control settings structure*/ - &rxAgcConfig, /* Rx AGC control settings structure*/ - RX1_RX2, /* The desired Rx Channels to enable during initialization*/ - 0, /* Internal LO = 0, external LO*2 = 1*/ - 2550000000U, /* Rx PLL LO Frequency (internal or external LO)*/ - 0 /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ -}; - -static mykonosDpdConfig_t dpdConfig = -{ - 5, /* 1/2^(damping + 8) fraction of power `forgotten' per sample (default: `1/8192' = 5, valid 0 to 15), 0 = infinite damping*/ - 1, /* number of weights to use for int8_cpx weights weights member of this structure (default = 1)*/ - 2, /* DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2)*/ - 1, /* 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS*/ - 20, /* Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20)*/ - 0, /* Default off = 0, 1=enables automatic outlier removal during DPD modeling */ - 512, /* Number of samples to capture (default: 512, valid 64-32768)*/ - 4096, /* threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1)*/ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ - {{64,0},{0,0},{0,0}}/* DPD model error weighting (real/imag valid from -128 to 127)*/ -}; - -static mykonosClgcConfig_t clgcConfig = -{ - -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100)*/ - -2000, /* (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100)*/ - 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit*/ - 0, /* (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit*/ - 75, /* valid range 1-100, default 75*/ - 75, /* valid range 1-100, default 45*/ - 0, /* 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx1Atten automatically updated*/ - 0, /* 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx2Atten automatically updated*/ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ - 600, /* Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/ - 600, /* Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600*/ - 0, /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/ - 0 /* Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0*/ -}; - -static mykonosVswrConfig_t vswrConfig = -{ - 0, /* 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64)*/ - 255, /* Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191)*/ - 0, /* 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos)*/ - 1, /* 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos)*/ - 0, /* 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level)*/ - 0, /* 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level)*/ - 50, /* Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution*/ - 50 /* Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution*/ -}; - -static mykonosTxSettings_t txSettings = -{ - &txProfile, /* Tx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &deframer, /* Mykonos JESD204b deframer config for the Tx data path*/ - TX1_TX2, /* The desired Tx channels to enable during initialization*/ - 0, /* Internal LO=0, external LO*2 if =1*/ - 2500000000U, /* Tx PLL LO frequency (internal or external LO)*/ - TXATTEN_0P05_DB,/* Initial and current Tx1 Attenuation*/ - 10000, /* Initial and current Tx1 Attenuation mdB*/ - 10000, /* Initial and current Tx2 Attenuation mdB*/ - NULL, /* DPD,CLGC,VSWR settings. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL, /* CLGC Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ - NULL /* VSWR Config Structure. Only valid for AD9373 device, set pointer to NULL otherwise*/ -}; - - -static mykonosObsRxSettings_t obsRxSettings = -{ - &orxProfile, /* ORx datapath profile, 3dB corner frequencies, and digital filter enables*/ - &orxGainControl,/* ObsRx gain control settings structure*/ - &obsRxAgcConfig,/* ORx AGC control settings structure*/ - &snifferProfile,/* Sniffer datapath profile, 3dB corner frequencies, and digital filter enables*/ - &snifferGainControl,/* SnRx gain control settings structure*/ - &obsRxFramer, /* ObsRx JESD204b framer configuration structure */ - (MYK_ORX1_ORX2 | MYK_SNRXA_B_C),/* obsRxChannel */ - OBSLO_TX_PLL, /* (obsRxLoSource) The Obs Rx mixer can use the Tx Synth(TX_PLL) or Sniffer Synth (SNIFFER_PLL) */ - 2600000000U, /* SnRx PLL LO frequency in Hz */ - 0, /* Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data*/ - NULL, /* Custom Loopback ADC profile to set the bandwidth of the ADC response */ - OBS_RXOFF /* Default ObsRx channel to enter when radioOn called */ -}; - -static mykonosArmGpioConfig_t armGpio = -{ - 1, // useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ - 1, // useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ - 1, // txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ - 0, // orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ - - /*Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ - 0, // orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ - 0, // orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ - 0, // orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ - - /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ - 0, // rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0, // srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - 0 // txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ - /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input*/ -}; - -static mykonosGpio3v3_t gpio3v3 = -{ - 0, /*!< Oe per pin, 1=output, 0 = input */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[3:0] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[7:4] */ - GPIO3V3_BITBANG_MODE, /*!< Mode for GPIO3V3[11:8] */ -}; - -static mykonosGpioLowVoltage_t gpio = -{ - 0,/* Oe per pin, 1=output, 0 = input */ - GPIO_MONITOR_MODE,/* Mode for GPIO[3:0] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[7:4] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[11:8] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[15:12] */ - GPIO_MONITOR_MODE,/* Mode for GPIO[18:16] */ -}; - -static mykonosAuxIo_t mykonosAuxIo = -{ - 0, //auxDacEnableMask uint16_t - {0,0,0,0,0,0,0,0,0,0}, //AuxDacValue uint16[10] - {0,0,0,0,0,0,0,0,0,0}, //AuxDacSlope uint8[10] - {0,0,0,0,0,0,0,0,0,0}, //AuxDacVref uint8[10] - &gpio3v3, //pointer to gpio3v3 struct - &gpio, //pointer to gpio1v8 struct - &armGpio -}; - -static spiSettings_t mykSpiSettings = -{ - 1, /* chip select index - valid 1~8 */ - 0, /* the level of the write bit of a SPI write instruction word, value is inverted for SPI read operation */ - 1, /* 1 = 16-bit instruction word, 0 = 8-bit instruction word */ - 1, /* 1 = MSBFirst, 0 = LSBFirst */ - 0, /* clock phase, sets which clock edge the data updates (valid 0 or 1) */ - 0, /* clock polarity 0 = clock starts low, 1 = clock starts high */ - 0, /* Not implemented in ADIs platform layer. SW feature to improve SPI throughput */ - 1, /* Not implemented in ADIs platform layer. For SPI Streaming, set address increment direction. 1= next addr = addr+1, 0:addr=addr-1 */ - 1 /* 1: Use 4-wire SPI, 0: 3-wire SPI (SDIO pin is bidirectional). NOTE: ADI's FPGA platform always uses 4-wire mode */ -}; - -static mykonosTempSensorConfig_t tempSensor = -{ - 7, /* 3-bit value that controls the AuxADC decimation factor when used for temp sensor calculations; AuxADC_decimation = 256 * 2^tempDecimation*/ - 67, /* 8-bit offset that gets added to temp sensor code internally*/ - 1, /* this bit overrides the factory-calibrated fuse offset and uses the value stored in the offset member*/ - 15, /* 4-bit code with a resolution of 1°C/LSB, each time a temperature measurement is performed, the device compares the current temperature against the previous value.*/ -}; - -static mykonosTempSensorStatus_t tempStatus = -{ - 0, /* 16-bit signed temperature value (in deg C) that is read back*/ - 0, /* If the absolute value of the difference is greater than the value in temperature configuration tempWindow, the windowExceeded flag is set.*/ - 0, /* when windowExceeded member gets set, this bit is set to 1 if current value is greater than previous value, else reset*/ - 0, /* when the reading is complete and a valid temperature value stored in tempCode.*/ -}; - -mykonosDevice_t mykDevice = -{ - &mykSpiSettings, /* SPI settings data structure pointer */ - &rxSettings, /* Rx settings data structure pointer */ - &txSettings, /* Tx settings data structure pointer */ - &obsRxSettings, /* ObsRx settings data structure pointer */ - &mykonosAuxIo, /* Auxiliary IO settings data structure pointer */ - &mykonosClocks, /* Holds settings for CLKPLL and reference clock */ - 0 /* Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */ -}; diff --git a/df_datalink_ge/src/hardware/myk_init.h b/df_datalink_ge/src/hardware/myk_init.h deleted file mode 100644 index ef11bad..0000000 --- a/df_datalink_ge/src/hardware/myk_init.h +++ /dev/null @@ -1,24 +0,0 @@ -/** - * \file myk_init.h - * - * \brief Contains structure definitions for myk_init.c - * - * The top level structure mykonosDevice_t mykDevice uses keyword - * extern to allow the application layer main() to have visibility - * to these settings. - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef MYK_INIT_H_ -#define MYK_INIT_H_ - - -extern mykonosDevice_t mykDevice; - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.c b/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.c deleted file mode 100644 index 369ad92..0000000 --- a/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.c +++ /dev/null @@ -1,8518 +0,0 @@ -/** - -SOFTWARE LICENSE AGREEMENT -20180301-AD937X-CTSLA - -This Software License Agreement (the 鈥淎greement鈥�) is a legal agreement -between Analog Devices, Inc., a Massachusetts corporation, with its principal -office at One Technology Way, Norwood, Massachusetts, USA 02062 (鈥淎nalog -Devices鈥�) and you (personally or on behalf of your employer, as applicable) -(鈥淟icensee鈥�) for the software and related documentation that accompanies -this Agreement (the 鈥淟icensed Software鈥�). YOU AGREE THAT YOU ARE BOUND BY -THE TERMS AND CONDITIONS OF THIS AGREEMENT BY DOWNLOADING, INSTALLING, COPYING -OR USING THE SOFTWARE. IF YOU DO NOT AGREE, DO NOT DOWNLOAD, INSTALL, COPY OR -USE THE SOFTWARE. - -1. Development License. Subject to terms of this Agreement, Analog Devices -grants to Licensee a non-exclusive, non-transferable, non-sublicensable -license, without charge, to incorporate Licensed Software in object code form -into Licensee products solely for use within Analog Devices products that are -incorporated into such Licensee products. The licenses granted under Sections -1 and 2 of this Agreement are limited to the specific Analog Devices products -identified in Appendix A to this Agreement. - -2. Distribution License. Subject to the terms of this Agreement, Analog -Devices grants to Licensee a non-exclusive, non-transferrable, -non-sublicensable license, to copy and distribute Licensed Software in object -code form solely for use within Analog Devices products that are incorporated -into Licensee products. Distribution is limited to Licensed Software in object -code form that is incorporated into Licensee products. - -3. License to Analog Devices. During the term of this Agreement Licensee -grants to Analog Devices (and its affiliates) under any and all Licensee (and -its affiliates) patents a non-exclusive, worldwide, fully paid-up, royalty-free -license to make, use, sell, import, export, copy, distribute and otherwise -exploit Licensed Software in-whole or in-part (including updated versions of -Licensed Software), and to directly or indirectly sub-license others to do the -same. - -4. Restrictions. Licensee shall not modify, reverse engineer, decompile, -disassemble or create derivative works of Licensed Software. Licensee may only -copy the Licensed Software as expressly authorized in Sections 1 and 2 above. -In no event shall Licensee deliver or disclose the Licensed Software apart from -Licensee products to any third party without entering into a written license -agreement with Analog Devices expressly permitting such distribution. The -Licensed Software may not be used with any products other than Analog -Devices鈥� products or for any other purpose. - -Licensee shall not use or distribute the Licensed Software in any manner that -would cause Licensed Software, in whole or in part to become subject to any -terms of an Excluded License. An 鈥淓xcluded License鈥� means any license, -including licenses for 鈥渙pen source鈥� code (as defined by the Free Software -Foundation), that requires as a condition of use, modification, and/or -distribution of software subject to the Excluded License, that such software or -other software combined and/or distributed with such software be (i) disclosed -or distributed in source code form; (ii) licensed for the purpose of making -derivative works; or (iii) redistributable at no charge. The restrictions of -this section apply regardless of whether the Licensed Software is intended or -designed to run in an environment that includes software under an Excluded -License. Any license, agreement or other document issued, entered into or -granted by Licensee that purports to apply any Excluded License to any portion -of Licensed Software shall be null and void with regard to Licensed Software. -Under no circumstances will Licensee offer, provide, distribute, or license any -Licensed Software (whether in source code form or object code form) under any -form of Excluded License. - -All rights not expressly granted in this Agreement are reserved to Analog -Devices and its licensors. Analog Devices and its licensors retain all right, -title and interest in the Licensed Software and modifications thereof, -including all related patent, copyright and other intellectual property rights, -and Licensee shall not take any action inconsistent with such ownership. Any -use of the Licensed Software for any purpose other than as expressly licensed -hereunder is outside the scope of this Agreement. It is agreed that because of -the proprietary nature of the Licensed Software, Analog Devices鈥� remedies at -law for a breach by the Licensee of its obligations under this License or for -use of the Licensed Software beyond the scope of the license granted herein -will be inadequate and that Analog Devices will, in the event of such breach, -be entitled to equitable relief, including injunctive relief, without the -posting of any bond, in addition to all other remedies provided under this -License or available at law. - -If Analog Devices elects to make any update, upgrade or new version of the -Licensed Software (鈥淯pdates鈥�) available to Licensee, such Updates shall be -deemed to be Licensed Software under this Agreement. If requested by Analog -Devices, Licensee shall only use the latest version of the Licensed Software -(including Updates). Analog Devices shall have no obligation to provide -support or Updates. - -5. Publicity. Notwithstanding anything in this Agreement, Licensee may not use -any trademark or trade name of Analog Devices or make any public announcement -regarding the existence of this Agreement without Analog Devices鈥� prior -written consent. Licensee may not publish or provide the results of any -benchmark or comparison tests run on the Licensed Software to any third party -without the prior written consent of Analog Devices. - -6. Feedback. Licensee may from time to time provide suggestions, ideas, -comments or other feedback (鈥淔eedback鈥�) to Analog Devices with respect to -the Licensed Software. Licensee agrees that all Feedback is and shall be given -entirely voluntarily. To the extent Licensee provides such Feedback, however, -Licensee hereby grants to Analog Devices a non-exclusive, irrevocable, -perpetual, worldwide, royalty-free, transferable license, with the right to -sublicense, under Licensee鈥檚 intellectual property, to use and disclose -Feedback in any manner Analog Devices chooses and to display, perform, copy, -make, have made, use, sell, and otherwise dispose of Analog Devices鈥� and its -licensee鈥檚 products embodying such Feedback in any manner and via any media -Analog Devices chooses, without reference to its source or other obligation to -Analog Devices, even if the Feedback is designated as confidential. - -7. Confidentiality. Licensed Software in source code form and accompanying -documentation shall be regarded as 鈥淐onfidential Information鈥� of Analog -Devices and Licensee agrees to protect the confidentiality of Analog Devices鈥� -Confidential Information with at least the same degree of care that it utilizes -with respect to its own similar proprietary information (but in no event less -than a reasonable degree of care), including without limitation agreeing (i) -not to disclose or otherwise permit any other person or entity access to -Confidential Information or to use Confidential Information or any part thereof -in any form whatsoever, except that such disclosure or access shall be -permitted to an employee or consultant of Licensee requiring access to -Confidential Information in connection with this Agreement who has signed an -agreement obligating the employee/consultant to maintain the confidentiality of -confidential information in Licensee鈥檚 possession, (ii) to notify Analog -Devices promptly and in writing of the circumstances surrounding any suspected -possessions, use, or knowledge of Confidential Information other than those -authorized by this Agreement, and (iii) not to use Confidential Information for -any purpose other than as explicitly set forth herein. Nothing shall restrict -Licensee with respect to information or data that is independently developed or -is available to the general public otherwise than through any act or default of -Licensee. - -8. Copyright Notice. In no event shall Licensee remove any copyright or other -intellectual property notice or other legend contained on or in copies of -Licensed Software or displayed by any Licensed Software. - -9. Third Party Software. The Licensed Software may be accompanied by or -include software made available by one or more third parties (鈥淭hird Party -Software鈥�). Each portion of Third Party Software is subject to its own -separate software license terms and conditions (鈥淭hird Party Licenses鈥�). -The Third Party Licenses for Third Party Software delivered with the Licensed -Software may be set forth or identified (by URL or otherwise) in (i) Appendix A -to this license (if any), (ii) the applicable software header or footer text, -(iii) a text file located in the directory of the applicable Third Party -Software component and/or (iv) such other location customarily used for -licensing terms. The use of each portion of Third Party Software is subject to -the Third Party Licenses, and you agree that your use of any Third Party -Software is bound by the applicable Third Party License. You agree to review -and comply with all applicable Third Party Licenses prior to any use or -distribution of any Third Party Software. Third Party Software is provided on -an 鈥渁s is鈥� basis without any representation, warranty or liability of any -kind. Analog Devices (including its licensors) shall have no liability or -responsibility for the operation or performance of the Third Party Software and -shall not be liable for any damages, costs, or expenses, direct or indirect, -arising out of the performance or failure to perform of the Third Party -Software. Analog Devices (including its licensors) shall be entitled to the -benefit of any and all limitations of liability and disclaimers of warranties -contained in the Third Party Licenses. - -In the event that Third Party Software has only been provided to you in object -code form under this Agreement, and the Third Party License requires -distribution of the corresponding source code, you may contact -software.licensing@analog.com regarding receiving a copy of such source code. - -10. Licensee Requirements. Licensee acknowledges that use or distribution of -the Licensed Software may require Licensee to obtain licenses to intellectual -property or other consents from one or more third parties. Licensee is -responsible for obtaining any and all such required licenses, or permissions -regarding the Licensed Software and for the performance of any and all required -tests or analysis necessary or appropriate for the determination of the -suitability of the Licensed Software for its or its customers鈥� purposes. -Licensee shall defend, indemnify and hold Analog Devices, its licensors, and -their respective officers, directors, employees and agents (each an -鈥淚ndemnified Party鈥�) harmless from and against any damages, fines, -penalties, assessments, liabilities, costs and expenses (including reasonable -attorneys鈥� fees and court costs) in the event that any claim is brought -against an Indemnified Party (i) arising or alleged to arise from Licensee鈥檚 -use or distribution of Licensed Software or Third Party Software, or (ii) on -account of Licensee鈥檚 failure to obtain any required license or consent to -use or distribute Licensed Software or Third Party Software. Licensee shall -bear any and all expenses and pay any and all taxes that may be payable in -relation to this Agreement. - -11. Audit. Analog Devices shall have the right upon ten (10) days prior -written notice to audit Licensee鈥檚 compliance with the terms of this -Agreement during normal business hours. In connection with such audit Analog -Devices shall have access to all reasonably requested documents, equipment, -information and personnel. Licensee shall maintain complete and accurate -records of its use of the Licensed Software for a period of at least three -years from the applicable use of the Licensed Software. - -12. License Term; Term of Agreement. This Agreement is effective upon receipt -of the Licensed Software and shall continue for three (3) years, unless earlier -terminated as permitted in this Agreement. This Agreement will automatically -renew for additional one (1) year terms unless indicated otherwise in writing -by either of the parties thirty (30) days prior to any renewal date. Licensee -may terminate this Agreement at any time by giving written notice to Analog -Devices. Analog Devices may terminate this Agreement at any time in the event -of any failure by Licensee to comply with any term or condition of the -Agreement. In the event of termination, Licensee must permanently delete all -copies of Licensed Software and all of its component parts, including any -backup or archival copies. Licenses granted to end users prior to termination -shall survive. The provisions of Sections 3-22 shall survive any termination -or expiration of this Agreement according to their terms. - -13. DISCLAIMER AND LIMITATION OF WARRANTIES. LICENSED SOFTWARE AND THIRD PARTY -SOFTWARE ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, AND ANALOG DEVICES, -FOR ITSELF AND ITS LICENSORS, HEREBY DISCLAIMS ALL WARRANTIES, WHETHER EXPRESS -OR IMPLIED, ORAL OR WRITTEN, WITH RESPECT TO THE LICENSED SOFTWARE AND THIRD -PARTY SOFTWARE, INCLUDING, BUT NOT LIMITED TO, ANY EXPRESS AND IMPLIED -WARRANTIES OF MERCHANTABILITY; FITNESS FOR PARTICULAR PURPOSE AND SYSTEM -INTEGRATION; CONDITIONS OF QUALITY AND ACCURACY OF INFORMATIONAL CONTENT; -NON-INFRINGEMENT; QUIET ENJOYMENT; AND TITLE. LICENSEE AGREES THAT ANY EFFORTS -BY ANALOG DEVICES TO MODIFY OR UPDATE LICENSED SOFTWARE OR THIRD PARTY SOFTWARE -SHALL NOT BE DEEMED A WAIVER OF THESE LIMITATIONS, AND THAT ANY ANALOG DEVICES -WARRANTIES SHALL NOT BE DEEMED TO HAVE FAILED OF THEIR ESSENTIAL PURPOSE. - -14. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY LAW ANALOG -DEVICES (INCLUDING ITS LICENSORS) SHALL NOT BE LIABLE FOR ANY DAMAGES ARISING -FROM OR RELATED TO THE LICENSED SOFTWARE, THIRD PARTY SOFTWARE, THEIR USE OR -ANY RELATED INFORMATION AND/OR SERVICES, INCLUDING BUT NOT LIMITED TO ANY -INDIRECT, INCIDENTAL, SPECIAL, PUNITIVE, EXEMPLARY, CONSEQUENTIAL OR ANALOGOUS -DAMAGES (INCLUDING WITHOUT LIMITATION ANY DAMAGES RESULTING FROM LOSS OF USE, -DATA, REVENUE, PROFITS, OR SAVINGS, COMPUTER DAMAGE OR ANY OTHER CAUSE), UNDER -ANY LEGAL THEORY (INCLUDING WITHOUT LIMITATION CONTRACT, WARRANTY, TORT, -NEGLIGENCE, STRICT OR PRODUCT LIABILITY), EVEN IF IT HAS BEEN INFORMED OF THE -POSSIBILITY OF SUCH DAMAGES. - -IN NO EVENT SHALL ANALOG DEVICES鈥� OR ITS LICENSORS鈥� CUMULATIVE LIABILITY -FOR DAMAGES TO LICENSEE FOR ANY AND ALL CAUSES WHATSOEVER, REGARDLESS OF THE -FORM OF ANY CLAIMS OR ACTIONS, EXCEED THE GREATER OF (1) ONE HUNDRED U.S. -DOLLARS ($100.00 U.S.) OR (2) THE AMOUNT PAID TO ANALOG DEVICES HEREUNDER FOR -THE LICENSED SOFTWARE. - -Some jurisdictions do not permit the exclusion or limitation of liability for -consequential or incidental damages, and, as such, some portion of the above -limitation may not apply to Licensee. In such jurisdictions, Analog Devices' -liability is limited to the greatest extent permitted by law. - -15. HIGH RISK APPLICATIONS. THE LICENSED SOFTWARE IS NOT DESIGNED OR INTENDED -FOR USE IN HAZARDOUS ENVIRONMENTS REQUIRING FAIL-SAFE PERFORMANCE, INCLUDING, -WITHOUT LIMITATION, IN THE OPERATION OF NUCLEAR FACILITIES, AIRCRAFT NAVIGATION -OR CONTROL SYSTEMS, AIR TRAFFIC CONTROL, LIFE SUPPORT MACHINES, WEAPONS -SYSTEMS, OR ANY OTHER APPLICATION IN WHICH THE FAILURE OF THE LICENSED SOFTWARE -COULD LEAD TO DEATH, PERSONAL INJURY OR SEVERE PHYSICAL OR ENVIRONMENTAL -DAMAGES (鈥淗IGH RISK ACTIVITIES鈥�). LICENSED SOFTWARE IS NOT DESIGNED, -AUTHORIZED, OR WARRANTED TO BE SUITABLE FOR USE IN CONNECTION WITH HIGH RISK -ACTIVITIES. USE OF LICENSED SOFTWARE IN CONNECTION WITH HIGH RISK ACTIVITIES -IS UNDERSTOOD TO BE FULLY AT LICENSEE鈥橲 RISK. - -16. Choice of Law. This Agreement and any dispute related to the Licensed -Software shall be governed by the laws of the Commonwealth of Massachusetts, -United States of America, without reference to its principles of conflicts of -laws, and, as to matters affecting copyrights, trademarks and patents, in -addition, by applicable United States federal law. The parties agree that the -jurisdiction and venue of any action with respect to this Agreement shall be in -a court of competent subject matter jurisdiction located in the Commonwealth of -Massachusetts, and each of the parties hereby agrees to submit itself to the -exclusive jurisdiction and venue of such courts for the purpose of any such -action, except that Analog Devices may seek injunctive relief in any venue of -its choosing. Licensee hereby submits to personal jurisdiction in such courts. -The parties hereto specifically exclude the United Nations Convention on -Contracts for the International Sale of Goods and the Uniform Computer -Information Transactions Act from this Agreement and any transaction between -them that may be implemented in connection with this Agreement. The original of -this Agreement has been written in English. The parties hereto waive any -statute, law, or regulation that might provide an alternative law or forum or -to have this Agreement written in any language other than English. - -17. U.S. Government Restricted Rights. Licensed Software is provided with -RESTRICTED RIGHTS. Use, duplication, or disclosure by the Government is -subject to restrictions as set forth in subparagraphs (a) through (d) of the -Commercial Computer Software - Restricted Rights clause at FAR 52.227-19, -(c)(1)(ii) of The Rights in Technical Data and Computer Software clause at -DFARS 252.227-7013, and in similar clauses in the NASA FAR Supplement, as -applicable. The contractor/manufacturer of this Licensed Software is Analog -Devices, Inc., One Technology Way, Norwood, Massachusetts 02062 USA, or its -authorized licensors. - -18. Export. Licensee shall not export, directly or indirectly, Licensed -Software, or other information or materials provided by Analog Devices or its -suppliers hereunder, to any country for which the United States or any other -relevant jurisdiction requires any export license or other governmental -approval at the time of export without first obtaining such license or -approval. Licensee shall defend indemnify and hold harmless Analog Devices -from and against any damages, fines, penalties, assessments, liabilities, costs -and expenses (including reasonable attorneys鈥� fees and court costs) arising -out of any failure by Licensee to comply with this Section. - -19. Compliance with Laws of Other Jurisdictions. Licensee shall comply with -all laws, legislation, rules, regulations, governmental requirements and -industry standards with respect to Licensed Software, and the performance by -Licensee of its obligations hereunder, existing in any applicable jurisdiction. - -20. Assignment. This Agreement is personal to Licensee and Licensee may not -transfer, sublicense, lease, rent, or assign its rights under this License, and -any such attempt shall be null and void. Analog Devices may assign, transfer, -or sublicense this Agreement or any rights or obligations hereunder at any time -in its sole discretion. - -21. Waiver; Modification; Severability. No waiver, consent, modification or -change of terms of this Agreement shall bind either party unless in writing -signed by both parties, and then such waiver, consent, modification or change -shall be effective only in the specific instance and for the specific purpose -given. If any provision of this Agreement is unenforceable, such provision -shall be enforced to the extent possible under applicable law, and the -remaining provisions will remain in effect. - -22. Entire Agreement. This Agreement supersedes any and all other agreements, -either oral or in writing, between the parties with respect to the matters -stated herein. If, for any reason, any provision of this Agreement is held -invalid, such invalidity shall not affect the remainder of this Agreement, and -this Agreement shall continue in force and effect to the full extent allowed by -law. For the avoidance of doubt, all Licensed Software under this Agreement is -subject to the terms and conditions of this Agreement and not any agreement or -terms for purchase of Analog Devices products, even if the Licensed Software is -delivered with such products. - - -Appendix A - -License limited to Analog Devices transceiver / receiver / transmitter products. - -*/ -#include "Mykonos_M3.h" -// Version 5.2.2 - -unsigned char firmware_Mykonos_M3_bin[] = { - 0x90, 0xbc, 0x00, 0x20, 0x35, 0x6b, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, - 0xf1, 0x66, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, 0xf1, 0x66, 0x01, 0x01, - 0xf1, 0x66, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x6a, 0x01, 0x01, - 0xf7, 0x6a, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x97, 0x7a, 0x00, 0x01, - 0x2d, 0x7a, 0x00, 0x01, 0xf9, 0x6a, 0x01, 0x01, 0xd7, 0x8b, 0x00, 0x01, - 0xe7, 0xeb, 0x00, 0x01, 0x71, 0x52, 0x00, 0x01, 0xfb, 0x6a, 0x01, 0x01, - 0x8d, 0x69, 0x00, 0x01, 0x9d, 0x69, 0x00, 0x01, 0xad, 0x69, 0x00, 0x01, - 0xd9, 0x69, 0x00, 0x01, 0x3f, 0xfd, 0x00, 0x01, 0x07, 0x8d, 0x00, 0x01, - 0x43, 0x8e, 0x00, 0x01, 0xc3, 0x8d, 0x00, 0x01, 0xeb, 0x8e, 0x00, 0x01, - 0xff, 0x32, 0x00, 0x01, 0x31, 0xf1, 0x00, 0x01, 0xd3, 0x8c, 0x00, 0x01, - 0x7b, 0xf2, 0x00, 0x01, 0xfd, 0x6a, 0x01, 0x01, 0x6b, 0x5f, 0x00, 0x01, - 0xff, 0x6a, 0x01, 0x01, 0x01, 0x6b, 0x01, 0x01, 0x03, 0x6b, 0x01, 0x01, - 0x05, 0x6b, 0x01, 0x01, 0x07, 0x6b, 0x01, 0x01, 0x51, 0xf4, 0x00, 0x01, - 0x09, 0x6b, 0x01, 0x01, 0x0b, 0x6b, 0x01, 0x01, 0x93, 0xfd, 0x00, 0x01, - 0x53, 0x8d, 0x00, 0x01, 0x7f, 0x8e, 0x00, 0x01, 0x65, 0x8f, 0x00, 0x01, - 0xbd, 0x9d, 0x00, 0x01, 0x11, 0xf3, 0x00, 0x01, 0x2d, 0xf2, 0x00, 0x01, - 0x5f, 0xf2, 0x00, 0x01, 0x0d, 0x6b, 0x01, 0x01, 0x0f, 0x6b, 0x01, 0x01, - 0x11, 0x6b, 0x01, 0x01, 0x13, 0x6b, 0x01, 0x01, 0x15, 0x6b, 0x01, 0x01, - 0x17, 0x6b, 0x01, 0x01, 0x19, 0x6b, 0x01, 0x01, 0x1b, 0x6b, 0x01, 0x01, - 0x1d, 0x6b, 0x01, 0x01, 0x1f, 0x6b, 0x01, 0x01, 0x21, 0x6b, 0x01, 0x01, - 0xf7, 0x82, 0x00, 0x01, 0x23, 0x6b, 0x01, 0x01, 0xdb, 0x82, 0x00, 0x01, - 0x25, 0x6b, 0x01, 0x01, 0x27, 0x6b, 0x01, 0x01, 0x29, 0x6b, 0x01, 0x01, - 0x2b, 0x6b, 0x01, 0x01, 0x2d, 0x6b, 0x01, 0x01, 0x2f, 0x6b, 0x01, 0x01, - 0x31, 0x6b, 0x01, 0x01, 0x33, 0x6b, 0x01, 0x01, 0x1a, 0xc4, 0x00, 0x00, - 0x10, 0x00, 0x00, 0x00, 0x1f, 0x15, 0x00, 0x00, 0x74, 0x72, 0x75, 0x6e, - 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf0, 0xb7, 0x00, 0x20, 0xb8, 0x82, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, - 0x10, 0xf1, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0xa4, 0x2b, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x8c, 0x09, 0x00, 0x20, 0xf0, 0xb2, 0x00, 0x20, 0x98, 0xb4, 0x00, 0x20, - 0x00, 0x00, 0x70, 0x47, 0x4c, 0xbd, 0x00, 0x20, 0x38, 0xb2, 0x00, 0x20, - 0xe0, 0xb3, 0x00, 0x20, 0xb8, 0x00, 0xff, 0xff, 0xef, 0xf3, 0x11, 0x80, - 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x38, 0xb5, 0x14, 0x46, - 0x00, 0x22, 0x82, 0x70, 0x00, 0xf1, 0x4c, 0x05, 0xdf, 0xf8, 0x14, 0x29, - 0x82, 0x61, 0x00, 0x22, 0xc2, 0x61, 0x02, 0x62, 0x02, 0x80, 0x82, 0x81, - 0x01, 0x22, 0xc2, 0x81, 0x02, 0x82, 0x42, 0x82, 0x00, 0x22, 0xa0, 0xf8, - 0x18, 0x22, 0x40, 0x22, 0xea, 0x83, 0x2a, 0x84, 0x00, 0x22, 0x6a, 0x85, - 0x2a, 0x80, 0xaa, 0x61, 0x41, 0xb1, 0x4f, 0xf0, 0x00, 0x41, 0x41, 0x61, - 0x4f, 0xf0, 0xff, 0x31, 0x01, 0x81, 0x41, 0x81, 0x81, 0x80, 0xc1, 0x80, - 0x01, 0xf0, 0x82, 0xf8, 0xdf, 0xf8, 0xd4, 0x08, 0x34, 0xb9, 0x41, 0x78, - 0x02, 0x78, 0x42, 0xea, 0x01, 0x21, 0xc2, 0x78, 0x80, 0x78, 0x05, 0xe0, - 0x41, 0x79, 0x02, 0x79, 0x42, 0xea, 0x01, 0x21, 0xc2, 0x79, 0x80, 0x79, - 0x09, 0xb2, 0x40, 0xea, 0x02, 0x20, 0xb1, 0xf5, 0x00, 0x5f, 0xa8, 0xbf, - 0xa1, 0xf5, 0x80, 0x41, 0x00, 0xb2, 0xb0, 0xf5, 0x00, 0x5f, 0xa8, 0xbf, - 0xa0, 0xf5, 0x80, 0x40, 0x69, 0x84, 0xa8, 0x84, 0x01, 0xf0, 0x96, 0xfd, - 0xdf, 0xf8, 0x94, 0x08, 0x34, 0x21, 0x01, 0xfb, 0x04, 0x04, 0x20, 0x46, - 0x02, 0xf0, 0xb0, 0xfe, 0x64, 0x20, 0x60, 0x60, 0xbd, 0xe8, 0x31, 0x40, - 0x01, 0xf0, 0x9d, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0e, 0x46, - 0x15, 0x46, 0xff, 0xf7, 0x9b, 0xff, 0x00, 0x27, 0x80, 0x46, 0xe1, 0x5f, - 0x70, 0x1e, 0x81, 0x42, 0xbc, 0xbf, 0x72, 0x42, 0x8a, 0x42, 0x05, 0xda, - 0xb4, 0xf9, 0x02, 0x10, 0x81, 0x42, 0xb8, 0xbf, 0x8a, 0x42, 0x02, 0xdb, - 0x27, 0x80, 0x67, 0x80, 0x01, 0x27, 0xb4, 0xf9, 0x00, 0x00, 0x00, 0x12, - 0x00, 0xf0, 0x3f, 0x01, 0xa5, 0xb9, 0x40, 0xf6, 0x15, 0x20, 0x02, 0xf0, - 0xc5, 0xfe, 0x20, 0x88, 0xc1, 0xb2, 0x40, 0xf6, 0x14, 0x20, 0x02, 0xf0, - 0xbf, 0xfe, 0x00, 0xf0, 0x2b, 0xf8, 0x40, 0xf6, 0x17, 0x20, 0x02, 0xf0, - 0xb9, 0xfe, 0x60, 0x88, 0xc1, 0xb2, 0x40, 0xf6, 0x16, 0x20, 0x13, 0xe0, - 0x40, 0xf6, 0x19, 0x20, 0x02, 0xf0, 0xb0, 0xfe, 0x20, 0x88, 0xc1, 0xb2, - 0x40, 0xf6, 0x18, 0x20, 0x02, 0xf0, 0xaa, 0xfe, 0x00, 0xf0, 0x16, 0xf8, - 0x40, 0xf6, 0x1b, 0x20, 0x02, 0xf0, 0xa4, 0xfe, 0x60, 0x88, 0xc1, 0xb2, - 0x40, 0xf6, 0x1a, 0x20, 0x02, 0xf0, 0x9e, 0xfe, 0x01, 0x20, 0xa8, 0x40, - 0xc1, 0xb2, 0x40, 0xf6, 0x1c, 0x20, 0x02, 0xf0, 0x97, 0xfe, 0x88, 0xf3, - 0x11, 0x88, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xb4, 0xf9, 0x02, 0x00, - 0x00, 0x12, 0x00, 0xf0, 0x3f, 0x01, 0x70, 0x47, 0x2d, 0xe9, 0xf8, 0x4f, - 0x80, 0x46, 0xdf, 0xf8, 0x0c, 0x0e, 0x4f, 0xf4, 0x08, 0x71, 0x01, 0xfb, - 0x08, 0x0a, 0xff, 0xf7, 0x3b, 0xff, 0x83, 0x46, 0x40, 0x46, 0x0a, 0xf1, - 0x6a, 0x05, 0x02, 0xf0, 0xe3, 0xff, 0x2a, 0x88, 0xdf, 0xf8, 0xf0, 0x1d, - 0x40, 0x56, 0x56, 0x56, 0x00, 0x24, 0x81, 0x1b, 0x04, 0xd4, 0xb1, 0x46, - 0x06, 0x46, 0x04, 0xd0, 0x01, 0x21, 0x02, 0xe0, 0x81, 0x46, 0x4f, 0xf0, - 0xff, 0x31, 0x40, 0x2a, 0x1f, 0xd0, 0x01, 0x24, 0x00, 0x29, 0x4c, 0xbf, - 0x1f, 0xfa, 0x89, 0xf7, 0xb7, 0xb2, 0xda, 0xe9, 0x82, 0x01, 0x3a, 0x46, - 0x03, 0xf0, 0x64, 0xf8, 0xc0, 0x07, 0x18, 0xd5, 0x0a, 0xeb, 0xc7, 0x00, - 0xb1, 0x45, 0xc1, 0x6f, 0x04, 0xd0, 0x80, 0x6f, 0x40, 0x11, 0xa8, 0x80, - 0x48, 0x11, 0xe8, 0x80, 0x42, 0x46, 0xdf, 0xf8, 0xd8, 0x0d, 0xb0, 0xf9, - 0x24, 0x10, 0x0a, 0xf1, 0x6e, 0x00, 0xff, 0xf7, 0x61, 0xff, 0xac, 0x81, - 0x8b, 0xf3, 0x11, 0x88, 0x00, 0x20, 0xbd, 0xe8, 0xf2, 0x8f, 0x00, 0x24, - 0xf7, 0xe7, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x26, 0x68, 0x60, 0x68, - 0xb6, 0xf9, 0x34, 0xc0, 0x03, 0xeb, 0x02, 0x17, 0x81, 0x1c, 0x67, 0x44, - 0x3f, 0x11, 0xcf, 0x80, 0xb7, 0x8e, 0x4a, 0x80, 0xff, 0x18, 0xb1, 0xf9, - 0x0a, 0x20, 0x8b, 0x80, 0x07, 0xf0, 0x0f, 0x07, 0x0f, 0x81, 0x00, 0x2a, - 0x14, 0xbf, 0x02, 0x22, 0x01, 0x22, 0xb1, 0xf9, 0x0c, 0x70, 0x13, 0x46, - 0x1f, 0xb1, 0x37, 0x69, 0xe7, 0x61, 0x01, 0x27, 0x08, 0xe0, 0x02, 0x2b, - 0x03, 0xd1, 0x77, 0x69, 0xe7, 0x61, 0x37, 0x8c, 0x02, 0xe0, 0xb7, 0x69, - 0xe7, 0x61, 0x77, 0x8c, 0x27, 0x84, 0xb1, 0xf9, 0x0e, 0x70, 0x00, 0x2f, - 0x01, 0xbf, 0xb1, 0xf9, 0x10, 0x70, 0x00, 0x2f, 0x0f, 0x78, 0xba, 0x42, - 0x24, 0xd0, 0x00, 0xf1, 0x18, 0x07, 0xdf, 0xf8, 0xb4, 0xc6, 0xc7, 0xf8, - 0x00, 0xc0, 0x4f, 0xf0, 0x00, 0x0c, 0xc7, 0xf8, 0x04, 0xc0, 0xc7, 0xf8, - 0x08, 0xc0, 0xb4, 0xf8, 0x12, 0xc0, 0xa4, 0xf8, 0x16, 0xc0, 0x4f, 0xf0, - 0x00, 0x0c, 0xa0, 0xf8, 0x00, 0xc0, 0xa1, 0xf8, 0x0e, 0xc0, 0x0a, 0x70, - 0xc7, 0xf8, 0x4c, 0xc0, 0x32, 0x69, 0xe2, 0x61, 0x01, 0x22, 0x22, 0x84, - 0xb1, 0xf9, 0x0c, 0x20, 0x00, 0x2a, 0x1a, 0xbf, 0x01, 0x2b, 0x08, 0x22, - 0x20, 0x22, 0xba, 0x86, 0xb1, 0xf9, 0x10, 0x10, 0x21, 0xb1, 0x00, 0xf0, - 0x4b, 0xff, 0x61, 0x68, 0x00, 0x20, 0x48, 0x82, 0x25, 0x81, 0xf1, 0xbd, - 0x2d, 0xe9, 0xf9, 0x4f, 0x97, 0xb0, 0x00, 0x20, 0x0c, 0x46, 0x01, 0x90, - 0xe0, 0x8a, 0x17, 0x99, 0x40, 0x08, 0x02, 0x90, 0x01, 0x20, 0x88, 0x40, - 0x11, 0x90, 0x00, 0x21, 0x00, 0x20, 0x03, 0xf0, 0x20, 0xf8, 0x11, 0x98, - 0x02, 0xf0, 0x32, 0xfe, 0x00, 0x25, 0x30, 0xb9, 0x04, 0xf0, 0x99, 0xf8, - 0x18, 0xb9, 0x03, 0xf0, 0x73, 0xf8, 0x02, 0x20, 0x0c, 0xe3, 0x00, 0xf0, - 0x26, 0xfb, 0x02, 0xf0, 0xec, 0xfd, 0xdf, 0xf8, 0x34, 0x0e, 0x00, 0x68, - 0x60, 0x62, 0x04, 0xf1, 0x28, 0x00, 0x04, 0xf0, 0xb6, 0xfe, 0x00, 0xf0, - 0x81, 0xff, 0x00, 0x28, 0x04, 0xf1, 0x2c, 0x00, 0x02, 0xd0, 0x04, 0xf0, - 0xe6, 0xff, 0x01, 0xe0, 0x05, 0xf0, 0x55, 0xfa, 0x17, 0x99, 0x20, 0x46, - 0x00, 0xf0, 0x16, 0xff, 0x06, 0x46, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x10, - 0x00, 0x29, 0x17, 0x99, 0x14, 0xbf, 0xb0, 0xf9, 0x08, 0x00, 0xb0, 0xf9, - 0x04, 0x00, 0x00, 0x29, 0x14, 0xbf, 0xdf, 0xf8, 0xf0, 0x1d, 0xdf, 0xf8, - 0xf0, 0x1d, 0x09, 0x68, 0xc9, 0x07, 0x05, 0xd5, 0x01, 0x21, 0xc0, 0x1d, - 0x80, 0x28, 0x02, 0xd3, 0x7f, 0x20, 0x00, 0xe0, 0x00, 0x21, 0x17, 0x9a, - 0xdf, 0xf8, 0xd8, 0x3d, 0x00, 0x04, 0x00, 0xf4, 0xfe, 0x00, 0x40, 0xea, - 0x82, 0x70, 0x40, 0xea, 0xc1, 0x32, 0x1a, 0x43, 0x16, 0x92, 0x00, 0x27, - 0x22, 0x8b, 0xd2, 0x05, 0x02, 0xf0, 0x7e, 0x52, 0x10, 0x43, 0x40, 0xea, - 0xc1, 0x30, 0xdf, 0xf8, 0xb8, 0x1d, 0x08, 0x43, 0x10, 0x90, 0x10, 0x98, - 0x05, 0xf0, 0x3b, 0xfb, 0x20, 0x68, 0xc0, 0x8e, 0x41, 0x42, 0x09, 0xb2, - 0x00, 0xb2, 0x05, 0xf0, 0xa3, 0xfd, 0x60, 0x68, 0xb0, 0xf9, 0x0e, 0x10, - 0x39, 0xb1, 0xdf, 0xf8, 0x84, 0x2d, 0x4f, 0xf4, 0x88, 0x71, 0xd1, 0x61, - 0x11, 0x62, 0x4f, 0xf4, 0x84, 0x77, 0x61, 0x6a, 0xdf, 0xf8, 0x70, 0x2d, - 0x39, 0x43, 0x41, 0xf0, 0x02, 0x01, 0x11, 0x60, 0xd0, 0xf8, 0x6e, 0x00, - 0x03, 0x90, 0x17, 0x98, 0x06, 0xf0, 0x60, 0xf8, 0x04, 0xe0, 0x1f, 0xfa, - 0x89, 0xf8, 0x01, 0x98, 0x40, 0x1c, 0x01, 0x90, 0x02, 0x98, 0x01, 0x99, - 0x88, 0x42, 0xc0, 0xf2, 0x66, 0x82, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2e, - 0x40, 0xf0, 0x61, 0x82, 0x08, 0x46, 0x02, 0x99, 0x88, 0x42, 0x08, 0xbf, - 0x4f, 0xf0, 0x01, 0x0a, 0x1c, 0xd0, 0x00, 0xf0, 0x05, 0xff, 0x4f, 0xf0, - 0x00, 0x0a, 0x20, 0xb9, 0x17, 0x98, 0x01, 0x21, 0xc0, 0xb2, 0x05, 0xf0, - 0xfa, 0xf9, 0x20, 0x68, 0x80, 0x8f, 0x06, 0xf0, 0x6d, 0xf9, 0x05, 0xf0, - 0x9c, 0xfa, 0x01, 0x98, 0x17, 0x9a, 0x64, 0x21, 0x48, 0x43, 0x02, 0x99, - 0x90, 0xfb, 0xf1, 0xf0, 0xdf, 0xf8, 0xe8, 0x14, 0x34, 0x23, 0x03, 0xfb, - 0x02, 0x11, 0x48, 0x60, 0x01, 0x98, 0x01, 0x28, 0x2d, 0xdb, 0xdd, 0xe9, - 0x08, 0x01, 0x06, 0xf0, 0xf7, 0xf9, 0x0f, 0x90, 0xdd, 0xe9, 0x06, 0x01, - 0x06, 0xf0, 0xf2, 0xf9, 0xb8, 0xf1, 0x00, 0x0f, 0x0e, 0x90, 0x20, 0xd1, - 0x60, 0x68, 0xdd, 0xe9, 0x14, 0x23, 0xd0, 0xe9, 0x0a, 0x71, 0xba, 0x18, - 0x4b, 0x41, 0xc0, 0xe9, 0x0a, 0x23, 0xd0, 0xe9, 0x0c, 0x71, 0xdd, 0xe9, - 0x12, 0x23, 0xba, 0x18, 0x4b, 0x41, 0xc0, 0xe9, 0x0c, 0x23, 0xd0, 0xe9, - 0x0e, 0x71, 0xdd, 0xe9, 0x08, 0x23, 0xba, 0x18, 0x4b, 0x41, 0xc0, 0xe9, - 0x0e, 0x23, 0xd0, 0xe9, 0x10, 0x71, 0xdd, 0xe9, 0x06, 0x23, 0xba, 0x18, - 0x4b, 0x41, 0xc0, 0xe9, 0x10, 0x23, 0x17, 0x98, 0x02, 0xf0, 0x4e, 0xfe, - 0xdf, 0xf8, 0xc8, 0x2a, 0xdf, 0xf8, 0x48, 0x1d, 0x80, 0x56, 0x31, 0xf8, - 0x10, 0x00, 0x06, 0xf0, 0xfd, 0xf9, 0xdf, 0xf8, 0x40, 0x1d, 0x06, 0xf0, - 0x09, 0xfa, 0x00, 0xf0, 0x6d, 0xfd, 0xba, 0xf1, 0x00, 0x0f, 0x0d, 0x90, - 0x39, 0xd1, 0x05, 0xf0, 0x62, 0xfa, 0x02, 0x28, 0x0c, 0xbf, 0x06, 0x26, - 0x01, 0x28, 0x00, 0xd1, 0x01, 0x25, 0xdf, 0xf8, 0x20, 0x2d, 0xd2, 0xe9, - 0x00, 0x01, 0xcd, 0xe9, 0x14, 0x01, 0xd2, 0xe9, 0x02, 0x01, 0xcd, 0xe9, - 0x12, 0x01, 0xd2, 0xe9, 0x04, 0x01, 0xcd, 0xe9, 0x08, 0x01, 0xd2, 0xe9, - 0x06, 0x01, 0xcd, 0xe9, 0x06, 0x01, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x00, - 0xb0, 0xb9, 0x17, 0x98, 0x00, 0x21, 0xc0, 0xb2, 0x05, 0xf0, 0x7d, 0xf9, - 0xdd, 0xe9, 0x08, 0x01, 0x40, 0x42, 0x61, 0xeb, 0x41, 0x01, 0xcd, 0xe9, - 0x08, 0x01, 0xdd, 0xe9, 0x06, 0x01, 0x40, 0x42, 0x61, 0xeb, 0x41, 0x01, - 0xcd, 0xe9, 0x06, 0x01, 0x20, 0x68, 0x80, 0x8f, 0x06, 0xf0, 0xe2, 0xf8, - 0x00, 0x2d, 0x04, 0xbf, 0x00, 0x2e, 0x05, 0xf0, 0x0e, 0xfa, 0x01, 0x98, - 0x02, 0x28, 0xc0, 0xf2, 0xcc, 0x80, 0x0f, 0x98, 0x00, 0x99, 0x06, 0xf0, - 0x3f, 0xfa, 0x0c, 0x90, 0x59, 0x46, 0x0e, 0x98, 0x06, 0xf0, 0x3a, 0xfa, - 0x0b, 0x90, 0xbd, 0xf9, 0x14, 0x10, 0xbd, 0xf9, 0x10, 0x00, 0x40, 0x1a, - 0x06, 0xf0, 0x9a, 0xf9, 0x07, 0x46, 0xbd, 0xf9, 0x12, 0x00, 0xbd, 0xf9, - 0x16, 0x10, 0x40, 0x1a, 0x06, 0xf0, 0x92, 0xf9, 0x00, 0xf0, 0x1c, 0xfd, - 0x83, 0x46, 0x48, 0x46, 0x00, 0xf0, 0xfc, 0xfc, 0x59, 0x46, 0x06, 0xf0, - 0x95, 0xfa, 0x06, 0xf0, 0xd5, 0xfa, 0x00, 0x21, 0x06, 0xf0, 0x0c, 0xfb, - 0x83, 0x46, 0x1d, 0xd0, 0x20, 0x68, 0x30, 0xf8, 0x42, 0x1f, 0x81, 0xb1, - 0x61, 0x68, 0x4c, 0x31, 0x00, 0x91, 0x40, 0x88, 0x06, 0xf0, 0x82, 0xf9, - 0x01, 0x46, 0x00, 0x98, 0x80, 0x69, 0x06, 0xf0, 0x09, 0xfb, 0x04, 0xd3, - 0x00, 0x98, 0x00, 0x88, 0x08, 0x28, 0xc0, 0xf2, 0x90, 0x80, 0x11, 0x98, - 0x02, 0xf0, 0xbe, 0xfc, 0x00, 0x28, 0x03, 0xd0, 0x04, 0x20, 0x02, 0xf0, - 0xab, 0xfc, 0x00, 0x28, 0x00, 0xf0, 0x85, 0x80, 0x0c, 0x98, 0x00, 0xf0, - 0xd6, 0xfc, 0x00, 0x90, 0x49, 0x46, 0x0b, 0x98, 0x06, 0xf0, 0x02, 0xfb, - 0x00, 0x99, 0x06, 0xf0, 0x63, 0xfa, 0x59, 0x46, 0x06, 0xf0, 0x6e, 0xf9, - 0x00, 0x90, 0x39, 0x46, 0x0b, 0x98, 0x06, 0xf0, 0xf7, 0xfa, 0x07, 0x46, - 0x0c, 0x98, 0x00, 0xf0, 0xbb, 0xfc, 0x01, 0x46, 0x38, 0x46, 0x06, 0xf0, - 0xdf, 0xf9, 0x59, 0x46, 0x06, 0xf0, 0x5e, 0xf9, 0x0a, 0x90, 0x4f, 0xf0, - 0x7e, 0x50, 0x18, 0x99, 0x06, 0xf0, 0xd6, 0xf9, 0xb8, 0xf1, 0x00, 0x0f, - 0x81, 0x46, 0x5c, 0xd1, 0x67, 0x68, 0x00, 0xf0, 0xa6, 0xfc, 0x0d, 0x99, - 0x06, 0xf0, 0xdc, 0xfa, 0xb9, 0x69, 0x06, 0xf0, 0x3d, 0xfa, 0xb8, 0x61, - 0x49, 0x46, 0x00, 0x98, 0x06, 0xf0, 0xd4, 0xfa, 0xf9, 0x69, 0x06, 0xf0, - 0x35, 0xfa, 0xf8, 0x61, 0x49, 0x46, 0x0a, 0x98, 0x06, 0xf0, 0xcc, 0xfa, - 0x39, 0x6a, 0x06, 0xf0, 0x2d, 0xfa, 0x38, 0x62, 0x4f, 0xf0, 0x7e, 0x51, - 0x38, 0x6d, 0x06, 0xf0, 0x27, 0xfa, 0x38, 0x65, 0x59, 0x46, 0x0d, 0x98, - 0x06, 0xf0, 0xbe, 0xfa, 0x81, 0x46, 0x00, 0x98, 0x49, 0x46, 0x06, 0xf0, - 0x2b, 0xf9, 0x79, 0x6d, 0x83, 0x46, 0x06, 0xf0, 0xa5, 0xf9, 0x00, 0x90, - 0x39, 0x6d, 0x06, 0xf0, 0x23, 0xf9, 0x79, 0x6d, 0x06, 0xf0, 0x12, 0xfa, - 0x01, 0x46, 0x79, 0x65, 0x00, 0xf0, 0x76, 0xfc, 0x00, 0x99, 0x06, 0xf0, - 0xa7, 0xfa, 0xf9, 0x6d, 0x06, 0xf0, 0x08, 0xfa, 0xf8, 0x65, 0x49, 0x46, - 0x0a, 0x98, 0x06, 0xf0, 0x11, 0xf9, 0xb9, 0x6d, 0x81, 0x46, 0x06, 0xf0, - 0x8b, 0xf9, 0x39, 0x6d, 0x83, 0x46, 0x06, 0xf0, 0x09, 0xf9, 0xb9, 0x6d, - 0x06, 0xf0, 0xf8, 0xf9, 0x01, 0x46, 0xb9, 0x65, 0x48, 0x46, 0x06, 0xf0, - 0x7f, 0xf9, 0x59, 0x46, 0x06, 0xf0, 0x8c, 0xfa, 0x39, 0x6e, 0x06, 0xf0, - 0xed, 0xf9, 0x38, 0x66, 0x01, 0xe0, 0x01, 0x28, 0x03, 0xdb, 0x0f, 0x98, - 0xdd, 0xf8, 0x38, 0xb0, 0x00, 0x90, 0xba, 0xf1, 0x00, 0x0f, 0x04, 0x98, - 0x05, 0x90, 0x03, 0x98, 0x04, 0x90, 0x7f, 0xf4, 0x70, 0xae, 0x60, 0x68, - 0xdf, 0xf8, 0x74, 0x2d, 0x50, 0xf8, 0x14, 0x7f, 0xdf, 0xf8, 0x6c, 0x3d, - 0x07, 0xf0, 0x01, 0x01, 0x51, 0x43, 0x81, 0xea, 0x57, 0x01, 0x00, 0xf0, - 0x05, 0xf9, 0x00, 0xf0, 0x03, 0xf9, 0x01, 0x60, 0x07, 0xf0, 0x01, 0x02, - 0x07, 0xf0, 0x02, 0x01, 0x49, 0x1e, 0x7b, 0x07, 0x05, 0xd5, 0xfb, 0x43, - 0x03, 0xf0, 0x01, 0x03, 0x4b, 0x43, 0x51, 0x43, 0x01, 0xe0, 0x52, 0x00, - 0x53, 0x1e, 0x07, 0x8f, 0x79, 0x43, 0x07, 0xfb, 0x03, 0xf2, 0xb0, 0xf9, - 0x5a, 0x70, 0x13, 0xb2, 0x3b, 0x44, 0xbd, 0xf9, 0x10, 0x70, 0xbb, 0x42, - 0x07, 0xd1, 0xb0, 0xf9, 0x5c, 0x70, 0x0b, 0xb2, 0x3b, 0x44, 0xbd, 0xf9, - 0x12, 0x70, 0xbb, 0x42, 0x04, 0xd0, 0x02, 0x9f, 0x01, 0x9b, 0x7f, 0x1e, - 0xbb, 0x42, 0x01, 0xdb, 0x00, 0x22, 0x00, 0x21, 0x83, 0x8e, 0xd3, 0x18, - 0x83, 0x86, 0xc3, 0x8e, 0xcb, 0x18, 0xc3, 0x86, 0xb0, 0xf8, 0x5a, 0x30, - 0xd2, 0x18, 0xad, 0xf8, 0x0c, 0x20, 0xb0, 0xf8, 0x5c, 0x00, 0x08, 0x18, - 0xad, 0xf8, 0x0e, 0x00, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2e, 0x07, 0xd1, - 0x05, 0xf0, 0xfb, 0xf8, 0x02, 0x28, 0x0c, 0xbf, 0x06, 0x26, 0x01, 0x28, - 0x00, 0xd1, 0x01, 0x25, 0xdf, 0xf8, 0x50, 0xca, 0xdd, 0xe9, 0x14, 0x23, - 0xdc, 0xe9, 0x00, 0x01, 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x14, 0x01, - 0xdd, 0xe9, 0x12, 0x23, 0xdc, 0xe9, 0x02, 0x01, 0x10, 0x18, 0x59, 0x41, - 0xcd, 0xe9, 0x12, 0x01, 0xdd, 0xe9, 0x08, 0x23, 0xdc, 0xe9, 0x04, 0x01, - 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x08, 0x01, 0xdd, 0xe9, 0x06, 0x23, - 0xdc, 0xe9, 0x06, 0x01, 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x06, 0x01, - 0x4f, 0xea, 0x68, 0x09, 0x20, 0x68, 0x24, 0x30, 0xc1, 0x8b, 0x00, 0x29, - 0x47, 0xd0, 0x16, 0x98, 0x4f, 0xf0, 0x8a, 0x41, 0x00, 0x2d, 0x08, 0x60, - 0x48, 0xd1, 0x00, 0x2e, 0x7f, 0xf4, 0xe5, 0xad, 0x05, 0xf0, 0xa5, 0xf8, - 0x20, 0x68, 0xb0, 0xf9, 0x24, 0x10, 0x17, 0x9a, 0x03, 0xa8, 0xff, 0xf7, - 0x41, 0xfc, 0x00, 0xf0, 0x96, 0xf8, 0x05, 0xf0, 0xb6, 0xf8, 0x02, 0x28, - 0x0c, 0xbf, 0x06, 0x26, 0x01, 0x28, 0x00, 0xd1, 0x01, 0x25, 0x10, 0x98, - 0x4f, 0xf0, 0x8a, 0x41, 0x08, 0x60, 0x67, 0x68, 0xdf, 0xf8, 0xec, 0x1d, - 0x78, 0x6e, 0x06, 0xf0, 0xd3, 0xf9, 0xdf, 0xf8, 0x90, 0x1d, 0x84, 0x46, - 0xdf, 0xf8, 0xac, 0x09, 0xc7, 0xf8, 0x64, 0xc0, 0xd1, 0xe9, 0x00, 0x23, - 0x00, 0x68, 0x00, 0xf0, 0x68, 0xf8, 0x08, 0xbf, 0x00, 0x28, 0x0b, 0xd0, - 0xdf, 0xf8, 0x70, 0x1d, 0xdf, 0xf8, 0x90, 0x09, 0x80, 0x68, 0xd1, 0xe9, - 0x12, 0x23, 0x00, 0xf0, 0x5c, 0xf8, 0x08, 0xbf, 0x00, 0x28, 0x0d, 0xd1, - 0x4f, 0xf0, 0x7e, 0x51, 0x60, 0x46, 0x06, 0xf0, 0x17, 0xf9, 0x78, 0x66, - 0x06, 0xe0, 0x41, 0x5e, 0x17, 0x9a, 0x03, 0xa8, 0xff, 0xf7, 0x06, 0xfc, - 0x00, 0xf0, 0x5b, 0xf8, 0x00, 0x2d, 0x3f, 0xf4, 0x9c, 0xad, 0x02, 0x98, - 0x80, 0x1c, 0x08, 0xf0, 0x01, 0x01, 0x40, 0x1a, 0x09, 0xf0, 0x01, 0x01, - 0x40, 0x1a, 0x02, 0x90, 0x4f, 0xf0, 0x03, 0x08, 0x91, 0xe5, 0x20, 0x68, - 0xb0, 0xf9, 0x24, 0x10, 0x60, 0x68, 0x17, 0x9a, 0x6e, 0x30, 0xff, 0xf7, - 0xed, 0xfb, 0x00, 0xf0, 0x42, 0xf8, 0x00, 0xf0, 0x3a, 0xf8, 0x02, 0xf0, - 0xed, 0xfa, 0x60, 0x6a, 0xdf, 0xf8, 0x58, 0x18, 0x08, 0x60, 0x00, 0xf0, - 0x99, 0xfc, 0x28, 0xb1, 0x00, 0x21, 0x04, 0xf1, 0x2c, 0x00, 0x04, 0xf0, - 0x10, 0xfd, 0x03, 0xe0, 0x04, 0xf1, 0x2c, 0x00, 0x04, 0xf0, 0x78, 0xff, - 0x04, 0xf1, 0x28, 0x00, 0x04, 0xf0, 0xc4, 0xfb, 0x00, 0x20, 0x02, 0xf0, - 0x69, 0xfd, 0x15, 0xb1, 0x00, 0x2e, 0x3f, 0xf4, 0xe4, 0xac, 0x30, 0x46, - 0x19, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, 0xff, 0xe6, 0xdb, 0x2e, - 0x14, 0x0a, 0x00, 0x46, 0x98, 0xf1, 0x00, 0x20, 0x01, 0x60, 0x01, 0xf0, - 0x01, 0x02, 0x5a, 0x43, 0x82, 0xea, 0x51, 0x01, 0x70, 0x47, 0xdb, 0x01, - 0x43, 0xea, 0x52, 0x63, 0x40, 0x43, 0xd2, 0x01, 0xc1, 0x17, 0x10, 0x1a, - 0x73, 0xeb, 0x01, 0x01, 0x70, 0x47, 0x02, 0x22, 0x04, 0xf1, 0x22, 0x01, - 0x0f, 0xf6, 0x68, 0x50, 0x70, 0x47, 0x22, 0x99, 0x09, 0x68, 0x08, 0x43, - 0x22, 0x99, 0x08, 0x60, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x8d, 0xb0, - 0x53, 0x78, 0x12, 0x78, 0x04, 0x46, 0x88, 0x46, 0xff, 0xf7, 0x41, 0xfc, - 0x20, 0x8b, 0xc0, 0xb2, 0x05, 0xf0, 0x56, 0xf8, 0x4f, 0xea, 0x40, 0x0b, - 0xe0, 0x69, 0x05, 0xf0, 0x99, 0xff, 0xdf, 0xf8, 0xc8, 0x1c, 0x05, 0xf0, - 0xa5, 0xff, 0x05, 0x90, 0x26, 0x68, 0xf0, 0x8d, 0x05, 0xf0, 0x90, 0xff, - 0xdf, 0xf8, 0xb8, 0x1c, 0x05, 0xf0, 0x9c, 0xff, 0x01, 0x46, 0x06, 0xf0, - 0x27, 0xf9, 0x07, 0x46, 0xe0, 0x8a, 0x05, 0xf0, 0x85, 0xff, 0x00, 0xf0, - 0xf0, 0xfa, 0x07, 0x46, 0x05, 0x99, 0x4f, 0xf0, 0x7e, 0x50, 0x06, 0xf0, - 0x0b, 0xf8, 0x4f, 0xf0, 0x80, 0x41, 0x06, 0xf0, 0x17, 0xf9, 0x01, 0x46, - 0x38, 0x46, 0x05, 0xf0, 0x85, 0xff, 0x82, 0x46, 0x4f, 0xf0, 0x7a, 0x50, - 0x51, 0x46, 0x06, 0xf0, 0x0d, 0xf9, 0x07, 0x90, 0x00, 0x20, 0x63, 0x68, - 0x03, 0xf1, 0x28, 0x02, 0xc2, 0xe9, 0x00, 0x00, 0xc2, 0xe9, 0x02, 0x00, - 0xc2, 0xe9, 0x04, 0x00, 0xc2, 0xe9, 0x06, 0x00, 0x10, 0x84, 0x50, 0x84, - 0x90, 0x62, 0x50, 0x63, 0xd0, 0x62, 0x90, 0x63, 0x10, 0x63, 0xa3, 0xf8, - 0x68, 0x00, 0x04, 0x90, 0x71, 0x8d, 0x90, 0x8c, 0x88, 0x42, 0x26, 0xbf, - 0xb1, 0x8d, 0x81, 0x42, 0x91, 0x84, 0x04, 0xa8, 0x00, 0x90, 0x5a, 0x46, - 0x05, 0x9b, 0x21, 0x46, 0x40, 0x46, 0xff, 0xf7, 0x4d, 0xfc, 0x00, 0x28, - 0x40, 0xf0, 0xa0, 0x82, 0x40, 0x46, 0x02, 0xf0, 0x82, 0xfb, 0x06, 0x46, - 0x40, 0x46, 0x02, 0xf0, 0x87, 0xfb, 0x07, 0x46, 0x40, 0xf2, 0x47, 0x30, - 0x86, 0x42, 0x0d, 0xda, 0x0f, 0xf6, 0xdc, 0x40, 0x30, 0x5c, 0x00, 0xf2, - 0x01, 0x10, 0x80, 0xb2, 0x05, 0xf0, 0x32, 0xff, 0x4f, 0xf0, 0x72, 0x51, - 0x06, 0xf0, 0xcc, 0xf8, 0x06, 0x46, 0x01, 0xe0, 0x4f, 0xf0, 0x82, 0x46, - 0xdf, 0xf8, 0x10, 0x15, 0x0f, 0xf6, 0x54, 0x40, 0x79, 0x56, 0x30, 0xf8, - 0x11, 0x00, 0x05, 0xf0, 0x21, 0xff, 0xdf, 0xf8, 0x88, 0x17, 0x05, 0xf0, - 0x2d, 0xff, 0x00, 0xf0, 0x91, 0xfa, 0x0b, 0x90, 0xe0, 0x8a, 0x40, 0x08, - 0x05, 0xf0, 0x16, 0xff, 0x07, 0x46, 0x60, 0x68, 0x0a, 0x90, 0x00, 0xf1, - 0x18, 0x05, 0xd5, 0xe9, 0x04, 0x01, 0x05, 0xf0, 0xd1, 0xfe, 0x00, 0xf0, - 0x7e, 0xfa, 0x81, 0x46, 0xd5, 0xe9, 0x06, 0x01, 0x05, 0xf0, 0xca, 0xfe, - 0x00, 0xf0, 0x77, 0xfa, 0x06, 0x90, 0xd5, 0xe9, 0x08, 0x01, 0x05, 0xf0, - 0xc3, 0xfe, 0x00, 0xf0, 0x70, 0xfa, 0x09, 0x90, 0xd5, 0xe9, 0x0a, 0x01, - 0x05, 0xf0, 0xbc, 0xfe, 0x00, 0xf0, 0x69, 0xfa, 0x08, 0x90, 0x2f, 0x68, - 0x69, 0x6c, 0xa8, 0x6c, 0x05, 0xf0, 0xf2, 0xff, 0x01, 0x90, 0x00, 0xf0, - 0x6b, 0xfa, 0x00, 0x90, 0xa9, 0x68, 0x00, 0xf0, 0x68, 0xfa, 0x00, 0x99, - 0x05, 0xf0, 0xe8, 0xff, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, 0x06, 0xf0, - 0x7f, 0xf8, 0x01, 0x46, 0x00, 0x98, 0x05, 0xf0, 0xed, 0xfe, 0x07, 0x46, - 0xa9, 0x6b, 0xdf, 0xf8, 0x54, 0x0b, 0x05, 0xf0, 0xd9, 0xff, 0x00, 0xf0, - 0x42, 0xfa, 0x01, 0x46, 0x01, 0x98, 0x05, 0xf0, 0xe1, 0xfe, 0x01, 0x46, - 0x50, 0x46, 0x06, 0xf0, 0x59, 0xf8, 0x02, 0xd2, 0xa8, 0x8e, 0x40, 0x1c, - 0xa8, 0x86, 0x08, 0x46, 0x07, 0x99, 0x06, 0xf0, 0x51, 0xf8, 0x04, 0xd2, - 0xa9, 0x8e, 0xa1, 0xeb, 0x11, 0x10, 0x40, 0x1e, 0xa8, 0x86, 0x20, 0x68, - 0x00, 0xf1, 0x26, 0x07, 0xb8, 0x8b, 0x02, 0x28, 0x0b, 0xd1, 0xf8, 0x8b, - 0x05, 0xf0, 0xb6, 0xfe, 0xe9, 0x6c, 0x06, 0xf0, 0x3f, 0xf8, 0x04, 0xd2, - 0xa8, 0x8e, 0x08, 0x28, 0xbc, 0xbf, 0x08, 0x20, 0xa8, 0x86, 0x48, 0x46, - 0x00, 0x21, 0x06, 0xf0, 0x35, 0xf8, 0xca, 0x46, 0x38, 0xbf, 0x8a, 0xf0, - 0x00, 0x4a, 0x06, 0x98, 0x06, 0xf0, 0x2e, 0xf8, 0x38, 0xbf, 0x80, 0xf0, - 0x00, 0x40, 0x00, 0x90, 0x58, 0x46, 0x05, 0xf0, 0x91, 0xfe, 0x07, 0x90, - 0x51, 0x46, 0x00, 0x98, 0x05, 0xf0, 0x98, 0xff, 0x82, 0x46, 0xdf, 0xf8, - 0xcc, 0x0a, 0x00, 0xf0, 0xf3, 0xf9, 0x07, 0x99, 0x05, 0xf0, 0x9e, 0xfe, - 0x51, 0x46, 0x06, 0xf0, 0x29, 0xf8, 0xdf, 0xf8, 0xbc, 0x1a, 0x06, 0xf0, - 0x25, 0xf8, 0x06, 0xf0, 0x8f, 0xf8, 0xad, 0xf8, 0x04, 0x00, 0xbd, 0xf8, - 0x04, 0x10, 0xa8, 0x8e, 0x88, 0x42, 0x38, 0xbf, 0x08, 0x46, 0xa8, 0x86, - 0xf9, 0x88, 0xa8, 0x8e, 0x81, 0x42, 0x26, 0xbf, 0xb9, 0x88, 0x88, 0x42, - 0xa9, 0x86, 0x00, 0xf0, 0xf1, 0xf9, 0xa9, 0x68, 0x82, 0x46, 0x00, 0xf0, - 0xee, 0xf9, 0x51, 0x46, 0x05, 0xf0, 0x6e, 0xff, 0x0b, 0x99, 0x06, 0xf0, - 0x07, 0xf8, 0x29, 0x68, 0x05, 0xf0, 0x76, 0xfe, 0x4f, 0xf0, 0x7e, 0x51, - 0x05, 0xf0, 0xee, 0xff, 0x82, 0x46, 0x38, 0xbf, 0x8a, 0x46, 0x09, 0x99, - 0x68, 0x68, 0x05, 0xf0, 0xf9, 0xff, 0x83, 0x46, 0x08, 0x99, 0xa8, 0x68, - 0x05, 0xf0, 0xf4, 0xff, 0x59, 0x46, 0x05, 0xf0, 0x55, 0xff, 0x00, 0xf0, - 0xc1, 0xf9, 0x83, 0x46, 0x08, 0x99, 0x68, 0x68, 0x05, 0xf0, 0xea, 0xff, - 0x00, 0x90, 0x09, 0x99, 0xa8, 0x68, 0x05, 0xf0, 0xe5, 0xff, 0x01, 0x46, - 0x00, 0x98, 0x05, 0xf0, 0xd1, 0xfe, 0x00, 0xf0, 0xb1, 0xf9, 0x00, 0x90, - 0xe0, 0x8a, 0x40, 0x08, 0x05, 0xf0, 0x3c, 0xfe, 0x82, 0x46, 0xb5, 0xf9, - 0x30, 0x00, 0x05, 0xf0, 0x2d, 0xfe, 0x00, 0xf0, 0xa5, 0xf9, 0x00, 0xf0, - 0x9c, 0xf9, 0x83, 0x46, 0xb5, 0xf9, 0x32, 0x00, 0x05, 0xf0, 0x24, 0xfe, - 0x00, 0xf0, 0x9c, 0xf9, 0x01, 0x46, 0x00, 0x98, 0x05, 0xf0, 0xb6, 0xfe, - 0x05, 0x46, 0xb8, 0x89, 0x90, 0xb1, 0x07, 0x99, 0x30, 0x46, 0x05, 0xf0, - 0x31, 0xfe, 0x06, 0x46, 0x48, 0x46, 0x00, 0xf0, 0x7f, 0xf9, 0x00, 0xf0, - 0x84, 0xf9, 0x83, 0x46, 0x06, 0x98, 0x00, 0xf0, 0x79, 0xf9, 0x01, 0x46, - 0x28, 0x46, 0x05, 0xf0, 0xa1, 0xfe, 0x05, 0x46, 0x58, 0x46, 0x06, 0xf0, - 0x3b, 0xf8, 0x06, 0xf0, 0x17, 0xf8, 0xad, 0xf8, 0x0c, 0x00, 0x28, 0x46, - 0x06, 0xf0, 0x34, 0xf8, 0x06, 0xf0, 0x10, 0xf8, 0xad, 0xf8, 0x0e, 0x00, - 0x78, 0x88, 0x05, 0xf0, 0x01, 0xfe, 0x06, 0x46, 0xbd, 0xf8, 0x04, 0x00, - 0x05, 0xf0, 0xfc, 0xfd, 0x01, 0x46, 0xdf, 0xf8, 0x9c, 0x09, 0x05, 0xf0, - 0x85, 0xfe, 0x00, 0xf0, 0x57, 0xf9, 0xdf, 0xf8, 0x94, 0x19, 0x05, 0xf0, - 0x01, 0xfe, 0xdf, 0xf8, 0x90, 0x19, 0x05, 0xf0, 0x79, 0xff, 0x81, 0x46, - 0x38, 0xbf, 0x89, 0x46, 0x00, 0xf0, 0x4d, 0xf9, 0x06, 0xf0, 0x12, 0xf8, - 0x05, 0xf0, 0xee, 0xff, 0xad, 0xf8, 0x08, 0x00, 0x49, 0x46, 0x28, 0x46, - 0x05, 0xf0, 0x7c, 0xff, 0x06, 0xf0, 0x08, 0xf8, 0x05, 0xf0, 0xe4, 0xff, - 0xad, 0xf8, 0x0a, 0x00, 0x0a, 0x98, 0xb0, 0xf8, 0x76, 0x00, 0x28, 0xb3, - 0xbd, 0xf9, 0x0a, 0x00, 0xbd, 0xf9, 0x08, 0x10, 0x23, 0x8c, 0x00, 0xfb, - 0x00, 0xf2, 0x01, 0xfb, 0x01, 0x22, 0x9a, 0x42, 0x1a, 0xda, 0x3a, 0x88, - 0x8a, 0x42, 0xbc, 0xbf, 0x12, 0xb2, 0xad, 0xf8, 0x08, 0x20, 0x39, 0x88, - 0x81, 0x42, 0xb8, 0xbf, 0xad, 0xf8, 0x0a, 0x10, 0x38, 0x88, 0xbd, 0xf9, - 0x08, 0x10, 0x40, 0x42, 0x81, 0x42, 0xb8, 0xbf, 0xad, 0xf8, 0x08, 0x00, - 0x38, 0x88, 0xbd, 0xf9, 0x0a, 0x10, 0x40, 0x42, 0x81, 0x42, 0xb8, 0xbf, - 0xad, 0xf8, 0x0a, 0x00, 0xff, 0xf7, 0x46, 0xf9, 0x06, 0x46, 0x60, 0x68, - 0xbd, 0xf8, 0x0c, 0x20, 0xb0, 0xf9, 0x6e, 0x10, 0xbd, 0xf8, 0x0e, 0x30, - 0x8a, 0x1a, 0xad, 0xf8, 0x0c, 0x20, 0xb0, 0xf8, 0x70, 0x20, 0xd2, 0x1a, - 0xad, 0xf8, 0x0e, 0x20, 0xbd, 0xf8, 0x08, 0x20, 0x89, 0x1a, 0xad, 0xf8, - 0x08, 0x10, 0x42, 0x46, 0xb0, 0xf8, 0x70, 0x00, 0xbd, 0xf8, 0x0a, 0x10, - 0x40, 0x1a, 0xad, 0xf8, 0x0a, 0x00, 0x20, 0x68, 0xb0, 0xf9, 0x24, 0x10, - 0x02, 0xa8, 0xff, 0xf7, 0x81, 0xf9, 0x04, 0x99, 0x08, 0x43, 0x04, 0x90, - 0x61, 0x68, 0x02, 0x98, 0xc1, 0xf8, 0x6e, 0x00, 0x86, 0xf3, 0x11, 0x88, - 0x34, 0x21, 0xdf, 0xf8, 0x4c, 0x04, 0x01, 0xfb, 0x08, 0x06, 0x23, 0x46, - 0x30, 0x69, 0x40, 0x1c, 0x30, 0x61, 0xf0, 0x68, 0x40, 0x1c, 0xf0, 0x60, - 0x04, 0x9a, 0x02, 0x99, 0x03, 0x98, 0xcd, 0xf8, 0x00, 0x80, 0x00, 0xf0, - 0xf4, 0xf8, 0x20, 0x68, 0x30, 0xf8, 0x42, 0x1f, 0x69, 0xb1, 0x61, 0x68, - 0x40, 0x88, 0x01, 0xf1, 0x4c, 0x07, 0x05, 0xf0, 0x63, 0xfd, 0x01, 0x46, - 0xb8, 0x69, 0x05, 0xf0, 0xeb, 0xfe, 0x02, 0xd3, 0x38, 0x88, 0x08, 0x28, - 0x14, 0xdb, 0xff, 0xf7, 0xf3, 0xf8, 0x67, 0x68, 0xb9, 0x69, 0x80, 0x46, - 0x05, 0x98, 0x05, 0xf0, 0xf1, 0xfe, 0xb8, 0x61, 0xf9, 0x69, 0x05, 0x98, - 0x05, 0xf0, 0xec, 0xfe, 0xf8, 0x61, 0x39, 0x6a, 0x05, 0x98, 0x05, 0xf0, - 0xe7, 0xfe, 0x38, 0x62, 0x88, 0xf3, 0x11, 0x88, 0x00, 0xf0, 0xc4, 0xfe, - 0x64, 0x68, 0x04, 0xf1, 0x18, 0x08, 0xd8, 0xf8, 0x04, 0x10, 0xd8, 0xf8, - 0x08, 0x70, 0x00, 0xf0, 0xba, 0xf8, 0x00, 0xf0, 0xbb, 0xf8, 0x49, 0x46, - 0x05, 0xf0, 0x38, 0xfe, 0x05, 0xf0, 0x78, 0xfe, 0x01, 0x46, 0x0b, 0x98, - 0x05, 0xf0, 0xce, 0xfe, 0xd8, 0xf8, 0x00, 0x10, 0x05, 0xf0, 0x3c, 0xfd, - 0xb0, 0x61, 0xd8, 0xf8, 0x08, 0x00, 0xd8, 0xf8, 0x04, 0x10, 0x80, 0xf0, - 0x00, 0x40, 0x05, 0xf0, 0x63, 0xff, 0xf0, 0x61, 0xb8, 0xf8, 0x34, 0x00, - 0x30, 0x86, 0x34, 0xf9, 0x0e, 0x0f, 0x00, 0x28, 0x6a, 0xd1, 0x58, 0x46, - 0x59, 0x46, 0x05, 0xf0, 0xb5, 0xfe, 0x07, 0x46, 0x28, 0x46, 0x29, 0x46, - 0x05, 0xf0, 0xb0, 0xfe, 0x39, 0x46, 0x05, 0xf0, 0x11, 0xfe, 0x05, 0xf0, - 0x51, 0xfe, 0x05, 0x46, 0xb1, 0x6a, 0x4f, 0xf0, 0x7e, 0x50, 0x05, 0xf0, - 0x09, 0xfe, 0xb0, 0x62, 0x28, 0x46, 0x31, 0x6a, 0x05, 0xf0, 0x90, 0xfd, - 0xb1, 0x6a, 0x07, 0x46, 0x05, 0xf0, 0x0e, 0xfd, 0x31, 0x6a, 0x05, 0xf0, - 0xfd, 0xfd, 0x01, 0x46, 0x31, 0x62, 0x28, 0x46, 0x05, 0xf0, 0x84, 0xfd, - 0x00, 0xf0, 0x61, 0xf8, 0x71, 0x6a, 0x05, 0xf0, 0xf3, 0xfd, 0x70, 0x62, - 0xdf, 0xf8, 0x90, 0x17, 0xb0, 0x6a, 0x05, 0xf0, 0x91, 0xff, 0x39, 0xd8, - 0x01, 0x46, 0xdf, 0xf8, 0x70, 0x07, 0xdf, 0xf8, 0x48, 0x57, 0x05, 0xf0, - 0xe5, 0xfd, 0x01, 0x46, 0x70, 0x6a, 0x05, 0xf0, 0xef, 0xfc, 0x01, 0x46, - 0xf1, 0x62, 0xdf, 0xf8, 0x70, 0x07, 0x05, 0xf0, 0xdb, 0xfd, 0x01, 0x46, - 0xdf, 0xf8, 0x68, 0x07, 0x05, 0xf0, 0xe4, 0xfc, 0x05, 0xf0, 0xfe, 0xfe, - 0x05, 0xf0, 0xda, 0xfe, 0xb0, 0x60, 0x65, 0x28, 0x24, 0xbf, 0x64, 0x20, - 0xb0, 0x60, 0xb0, 0x6a, 0x29, 0x46, 0x05, 0xf0, 0x65, 0xfe, 0xdf, 0xf8, - 0x2c, 0x17, 0x05, 0xf0, 0xc5, 0xfd, 0x71, 0x6a, 0x05, 0xf0, 0x5e, 0xfe, - 0x07, 0x46, 0xb1, 0x6a, 0xdf, 0xf8, 0x18, 0x07, 0x05, 0xf0, 0xbc, 0xfd, - 0x01, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xc6, 0xfc, 0x70, 0x62, 0x29, 0x46, - 0xb0, 0x6a, 0x05, 0xf0, 0x4f, 0xfe, 0xb0, 0x62, 0x04, 0x98, 0x20, 0xb1, - 0x01, 0x20, 0x60, 0x80, 0x70, 0x69, 0x40, 0x1c, 0x70, 0x61, 0x00, 0xf0, - 0x3c, 0xfe, 0x00, 0x20, 0x0d, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, - 0x48, 0xad, 0x00, 0x20, 0x24, 0x2b, 0x00, 0x20, 0x31, 0x46, 0x05, 0xf0, - 0x39, 0xbe, 0x58, 0x46, 0x49, 0x46, 0x05, 0xf0, 0x35, 0xbe, 0x01, 0x46, - 0x58, 0x46, 0x05, 0xf0, 0x21, 0xbd, 0x39, 0x46, 0x05, 0xf0, 0x2e, 0xbe, - 0x51, 0x46, 0x05, 0xf0, 0x9d, 0xbc, 0x39, 0x46, 0x05, 0xf0, 0x9a, 0xbc, - 0x01, 0x46, 0xdf, 0xf8, 0xd0, 0x06, 0x06, 0xf0, 0x9a, 0xb8, 0x00, 0x00, - 0xdc, 0x2a, 0x00, 0x20, 0x69, 0x68, 0x08, 0x46, 0x05, 0xf0, 0x1c, 0xbe, - 0x81, 0x46, 0x38, 0x46, 0x39, 0x46, 0x05, 0xf0, 0x17, 0xbe, 0x2d, 0xe9, - 0xfa, 0x4f, 0x83, 0xb0, 0x1e, 0x68, 0xd3, 0xf8, 0x04, 0x80, 0x22, 0xb1, - 0x40, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0xb6, 0xe0, 0x0e, 0x98, - 0x02, 0xf0, 0xb2, 0xf8, 0x08, 0xf1, 0x68, 0x05, 0x83, 0x46, 0xa9, 0x88, - 0xdf, 0xf8, 0x8c, 0x06, 0x09, 0x56, 0x02, 0x91, 0x1b, 0xf9, 0x00, 0x00, - 0x40, 0x1a, 0x7d, 0xd0, 0x28, 0x88, 0x00, 0x28, 0x7a, 0xd1, 0xb8, 0xf9, - 0x0c, 0x00, 0xe8, 0xb1, 0x04, 0x98, 0x40, 0x68, 0x02, 0x9a, 0x00, 0xf5, - 0x02, 0x74, 0xd4, 0xe9, 0x02, 0x01, 0x02, 0xf0, 0x35, 0xf9, 0xc0, 0x07, - 0x12, 0xd4, 0xd4, 0xe9, 0x02, 0x01, 0xcd, 0xe9, 0x00, 0x01, 0x02, 0x9a, - 0x01, 0x20, 0x00, 0x21, 0x06, 0xf0, 0x5c, 0xf8, 0xdd, 0xe9, 0x00, 0x23, - 0x10, 0x43, 0x19, 0x43, 0xc4, 0xe9, 0x02, 0x01, 0x00, 0x26, 0x4f, 0xf0, - 0x7e, 0x5a, 0x0d, 0xe0, 0xf0, 0x69, 0x05, 0xf0, 0x37, 0xfc, 0xdf, 0xf8, - 0x04, 0x16, 0x05, 0xf0, 0x43, 0xfc, 0x06, 0x46, 0x4f, 0xf0, 0x7e, 0x50, - 0x31, 0x46, 0x05, 0xf0, 0xbb, 0xfc, 0x82, 0x46, 0xb5, 0xf9, 0x0a, 0x00, - 0x44, 0x01, 0xb5, 0xf9, 0x0c, 0x00, 0x4f, 0xea, 0x40, 0x19, 0x02, 0x98, - 0x08, 0xeb, 0xc0, 0x07, 0x04, 0x98, 0x42, 0x68, 0xd2, 0xe9, 0x82, 0x01, - 0x02, 0x9a, 0x02, 0xf0, 0x01, 0xf9, 0xc0, 0x07, 0x2b, 0xd5, 0x20, 0x46, - 0x05, 0xf0, 0x0c, 0xfc, 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0xb0, 0xfd, - 0x04, 0x46, 0xb8, 0x6f, 0x05, 0xf0, 0x04, 0xfc, 0x01, 0x46, 0x30, 0x46, - 0x05, 0xf0, 0xa8, 0xfd, 0x01, 0x46, 0x20, 0x46, 0x05, 0xf0, 0x08, 0xfd, - 0x05, 0xf0, 0x0e, 0xfe, 0x04, 0x46, 0x48, 0x46, 0x05, 0xf0, 0xf6, 0xfb, - 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0x9a, 0xfd, 0x82, 0x46, 0xf8, 0x6f, - 0x05, 0xf0, 0xee, 0xfb, 0x01, 0x46, 0x30, 0x46, 0x05, 0xf0, 0x92, 0xfd, - 0x01, 0x46, 0x50, 0x46, 0x05, 0xf0, 0xf2, 0xfc, 0x05, 0xf0, 0xf8, 0xfd, - 0x81, 0x46, 0xfe, 0xf7, 0x85, 0xff, 0xbc, 0x67, 0x06, 0x46, 0xc7, 0xf8, - 0x7c, 0x90, 0x02, 0x98, 0x81, 0xb2, 0x04, 0x98, 0x00, 0xf0, 0xd6, 0xfa, - 0x86, 0xf3, 0x11, 0x88, 0x28, 0x88, 0x48, 0xb9, 0xfe, 0xf7, 0x76, 0xff, - 0x06, 0x46, 0x03, 0x98, 0xc8, 0xf8, 0x72, 0x00, 0xa5, 0xf8, 0x04, 0xb0, - 0x86, 0xf3, 0x11, 0x88, 0x01, 0x20, 0xe8, 0x81, 0x58, 0xe1, 0x38, 0xb5, - 0x14, 0x46, 0xdf, 0xf8, 0x64, 0x15, 0x4f, 0xf4, 0x08, 0x72, 0x02, 0xfb, - 0x00, 0x15, 0xff, 0xf7, 0x1b, 0xf8, 0x05, 0xf1, 0x68, 0x00, 0x01, 0x21, - 0x44, 0x80, 0x01, 0x80, 0x31, 0xbd, 0x00, 0x00, 0x04, 0x00, 0x00, 0x51, - 0x00, 0x00, 0x50, 0x59, 0x00, 0x00, 0x40, 0x59, 0x06, 0x40, 0x80, 0x83, - 0x07, 0x40, 0x00, 0x80, 0x00, 0xf5, 0x02, 0x70, 0x00, 0x22, 0xc0, 0xe9, - 0x00, 0x22, 0xc0, 0xe9, 0x02, 0x22, 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x00, 0xf0, 0x59, 0xf8, 0x40, 0xf2, 0x42, 0x66, 0x88, 0xb3, - 0xdf, 0xf8, 0x14, 0x05, 0xb0, 0xf8, 0x54, 0x10, 0x28, 0x46, 0x03, 0xf0, - 0xa6, 0xfb, 0x08, 0xb1, 0x07, 0x20, 0x70, 0xbd, 0xdf, 0xf8, 0x04, 0x05, - 0x01, 0x78, 0x03, 0x22, 0x11, 0x42, 0x06, 0xd0, 0x00, 0x7e, 0x00, 0xf0, - 0x03, 0x00, 0x02, 0x28, 0x01, 0xd1, 0x06, 0x20, 0x70, 0xbd, 0xe8, 0xb2, - 0x02, 0xf0, 0xea, 0xfb, 0x00, 0x28, 0xe0, 0x60, 0x01, 0xd5, 0x08, 0x20, - 0x70, 0xbd, 0x00, 0x22, 0x10, 0x21, 0x30, 0x46, 0x01, 0xf0, 0x6c, 0xfe, - 0x08, 0x20, 0x04, 0xf0, 0x03, 0xf9, 0x08, 0xb1, 0x09, 0x20, 0x70, 0xbd, - 0xe0, 0x68, 0x04, 0xf0, 0xbc, 0xf8, 0x04, 0xf0, 0xdb, 0xf8, 0x00, 0xf0, - 0x1f, 0xf8, 0x13, 0xe0, 0xe5, 0x60, 0x01, 0x21, 0xe8, 0xb2, 0x04, 0xf0, - 0xfd, 0xf9, 0x04, 0xf0, 0x38, 0xfa, 0x00, 0xf0, 0x15, 0xf8, 0x00, 0x22, - 0x18, 0x21, 0x40, 0xf2, 0x7a, 0x60, 0x01, 0xf0, 0x4f, 0xfe, 0x00, 0x22, - 0x20, 0x21, 0x30, 0x46, 0x01, 0xf0, 0x4a, 0xfe, 0x00, 0x20, 0x70, 0xbd, - 0x68, 0x18, 0x00, 0x01, 0x00, 0x00, 0xc8, 0xc3, 0xc0, 0x01, 0x00, 0x45, - 0x98, 0xf1, 0x00, 0x20, 0xe0, 0x68, 0x80, 0x1c, 0x28, 0x21, 0x80, 0xb2, - 0x03, 0xf0, 0x46, 0xbf, 0x60, 0x68, 0xb0, 0xf9, 0x0c, 0x00, 0x70, 0x47, - 0x2d, 0xe9, 0xf0, 0x4f, 0xdf, 0xf8, 0x64, 0x04, 0x85, 0xb0, 0x80, 0x7a, - 0x00, 0xf0, 0x03, 0x00, 0x04, 0x90, 0x0c, 0x46, 0xdf, 0xf8, 0x58, 0x04, - 0x20, 0x60, 0x20, 0x46, 0x00, 0xf0, 0x8c, 0xf9, 0x05, 0x00, 0x40, 0xf0, - 0xc0, 0x80, 0x00, 0x26, 0x0f, 0xf2, 0x74, 0x4a, 0x04, 0x98, 0xf0, 0x40, - 0xc0, 0x07, 0x40, 0xf1, 0xb4, 0x80, 0x34, 0x20, 0x00, 0xfb, 0x06, 0xfb, - 0xdf, 0xf8, 0x34, 0x04, 0xdf, 0xf8, 0x30, 0x14, 0x0b, 0xeb, 0x00, 0x09, - 0x00, 0x20, 0x4b, 0xf8, 0x01, 0x00, 0xc9, 0xf8, 0x04, 0x00, 0x4f, 0xf4, - 0x08, 0x71, 0xdf, 0xf8, 0x08, 0x04, 0x01, 0xfb, 0x06, 0x00, 0x60, 0x60, - 0x00, 0x21, 0x81, 0x81, 0x01, 0x21, 0xc1, 0x81, 0x01, 0x82, 0x41, 0x82, - 0xff, 0xf7, 0x5e, 0xff, 0x60, 0x68, 0x00, 0x21, 0x20, 0xf8, 0x6e, 0x1f, - 0x41, 0x80, 0x32, 0x46, 0x21, 0x68, 0xb1, 0xf9, 0x24, 0x10, 0xfe, 0xf7, - 0x01, 0xff, 0x30, 0x46, 0x01, 0xf0, 0x4e, 0xff, 0x80, 0x46, 0x60, 0x68, - 0xa0, 0xf8, 0x6a, 0x80, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, 0x28, 0xff, - 0xdd, 0xe9, 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0x02, 0xaa, 0x00, 0x20, - 0x8d, 0xf8, 0x0a, 0x00, 0x01, 0x21, 0x30, 0x46, 0x05, 0xf0, 0x53, 0xff, - 0x20, 0x68, 0x90, 0xf8, 0x3a, 0x00, 0x3a, 0xf8, 0x10, 0x10, 0x00, 0xf0, - 0x79, 0xf8, 0x60, 0x8a, 0xe0, 0x82, 0x31, 0x46, 0x01, 0x20, 0x20, 0x82, - 0x00, 0xf0, 0xca, 0xf8, 0x05, 0x46, 0x02, 0x20, 0x20, 0x82, 0x31, 0x46, - 0x60, 0x8a, 0x00, 0x09, 0xe0, 0x82, 0x00, 0xf0, 0xc1, 0xf8, 0x05, 0xb9, - 0x05, 0x46, 0x20, 0x68, 0x90, 0xf8, 0x3a, 0x00, 0x47, 0x1c, 0x09, 0xe0, - 0x3a, 0xf8, 0x17, 0x10, 0x00, 0xf0, 0x5e, 0xf8, 0x01, 0x20, 0x00, 0xf0, - 0xb1, 0xf8, 0x05, 0xb9, 0x05, 0x46, 0x7f, 0x1c, 0x20, 0x68, 0x90, 0xf8, - 0x3b, 0x00, 0xbf, 0xb2, 0xb8, 0x42, 0xef, 0xd2, 0x07, 0x46, 0x12, 0xe0, - 0x20, 0x68, 0x90, 0xf8, 0x3b, 0x00, 0x02, 0xeb, 0xc0, 0x00, 0x00, 0xf1, - 0x70, 0x0c, 0x02, 0xeb, 0xc7, 0x02, 0xdc, 0xe9, 0x00, 0x01, 0x78, 0x32, - 0xc2, 0xe9, 0x00, 0x01, 0x39, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xa4, 0xf9, - 0x7f, 0x1c, 0xbf, 0xb2, 0x62, 0x68, 0x32, 0x2f, 0xe8, 0xdb, 0xa2, 0xf8, - 0x6c, 0x80, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, 0xef, 0xfe, 0x00, 0xf0, - 0x2e, 0xf8, 0x03, 0x20, 0x00, 0xf0, 0x84, 0xf8, 0x05, 0xb9, 0x05, 0x46, - 0x1d, 0xb9, 0x61, 0x68, 0x01, 0x20, 0xa1, 0xf8, 0x18, 0x02, 0x00, 0xf0, - 0x28, 0xf8, 0x30, 0xf8, 0x02, 0x1c, 0x00, 0xf0, 0x21, 0xf8, 0x00, 0xf0, - 0x1c, 0xf8, 0x00, 0xf0, 0x20, 0xf8, 0x30, 0xf8, 0x04, 0x1c, 0x00, 0xf0, - 0x19, 0xf8, 0x00, 0xf0, 0x14, 0xf8, 0x69, 0x46, 0x30, 0x46, 0x05, 0xf0, - 0xcf, 0xfe, 0x00, 0xf0, 0x0e, 0xf8, 0x64, 0x20, 0xc9, 0xf8, 0x04, 0x00, - 0xb6, 0x48, 0x4b, 0xf8, 0x00, 0x50, 0x76, 0x1c, 0x02, 0x2e, 0xff, 0xf4, - 0x43, 0xaf, 0x28, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x30, 0x46, - 0xfe, 0xf7, 0xc6, 0xbe, 0x30, 0x46, 0x05, 0xf0, 0x1d, 0xbf, 0x20, 0x68, - 0x90, 0xf8, 0x3b, 0x00, 0x0a, 0xeb, 0x40, 0x00, 0x70, 0x47, 0x2d, 0xe9, - 0xf0, 0x47, 0x0c, 0x46, 0xa8, 0x48, 0xa7, 0x49, 0x20, 0x60, 0x49, 0x89, - 0xc0, 0x8f, 0x08, 0x40, 0x00, 0xf0, 0x03, 0x08, 0x20, 0x46, 0x00, 0xf0, - 0xab, 0xf8, 0x05, 0x00, 0x37, 0xd1, 0x00, 0x26, 0xdf, 0xf8, 0x88, 0xa2, - 0x28, 0xfa, 0x06, 0xf0, 0xc0, 0x07, 0x2d, 0xd5, 0x00, 0xf0, 0xd0, 0xfb, - 0x34, 0x20, 0x00, 0xfb, 0x06, 0xf9, 0x09, 0xeb, 0x0a, 0x07, 0x00, 0x20, - 0x78, 0x60, 0x49, 0xf8, 0x0a, 0x00, 0x00, 0xf0, 0xda, 0xfb, 0x94, 0x48, - 0x4f, 0xf4, 0x08, 0x71, 0x01, 0xfb, 0x06, 0x00, 0x60, 0x60, 0x01, 0x21, - 0x81, 0x81, 0xc1, 0x81, 0x21, 0x82, 0x31, 0x46, 0x60, 0x8a, 0xe0, 0x82, - 0x00, 0xf0, 0x1c, 0xf8, 0x05, 0x46, 0xa0, 0x8a, 0xe0, 0x82, 0x31, 0x46, - 0x02, 0x20, 0x20, 0x82, 0x00, 0xf0, 0x14, 0xf8, 0x05, 0xb9, 0x05, 0x46, - 0x00, 0xf0, 0xaa, 0xfb, 0x64, 0x20, 0x78, 0x60, 0x49, 0xf8, 0x0a, 0x50, - 0x00, 0xf0, 0xb9, 0xfb, 0x76, 0x1c, 0x02, 0x2e, 0xca, 0xd3, 0x28, 0x46, - 0xbd, 0xe8, 0xf0, 0x87, 0x49, 0x03, 0x00, 0x80, 0x20, 0x82, 0x31, 0x46, - 0x20, 0x46, 0xad, 0xe0, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x0d, 0x46, - 0x7f, 0x48, 0x80, 0x4f, 0x28, 0x60, 0x4f, 0xf4, 0x08, 0x71, 0x79, 0x48, - 0x01, 0xfb, 0x08, 0x00, 0x68, 0x60, 0x00, 0xf0, 0x89, 0xfb, 0x34, 0x20, - 0x00, 0xfb, 0x08, 0xf6, 0xf4, 0x19, 0x00, 0x20, 0x60, 0x60, 0xf0, 0x51, - 0x00, 0xf0, 0x95, 0xfb, 0x28, 0x46, 0x00, 0xf0, 0x4d, 0xf8, 0x5f, 0xea, - 0x00, 0x09, 0x2b, 0xd1, 0x68, 0x68, 0xb0, 0xf8, 0x18, 0x12, 0x11, 0xb9, - 0x4f, 0xf0, 0x04, 0x09, 0x24, 0xe0, 0x30, 0xf9, 0x0c, 0x1f, 0x00, 0x29, - 0x02, 0xbf, 0x29, 0x68, 0xb1, 0xf8, 0x40, 0x10, 0x00, 0x29, 0x10, 0xd1, - 0x01, 0x21, 0x01, 0x80, 0x03, 0x21, 0x29, 0x82, 0x00, 0x21, 0x41, 0x80, - 0x01, 0x20, 0x00, 0xf0, 0x1e, 0xf8, 0x81, 0x46, 0x02, 0x20, 0x00, 0xf0, - 0x1a, 0xf8, 0xb9, 0xf1, 0x00, 0x0f, 0x0b, 0xd1, 0x09, 0xe0, 0x01, 0x21, - 0x29, 0x82, 0x00, 0x21, 0x41, 0x80, 0x41, 0x46, 0xa8, 0x8a, 0xe8, 0x82, - 0x28, 0x46, 0x00, 0xf0, 0x65, 0xf8, 0x81, 0x46, 0x00, 0xf0, 0x4c, 0xfb, - 0x64, 0x20, 0x60, 0x60, 0x46, 0xf8, 0x07, 0x90, 0x00, 0xf0, 0x5b, 0xfb, - 0x48, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x28, 0x82, 0x41, 0x46, 0x28, 0x46, - 0x54, 0xe0, 0x80, 0xb5, 0x53, 0x49, 0x56, 0x4a, 0x09, 0x6c, 0xa0, 0xfb, - 0x01, 0x01, 0x00, 0x23, 0x05, 0xf0, 0xc4, 0xfe, 0x04, 0xf0, 0x76, 0xfa, - 0xbd, 0xe8, 0x02, 0x40, 0x04, 0xf0, 0x68, 0xba, 0x70, 0xb5, 0x04, 0x46, - 0x00, 0x20, 0x02, 0xf0, 0x7b, 0xfd, 0x06, 0x46, 0x20, 0x68, 0x01, 0x88, - 0x0a, 0x25, 0x8e, 0x42, 0xb8, 0xbf, 0x0e, 0x46, 0x03, 0xdb, 0x40, 0x88, - 0xb0, 0x42, 0xb8, 0xbf, 0x06, 0x46, 0x10, 0x2e, 0x18, 0xdb, 0x40, 0xf2, - 0xee, 0x20, 0xff, 0xf7, 0xda, 0xff, 0x05, 0x46, 0xa6, 0xf1, 0x0f, 0x00, - 0xff, 0xf7, 0xd5, 0xff, 0x06, 0x46, 0x04, 0xf0, 0x53, 0xfa, 0x20, 0x83, - 0x20, 0x68, 0x41, 0x68, 0x69, 0x43, 0xb1, 0xfb, 0xf6, 0xf1, 0x61, 0x82, - 0x80, 0x68, 0x68, 0x43, 0xb0, 0xfb, 0xf6, 0xf0, 0xa0, 0x82, 0x00, 0x25, - 0x28, 0x46, 0x70, 0xbd, 0x70, 0xb5, 0x00, 0x24, 0x38, 0x4d, 0x31, 0x4e, - 0x4f, 0xf4, 0x08, 0x70, 0x22, 0x46, 0x01, 0x21, 0x00, 0xfb, 0x04, 0x60, - 0xfe, 0xf7, 0x16, 0xfd, 0x2b, 0x46, 0x00, 0x22, 0xe1, 0xb2, 0x00, 0x20, - 0x01, 0xf0, 0x7c, 0xfd, 0x64, 0x1c, 0x02, 0x2c, 0xee, 0xd3, 0x70, 0xbd, - 0x00, 0x01, 0x00, 0x45, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x00, 0x20, - 0x05, 0xf0, 0x5b, 0xff, 0x90, 0xb1, 0x29, 0x46, 0x00, 0x20, 0x05, 0xf0, - 0x5b, 0xff, 0x06, 0x46, 0x32, 0x46, 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, - 0xae, 0xf9, 0x21, 0x8a, 0x49, 0x1e, 0x21, 0x82, 0x09, 0xb2, 0x01, 0x29, - 0x03, 0xdb, 0x00, 0x28, 0xf2, 0xd0, 0x70, 0xbd, 0x03, 0x20, 0x70, 0xbd, - 0x18, 0x49, 0xc2, 0x07, 0x44, 0xbf, 0x01, 0x22, 0x0a, 0x82, 0x80, 0x07, - 0x44, 0xbf, 0x01, 0x20, 0xa1, 0xf8, 0x30, 0x02, 0x70, 0x47, 0x00, 0x00, - 0xa4, 0x70, 0x7d, 0x3f, 0x11, 0x49, 0xc2, 0x07, 0x44, 0xbf, 0x01, 0x22, - 0x4a, 0x82, 0x80, 0x07, 0x44, 0xbf, 0x01, 0x20, 0xa1, 0xf8, 0x32, 0x02, - 0x70, 0x47, 0x00, 0x00, 0x00, 0x24, 0x74, 0x49, 0x00, 0x00, 0x7a, 0x44, - 0x00, 0x00, 0x80, 0xbf, 0x02, 0x56, 0xfd, 0x37, 0x00, 0x00, 0x34, 0x44, - 0x00, 0xa0, 0x8c, 0x47, 0xcd, 0xcc, 0x4c, 0x3d, 0x01, 0x00, 0x80, 0x3f, - 0xff, 0xe6, 0xdb, 0x2e, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0x20, 0x41, - 0x24, 0x2b, 0x00, 0x20, 0x48, 0xad, 0x00, 0x20, 0x4c, 0x1f, 0x00, 0x20, - 0x48, 0x04, 0x00, 0x46, 0x78, 0x29, 0x00, 0x20, 0xdc, 0x2a, 0x00, 0x20, - 0x98, 0xf1, 0x00, 0x20, 0x80, 0x8d, 0x5b, 0x00, 0xbf, 0x12, 0x00, 0x01, - 0xd0, 0xb5, 0x44, 0x68, 0x0a, 0x46, 0xd4, 0xe9, 0x82, 0x67, 0x01, 0x20, - 0x00, 0x21, 0x05, 0xf0, 0x1b, 0xfd, 0x30, 0x43, 0x39, 0x43, 0xc4, 0xe9, - 0x82, 0x01, 0xd0, 0xbd, 0x42, 0x06, 0x7a, 0x06, 0x00, 0x00, 0x06, 0x00, - 0x0c, 0x00, 0x0f, 0x00, 0x15, 0x00, 0x1b, 0x00, 0x1e, 0x00, 0x24, 0x00, - 0x28, 0x00, 0x2f, 0x00, 0x32, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x41, 0x00, - 0x46, 0x00, 0x4b, 0x00, 0x52, 0x00, 0x56, 0x00, 0x5b, 0x00, 0x60, 0x00, - 0x65, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x73, 0x00, 0x79, 0x00, 0x7e, 0x00, - 0x84, 0x00, 0x91, 0x00, 0x96, 0x00, 0x9d, 0x00, 0xab, 0x00, 0xba, 0x00, - 0xc3, 0x00, 0xd3, 0x00, 0xdd, 0x00, 0xe7, 0x00, 0xf1, 0x00, 0x09, 0x01, - 0x15, 0x01, 0x23, 0x01, 0x32, 0x01, 0x55, 0x01, 0x6b, 0x01, 0x83, 0x01, - 0x9d, 0x01, 0xbe, 0x01, 0xe2, 0x01, 0x14, 0x02, 0x5a, 0x02, 0xd3, 0x02, - 0xff, 0xfc, 0xf9, 0xf6, 0xf4, 0xf1, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, - 0xfd, 0xfa, 0xf7, 0xfd, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xfd, 0xfa, 0xf7, - 0xf4, 0xf1, 0xee, 0xfd, 0xfa, 0xf7, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, - 0xff, 0xfd, 0xfa, 0xf7, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xfd, - 0xfb, 0xf8, 0xff, 0xfc, 0xf9, 0xf6, 0xf4, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, - 0xed, 0xea, 0xfd, 0xfa, 0xf7, 0xff, 0xfd, 0xfa, 0xf7, 0xf4, 0xfd, 0xfa, - 0xf7, 0xf4, 0xf1, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xec, 0xe9, 0xfe, 0xfb, - 0xf8, 0xf5, 0xff, 0xfc, 0xfa, 0xf7, 0xf4, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, - 0xfd, 0xfa, 0xf7, 0xf4, 0xf1, 0xfc, 0xf9, 0xf6, 0xf3, 0xff, 0xfc, 0xf9, - 0xf6, 0xf3, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xff, 0xfd, 0xfa, 0xf7, 0xf4, - 0xf1, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf1, - 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, 0xe7, 0xe4, 0xe2, 0xdf, - 0xdc, 0xfb, 0xf8, 0xf5, 0xf2, 0xf0, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf1, - 0xee, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xea, 0xe7, 0xe4, 0xe1, - 0xde, 0xdc, 0xd9, 0xfd, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xe9, 0xe6, - 0xe4, 0xe1, 0xde, 0xdb, 0xd9, 0xd6, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, - 0xec, 0xea, 0xe7, 0xfb, 0xf8, 0xf5, 0xf2, 0xf0, 0xed, 0xea, 0xe7, 0xe4, - 0xe1, 0xdf, 0xdc, 0xd9, 0xd6, 0xd4, 0xd1, 0xff, 0xfc, 0xf9, 0xf6, 0xf4, - 0xf1, 0xee, 0xeb, 0xe8, 0xe5, 0xfd, 0xfa, 0xf8, 0xf5, 0xf2, 0xef, 0xec, - 0xe9, 0xe6, 0xe4, 0xfd, 0xfa, 0xf7, 0xf4, 0xf2, 0xef, 0xec, 0xe9, 0xe6, - 0xe3, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, 0xeb, 0xe8, 0xe5, 0xe2, - 0xdf, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf, 0xcc, 0xca, 0xc7, 0xc4, 0xc2, - 0xbf, 0xfc, 0xf9, 0xf7, 0xf4, 0xf1, 0xee, 0xeb, 0xe8, 0xe5, 0xe3, 0xe0, - 0xdd, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xee, 0xeb, 0xe8, 0xe5, 0xe2, - 0xe0, 0xdd, 0xda, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, 0xea, 0xe8, - 0xe5, 0xe2, 0xdf, 0xdd, 0xda, 0xd7, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, - 0xee, 0xeb, 0xe8, 0xe5, 0xe2, 0xe0, 0xdd, 0xda, 0xd7, 0xd5, 0xd2, 0xcf, - 0xcd, 0xca, 0xc7, 0xc5, 0xc2, 0xc0, 0xbd, 0xba, 0xb8, 0xb5, 0xb3, 0xb0, - 0xae, 0xab, 0xa9, 0xa6, 0xa4, 0xff, 0xfc, 0xf9, 0xf6, 0xf3, 0xf0, 0xed, - 0xea, 0xe8, 0xe5, 0xe2, 0xdf, 0xdc, 0xda, 0xd7, 0xd4, 0xd2, 0xcf, 0xcc, - 0xca, 0xc7, 0xc4, 0xfa, 0xf7, 0xf4, 0xf1, 0xef, 0xec, 0xe9, 0xe6, 0xe3, - 0xe0, 0xde, 0xdb, 0xd8, 0xd6, 0xd3, 0xd0, 0xcd, 0xcb, 0xc8, 0xc6, 0xc3, - 0xc0, 0xbe, 0xbb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xe9, 0xe7, 0xe4, 0xe1, - 0xde, 0xdc, 0xd9, 0xd6, 0xd3, 0xd1, 0xce, 0xcb, 0xc9, 0xc6, 0xc3, 0xc1, - 0xbe, 0xbc, 0xb9, 0xb7, 0xb4, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xec, 0xe9, - 0xe6, 0xe3, 0xe0, 0xde, 0xdb, 0xd8, 0xd5, 0xd3, 0xd0, 0xcd, 0xcb, 0xc8, - 0xc6, 0xc3, 0xc0, 0xbe, 0xbb, 0xb9, 0xb6, 0xb4, 0xb1, 0xaf, 0xac, 0xaa, - 0xa7, 0xa5, 0xf6, 0xf3, 0xf0, 0xee, 0xeb, 0xe8, 0xe5, 0xe2, 0xe0, 0xdd, - 0xda, 0xd7, 0xd5, 0xd2, 0xcf, 0xcd, 0xca, 0xc7, 0xc5, 0xc2, 0xbf, 0xbd, - 0xba, 0xb8, 0xb5, 0xb3, 0xb0, 0xae, 0xab, 0xa9, 0xa6, 0xa4, 0xa2, 0x9f, - 0x9d, 0x9a, 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, 0xe7, 0xe4, - 0xe2, 0xdf, 0xdc, 0xd9, 0xd7, 0xd4, 0xd1, 0xcf, 0xcc, 0xc9, 0xc7, 0xc4, - 0xc1, 0xbf, 0xbc, 0xba, 0xb7, 0xb5, 0xb2, 0xb0, 0xad, 0xab, 0xa8, 0xa6, - 0xa3, 0xa1, 0x9f, 0x9c, 0x9a, 0x97, 0x95, 0x93, 0x90, 0x8e, 0x8c, 0x8a, - 0x87, 0x85, 0x83, 0x81, 0xfe, 0xfb, 0xf8, 0xf5, 0xf3, 0xf0, 0xed, 0xea, - 0xe7, 0xe4, 0xe2, 0xdf, 0xdc, 0xd9, 0xd7, 0xd4, 0xd1, 0xcf, 0xcc, 0xc9, - 0xc7, 0xc4, 0xc1, 0xbf, 0xbc, 0xba, 0xb7, 0xb5, 0xb2, 0xb0, 0xad, 0xab, - 0xa8, 0xa6, 0xa3, 0xa1, 0x9f, 0x9c, 0x9a, 0x97, 0x95, 0x93, 0x90, 0x8e, - 0x8c, 0x8a, 0x87, 0x85, 0x83, 0x81, 0x7e, 0x7c, 0x7a, 0x78, 0x76, 0x73, - 0x71, 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61, 0x5f, 0x5d, 0x5b, - 0x59, 0x57, 0xff, 0xfc, 0xfa, 0xf7, 0xf4, 0xf1, 0xee, 0xeb, 0xe8, 0xe6, - 0xe3, 0xe0, 0xdd, 0xda, 0xd8, 0xd5, 0xd2, 0xd0, 0xcd, 0xca, 0xc8, 0xc5, - 0xc3, 0xc0, 0xbd, 0xbb, 0xb8, 0xb6, 0xb3, 0xb1, 0xae, 0xac, 0xa9, 0xa7, - 0xa4, 0xa2, 0xa0, 0x9d, 0x9b, 0x98, 0x96, 0x94, 0x91, 0x8f, 0x8d, 0x8b, - 0x88, 0x86, 0x84, 0x82, 0x7f, 0x7d, 0x7b, 0x79, 0x77, 0x74, 0x72, 0x70, - 0x6e, 0x6c, 0x6a, 0x68, 0x66, 0x64, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, - 0x56, 0x54, 0x52, 0x50, 0x4e, 0x4c, 0x4a, 0x48, 0x46, 0x44, 0x42, 0x41, - 0x3f, 0x3d, 0x3b, 0x39, 0x37, 0x36, 0x34, 0x32, 0x30, 0x2f, 0x2d, 0x2b, - 0x29, 0x28, 0x26, 0x24, 0x23, 0x21, 0x1f, 0x1e, 0x1c, 0x1a, 0x19, 0x17, - 0x15, 0x14, 0x12, 0x11, 0x0f, 0x0e, 0x0c, 0x0b, 0x09, 0x07, 0x06, 0x04, - 0x03, 0x01, 0x00, 0xfe, 0xfb, 0xf8, 0xf5, 0xf2, 0xef, 0xec, 0xea, 0xe7, - 0xe4, 0xe1, 0xde, 0xdc, 0xd9, 0xd6, 0xd3, 0xd1, 0xce, 0xcb, 0xc9, 0xc6, - 0xc4, 0xc1, 0xbe, 0xbc, 0xb9, 0xb7, 0xb4, 0xb2, 0xaf, 0xad, 0xaa, 0xa8, - 0xa5, 0xa3, 0xa1, 0x9e, 0x9c, 0x99, 0x97, 0x95, 0x92, 0x90, 0x8e, 0x8b, - 0x89, 0x87, 0x85, 0x82, 0x80, 0x7e, 0x7c, 0x7a, 0x77, 0x75, 0x73, 0x71, - 0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x64, 0x62, 0x60, 0x5e, 0x5c, 0x5a, 0x58, - 0x56, 0x54, 0x52, 0x50, 0x4f, 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, - 0x3f, 0x3e, 0x3c, 0x3a, 0x38, 0x36, 0x35, 0x33, 0x31, 0x2f, 0x2e, 0x2c, - 0x2a, 0x28, 0x27, 0x25, 0x23, 0x22, 0x20, 0x1e, 0x1d, 0x1b, 0x19, 0x18, - 0x16, 0x15, 0x13, 0x11, 0x10, 0x0e, 0x0d, 0x0b, 0x0a, 0x08, 0x07, 0x00, - 0x70, 0xb5, 0x86, 0xb0, 0x05, 0xf0, 0xac, 0xfe, 0xdf, 0xf8, 0x14, 0x19, - 0xdf, 0xf8, 0x14, 0x49, 0x00, 0x20, 0x08, 0x60, 0x20, 0x70, 0x60, 0x70, - 0xa0, 0x71, 0x60, 0x71, 0x20, 0x61, 0xe0, 0x61, 0x20, 0x72, 0x20, 0x71, - 0x00, 0x21, 0x04, 0xf1, 0x0c, 0x00, 0xa1, 0x70, 0x01, 0x60, 0xe1, 0x70, - 0xa1, 0x62, 0x21, 0x62, 0x04, 0xf5, 0x45, 0x75, 0x4f, 0xf4, 0xfc, 0x61, - 0x28, 0x46, 0x00, 0xf0, 0x78, 0xf9, 0x64, 0x21, 0x04, 0xf1, 0x30, 0x00, - 0x00, 0xf0, 0x73, 0xf9, 0x00, 0x20, 0xad, 0xa1, 0x54, 0x22, 0x02, 0xfb, - 0x00, 0x43, 0x03, 0xf5, 0x45, 0x76, 0x40, 0x1c, 0x03, 0xf5, 0x5a, 0x73, - 0x17, 0x28, 0x73, 0x61, 0xf1, 0x64, 0xf4, 0xd3, 0x02, 0xfb, 0x00, 0x40, - 0x00, 0xf5, 0x45, 0x70, 0x00, 0x22, 0x42, 0x61, 0xc1, 0x64, 0x65, 0x62, - 0xe2, 0x62, 0x04, 0xf1, 0x94, 0x05, 0x4f, 0xf4, 0xa0, 0x71, 0x28, 0x46, - 0x00, 0xf0, 0x55, 0xf9, 0x00, 0x20, 0x00, 0x23, 0x04, 0xeb, 0x00, 0x11, - 0x01, 0xf1, 0x94, 0x02, 0x40, 0x1c, 0xa4, 0x31, 0x13, 0x28, 0x13, 0x70, - 0x51, 0x60, 0xf5, 0xd3, 0x04, 0xeb, 0x00, 0x10, 0x00, 0xf8, 0x94, 0x3f, - 0x43, 0x60, 0x65, 0x61, 0x00, 0xf0, 0xea, 0xfb, 0x00, 0xf0, 0x5c, 0xfd, - 0x03, 0x21, 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, 0x80, 0x21, 0x02, 0x91, - 0x4f, 0xf6, 0xff, 0x71, 0xdf, 0xf8, 0x64, 0x08, 0x01, 0x90, 0x00, 0x91, - 0x00, 0xf5, 0xfe, 0x72, 0x18, 0x23, 0x00, 0x21, 0x0f, 0xf2, 0xc1, 0x30, - 0x00, 0xf0, 0x0d, 0xfe, 0x05, 0xaa, 0x0f, 0xf2, 0x14, 0x01, 0x18, 0x20, - 0x00, 0xf0, 0xbe, 0xfe, 0x01, 0xf0, 0x74, 0xf8, 0xc0, 0x46, 0xc0, 0x46, - 0x06, 0xb0, 0x70, 0xbd, 0x75, 0x43, 0x2f, 0x4f, 0x53, 0x2d, 0x49, 0x49, - 0x20, 0x49, 0x64, 0x6c, 0x65, 0x00, 0x00, 0x00, 0x38, 0xb5, 0x00, 0xf0, - 0x31, 0xf8, 0x1e, 0xd1, 0x05, 0xf0, 0x9a, 0xfe, 0x05, 0x46, 0x20, 0x78, - 0x08, 0xb1, 0x40, 0x1e, 0x20, 0x70, 0x20, 0x78, 0x61, 0x78, 0x08, 0x43, - 0x11, 0xd1, 0x00, 0xf0, 0x2c, 0xf9, 0xe0, 0x78, 0xa2, 0x78, 0x04, 0xeb, - 0x80, 0x01, 0x90, 0x42, 0x09, 0x6b, 0xa1, 0x62, 0x07, 0xd0, 0x88, 0x6b, - 0x40, 0x1c, 0x88, 0x63, 0x20, 0x69, 0x40, 0x1c, 0x20, 0x61, 0x05, 0xf0, - 0x9a, 0xfe, 0x28, 0x46, 0x15, 0xe1, 0x31, 0xbd, 0x10, 0xb5, 0x00, 0xf0, - 0x0d, 0xf8, 0x0a, 0xd1, 0x05, 0xf0, 0x76, 0xfe, 0x21, 0x78, 0x21, 0xb9, - 0x61, 0x78, 0xff, 0x29, 0x1c, 0xbf, 0x49, 0x1c, 0x61, 0x70, 0x00, 0xf0, - 0xe3, 0xbe, 0x10, 0xbd, 0xdf, 0xf8, 0xb4, 0x47, 0x60, 0x79, 0x01, 0x28, - 0x70, 0x47, 0x10, 0xb5, 0xff, 0xf7, 0xf8, 0xff, 0x10, 0xd1, 0x05, 0xf0, - 0x61, 0xfe, 0x21, 0x78, 0x51, 0xb9, 0x61, 0x78, 0x41, 0xb1, 0x49, 0x1e, - 0x61, 0x70, 0xc9, 0xb2, 0x21, 0xb9, 0x80, 0xf3, 0x11, 0x88, 0xbd, 0xe8, - 0x10, 0x40, 0xcf, 0xe0, 0x00, 0xf0, 0xc8, 0xbe, 0x10, 0xbd, 0x10, 0xb5, - 0xdf, 0xf8, 0x7c, 0x47, 0x60, 0x79, 0x60, 0xb9, 0x00, 0xf0, 0xe7, 0xf8, - 0xe0, 0x78, 0xa0, 0x70, 0x04, 0xeb, 0x80, 0x00, 0x00, 0x6b, 0xa0, 0x62, - 0x20, 0x62, 0xbd, 0xe8, 0x10, 0x40, 0x05, 0xf0, 0x48, 0xbe, 0x10, 0xbd, - 0x70, 0xb5, 0x05, 0xf0, 0x14, 0xfe, 0x05, 0xf0, 0x39, 0xfe, 0xdf, 0xf8, - 0x4c, 0x17, 0xdf, 0xf8, 0x4c, 0x47, 0x0a, 0x68, 0x52, 0x1c, 0x0a, 0x60, - 0x80, 0xf3, 0x11, 0x88, 0x60, 0x79, 0x01, 0x28, 0x35, 0xd1, 0xe0, 0x79, - 0x38, 0xb1, 0x02, 0x28, 0x01, 0xd0, 0x30, 0xd3, 0x01, 0xe0, 0x01, 0x20, - 0x00, 0xe0, 0x00, 0x20, 0xe0, 0x71, 0xe6, 0x6a, 0x12, 0xe0, 0x69, 0x77, - 0x29, 0x7f, 0x09, 0x07, 0x0b, 0xd4, 0x06, 0xf1, 0x34, 0x01, 0x22, 0x79, - 0x8b, 0x78, 0x1a, 0x43, 0x22, 0x71, 0x0a, 0x78, 0x49, 0x78, 0x12, 0x19, - 0x13, 0x7b, 0x19, 0x43, 0x11, 0x73, 0x2e, 0x68, 0x80, 0xf3, 0x11, 0x88, - 0x06, 0xf1, 0x14, 0x05, 0xa8, 0x7f, 0x18, 0x28, 0x11, 0xd0, 0x05, 0xf0, - 0x07, 0xfe, 0xa9, 0x69, 0x00, 0x29, 0xf2, 0xd0, 0x49, 0x1e, 0xa9, 0x61, - 0xef, 0xd1, 0x29, 0x7f, 0x37, 0x22, 0x11, 0x42, 0x1d, 0xbf, 0x01, 0xf0, - 0xc8, 0x01, 0x29, 0x77, 0x01, 0x21, 0x00, 0x21, 0xd5, 0xe7, 0x70, 0xbd, - 0xf8, 0xb5, 0x85, 0x7a, 0x0f, 0xf2, 0x38, 0x14, 0xdf, 0xf8, 0xc0, 0x76, - 0x2e, 0x5d, 0x35, 0x18, 0x4f, 0xf0, 0x00, 0x0e, 0xed, 0x7a, 0x2c, 0x5d, - 0x04, 0xeb, 0xc6, 0x05, 0xed, 0xb2, 0x07, 0xeb, 0x85, 0x04, 0x24, 0x6b, - 0x04, 0xf1, 0x20, 0x0c, 0xcc, 0xf8, 0x00, 0x10, 0xcc, 0xf8, 0x0c, 0xe0, - 0x8c, 0xf8, 0x11, 0x30, 0x9c, 0xf8, 0x10, 0x10, 0x91, 0x43, 0x8c, 0xf8, - 0x10, 0x10, 0x9c, 0xf8, 0x10, 0x10, 0x09, 0x07, 0x0a, 0xd4, 0x39, 0x79, - 0x9c, 0xf8, 0x16, 0x20, 0x11, 0x43, 0x39, 0x71, 0xf1, 0x19, 0x9c, 0xf8, - 0x15, 0x30, 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, 0x01, 0x46, 0x20, 0x46, - 0x00, 0xf0, 0x26, 0xf8, 0x28, 0x46, 0xf2, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, - 0x60, 0x16, 0x0a, 0x6a, 0x42, 0xf8, 0x1c, 0x0f, 0x13, 0x7e, 0x52, 0x7e, - 0x1b, 0x18, 0xdc, 0x7a, 0x22, 0x43, 0xda, 0x72, 0x0b, 0x6a, 0x82, 0x7a, - 0x93, 0xf8, 0x36, 0x30, 0x1a, 0x43, 0x82, 0x72, 0x08, 0x6a, 0x10, 0xf8, - 0x34, 0x2f, 0x44, 0x78, 0x52, 0x18, 0x13, 0x7b, 0xa3, 0x43, 0x13, 0x73, - 0x04, 0xd1, 0x0a, 0x79, 0x80, 0x78, 0x22, 0xea, 0x00, 0x00, 0x08, 0x71, - 0x10, 0xbd, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x10, 0xb5, 0x10, 0xf8, - 0x34, 0x2f, 0x44, 0x78, 0x52, 0x18, 0xd3, 0x7a, 0xa3, 0x43, 0xd3, 0x72, - 0x04, 0xd1, 0x8a, 0x7a, 0x80, 0x78, 0x22, 0xea, 0x00, 0x00, 0x88, 0x72, - 0x10, 0xbd, 0x00, 0x21, 0x81, 0x72, 0x0b, 0x30, 0x04, 0x21, 0x01, 0xf0, - 0x2f, 0xb8, 0x00, 0x29, 0x18, 0xbf, 0x01, 0xf0, 0x2b, 0xb8, 0x70, 0x47, - 0x38, 0xb5, 0x05, 0xf0, 0x81, 0xfd, 0xdf, 0xf8, 0xe0, 0x55, 0x69, 0x78, - 0x04, 0x46, 0x28, 0x78, 0x08, 0x43, 0x11, 0xd1, 0x00, 0xf0, 0x15, 0xf8, - 0xe8, 0x78, 0xaa, 0x78, 0x05, 0xeb, 0x80, 0x01, 0x90, 0x42, 0x09, 0x6b, - 0xa9, 0x62, 0x07, 0xd0, 0x88, 0x6b, 0x40, 0x1c, 0x88, 0x63, 0x28, 0x69, - 0x40, 0x1c, 0x28, 0x61, 0x05, 0xf0, 0x7f, 0xfd, 0x20, 0x46, 0xbd, 0xe8, - 0x32, 0x40, 0x05, 0xf0, 0x69, 0xbd, 0xdf, 0xf8, 0xa4, 0x05, 0x0f, 0xf2, - 0x14, 0x01, 0x02, 0x79, 0x52, 0x5c, 0x13, 0x18, 0x1b, 0x7b, 0x59, 0x5c, - 0x01, 0xeb, 0xc2, 0x01, 0xc1, 0x70, 0x70, 0x47, 0x00, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x06, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x07, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x06, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x04, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x05, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x01, 0x00, 0x03, 0x00, 0x01, 0x00, 0x02, 0x00, 0x01, 0x00, - 0x80, 0xb5, 0x05, 0xf0, 0xd3, 0xfc, 0xdf, 0xf8, 0x84, 0x14, 0xca, 0x69, - 0x52, 0x1c, 0xca, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x05, 0xf0, 0x60, 0xfc, - 0xf3, 0xe7, 0x2d, 0xe9, 0xf8, 0x43, 0x04, 0x46, 0x0f, 0x46, 0x91, 0x46, - 0x98, 0x46, 0x05, 0xf0, 0xc1, 0xfc, 0xdf, 0xf8, 0x60, 0x54, 0x6e, 0x6a, - 0x00, 0x2e, 0x58, 0xd0, 0x71, 0x69, 0x69, 0x62, 0x80, 0xf3, 0x11, 0x88, - 0x37, 0x60, 0x00, 0x20, 0x06, 0xf1, 0x30, 0x07, 0xbc, 0x70, 0x38, 0x70, - 0x78, 0x70, 0xf0, 0x62, 0x01, 0x22, 0x09, 0x98, 0x70, 0x60, 0x04, 0xf0, - 0x07, 0x01, 0x08, 0x98, 0xf0, 0x60, 0xc6, 0xf8, 0x08, 0x90, 0x0a, 0x98, - 0x30, 0x82, 0xa6, 0xf8, 0x12, 0x80, 0x00, 0x20, 0xf8, 0x71, 0xf9, 0x70, - 0xe0, 0x08, 0x38, 0x71, 0x02, 0xfa, 0x00, 0xf0, 0xb8, 0x71, 0x02, 0xfa, - 0x01, 0xf0, 0x78, 0x71, 0x00, 0x20, 0xf0, 0x61, 0x70, 0x62, 0x30, 0x62, - 0xb8, 0x60, 0x38, 0x61, 0xf8, 0x60, 0x78, 0x61, 0xb8, 0x61, 0x4d, 0xa0, - 0xf8, 0x61, 0x00, 0x20, 0x38, 0x62, 0x30, 0x46, 0x05, 0xf0, 0x5f, 0xfc, - 0x05, 0xf0, 0x86, 0xfc, 0x05, 0xeb, 0x84, 0x01, 0x0e, 0x63, 0x80, 0xf3, - 0x11, 0x88, 0x30, 0x46, 0x05, 0xf0, 0x10, 0xfc, 0x05, 0xf0, 0x7c, 0xfc, - 0xe9, 0x6a, 0x71, 0x61, 0x00, 0x21, 0xb1, 0x61, 0xe9, 0x6a, 0x01, 0xb1, - 0x8e, 0x61, 0xee, 0x62, 0x29, 0x79, 0xba, 0x79, 0x11, 0x43, 0x29, 0x71, - 0x39, 0x79, 0x7b, 0x79, 0x49, 0x19, 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, - 0xa9, 0x79, 0x49, 0x1c, 0xa9, 0x71, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x20, - 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x42, 0x20, 0xbd, 0xe8, 0xf2, 0x83, - 0x00, 0x00, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x05, 0x46, 0x88, 0x46, - 0x28, 0x78, 0x05, 0x28, 0x17, 0x46, 0x1c, 0x46, 0x02, 0xd0, 0x00, 0xf0, - 0x7c, 0xfa, 0x36, 0xe0, 0x38, 0x06, 0x46, 0xbf, 0x07, 0xf0, 0x7f, 0x07, - 0x01, 0x26, 0x00, 0x26, 0x00, 0x20, 0x20, 0x70, 0x05, 0xf0, 0x46, 0xfc, - 0x03, 0x2f, 0x24, 0xd8, 0xdf, 0xe8, 0x07, 0xf0, 0x15, 0x1b, 0x02, 0x0c, - 0x29, 0x89, 0x08, 0xea, 0x01, 0x07, 0x47, 0x45, 0x08, 0xd0, 0x70, 0x21, - 0x21, 0x70, 0x80, 0xf3, 0x11, 0x88, 0x1b, 0xe0, 0x29, 0x89, 0x18, 0xea, - 0x01, 0x07, 0xf6, 0xd0, 0x00, 0x2e, 0xf6, 0xd0, 0xb9, 0x43, 0x29, 0x81, - 0xf3, 0xe7, 0x29, 0x89, 0x28, 0xea, 0x01, 0x07, 0x47, 0x45, 0xec, 0xd1, - 0x03, 0xe0, 0x29, 0x89, 0x38, 0xea, 0x01, 0x07, 0xe7, 0xd0, 0x00, 0x2e, - 0xe7, 0xd0, 0x39, 0x43, 0xef, 0xe7, 0x80, 0xf3, 0x11, 0x88, 0x6f, 0x20, - 0x00, 0x27, 0x20, 0x70, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, - 0xdf, 0xf8, 0x08, 0x73, 0x06, 0x46, 0x38, 0x78, 0x0c, 0x46, 0x10, 0xb1, - 0x10, 0x20, 0x00, 0xf0, 0xb2, 0xbd, 0x05, 0xf0, 0x0b, 0xfc, 0xb9, 0x69, - 0x0d, 0x00, 0x0c, 0xd0, 0x49, 0x68, 0xb9, 0x61, 0x05, 0x21, 0x29, 0x70, - 0x2e, 0x81, 0x00, 0x21, 0x69, 0x60, 0x06, 0xa1, 0xe9, 0x60, 0x80, 0xf3, - 0x11, 0x88, 0x00, 0x20, 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x72, 0x20, - 0xff, 0xe7, 0x20, 0x70, 0x28, 0x46, 0xf2, 0xbd, 0x3f, 0x00, 0x00, 0x00, - 0x2d, 0xe9, 0xf8, 0x4f, 0x86, 0xb0, 0xdf, 0xf8, 0x3c, 0x65, 0x10, 0x9d, - 0x04, 0x46, 0x30, 0x78, 0x8a, 0x46, 0x93, 0x46, 0x08, 0xb1, 0x02, 0x20, - 0x7a, 0xe0, 0x70, 0x78, 0x08, 0xb1, 0x0d, 0x20, 0x76, 0xe0, 0x20, 0x78, - 0x05, 0x28, 0x18, 0xbf, 0x01, 0x20, 0x71, 0xd1, 0x5f, 0xea, 0x0b, 0x60, - 0x46, 0xbf, 0x0b, 0xf0, 0x7f, 0x0b, 0x4f, 0xf0, 0x01, 0x08, 0x4f, 0xf0, - 0x00, 0x08, 0x05, 0xf0, 0xd1, 0xfb, 0xbb, 0xf1, 0x03, 0x0f, 0x81, 0x46, - 0x5f, 0xd8, 0xdf, 0xe8, 0x0b, 0xf0, 0x33, 0x39, 0x02, 0x2a, 0x20, 0x89, - 0x0a, 0xea, 0x00, 0x07, 0x57, 0x45, 0x26, 0xd0, 0x06, 0x98, 0x00, 0x90, - 0x5b, 0x46, 0x52, 0x46, 0x01, 0xa9, 0x20, 0x46, 0x00, 0xf0, 0xae, 0xf8, - 0x00, 0xf0, 0x30, 0xf9, 0xff, 0xf7, 0x34, 0xfe, 0x05, 0xf0, 0xb6, 0xfb, - 0x81, 0x46, 0x30, 0x6a, 0x28, 0x30, 0x47, 0x7a, 0x57, 0xb3, 0x00, 0x21, - 0x41, 0x72, 0x01, 0xa8, 0x00, 0xf0, 0x0b, 0xf9, 0x31, 0x6a, 0x00, 0x20, - 0x81, 0xf8, 0x30, 0x00, 0x00, 0xf0, 0x1c, 0xf9, 0x02, 0x2f, 0x14, 0xbf, - 0x0a, 0x20, 0x0e, 0x20, 0x36, 0xe0, 0x20, 0x89, 0x1a, 0xea, 0x00, 0x07, - 0xd8, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, 0x10, 0xd0, 0xb8, 0x43, 0x0d, 0xe0, - 0x20, 0x89, 0x2a, 0xea, 0x00, 0x07, 0x57, 0x45, 0xce, 0xd1, 0x03, 0xe0, - 0x20, 0x89, 0x3a, 0xea, 0x00, 0x07, 0xc9, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, - 0x01, 0xd0, 0x38, 0x43, 0x20, 0x81, 0x30, 0x6a, 0x07, 0x85, 0x0d, 0xe0, - 0x07, 0x88, 0xb8, 0xf1, 0x00, 0x0f, 0x09, 0xd0, 0xbb, 0xf1, 0x01, 0x0f, - 0x0e, 0xd9, 0xab, 0xf1, 0x02, 0x00, 0x01, 0x28, 0x0d, 0xd8, 0x20, 0x89, - 0xb8, 0x43, 0x20, 0x81, 0x00, 0xf0, 0xec, 0xf8, 0x00, 0x20, 0x28, 0x70, - 0x38, 0x46, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x20, 0x89, 0x38, 0x43, - 0xf3, 0xe7, 0x00, 0xf0, 0xe1, 0xf8, 0x6f, 0x20, 0x28, 0x70, 0x00, 0x20, - 0xf3, 0xe7, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0f, 0x46, - 0x20, 0x78, 0x05, 0x28, 0x16, 0x46, 0x1d, 0x46, 0x18, 0xbf, 0x01, 0x20, - 0x3a, 0xd1, 0x05, 0xf0, 0x59, 0xfb, 0x80, 0x46, 0x16, 0xb1, 0x01, 0x2e, - 0x06, 0xd0, 0x08, 0xe0, 0x20, 0x89, 0xb8, 0x43, 0x20, 0x81, 0x00, 0x27, - 0x66, 0x68, 0x13, 0xe0, 0x20, 0x89, 0x38, 0x43, 0xf8, 0xe7, 0x80, 0xf3, - 0x11, 0x88, 0x71, 0x20, 0x26, 0xe0, 0x30, 0x8a, 0x21, 0x89, 0x01, 0x40, - 0x81, 0x42, 0x06, 0xd1, 0x00, 0x22, 0x30, 0x46, 0x00, 0xf0, 0x7f, 0xf8, - 0x01, 0x28, 0x08, 0xbf, 0x01, 0x27, 0x36, 0x68, 0xde, 0xb1, 0xb0, 0x7c, - 0x03, 0x28, 0x12, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x08, 0x0d, 0x02, 0x03, - 0xe9, 0xe7, 0x20, 0x89, 0x31, 0x8a, 0x01, 0x40, 0xf1, 0xd0, 0xe9, 0xe7, - 0x30, 0x8a, 0x21, 0x89, 0x20, 0xea, 0x01, 0x01, 0xe2, 0xe7, 0x20, 0x89, - 0x31, 0x8a, 0x81, 0x43, 0xf4, 0xe7, 0x00, 0xf0, 0x4e, 0xfa, 0x6f, 0x20, - 0x28, 0x70, 0x00, 0x20, 0x0c, 0xe0, 0x00, 0xf0, 0x48, 0xfa, 0x0f, 0xb1, - 0xff, 0xf7, 0x94, 0xfd, 0x05, 0xf0, 0x16, 0xfb, 0x24, 0x89, 0x80, 0xf3, - 0x11, 0x88, 0x00, 0x20, 0x28, 0x70, 0x20, 0x46, 0xbd, 0xe8, 0xf0, 0x81, - 0x70, 0xb5, 0xdf, 0xf8, 0x78, 0x43, 0x25, 0x6a, 0x95, 0xf8, 0x30, 0x60, - 0x46, 0xf0, 0x20, 0x06, 0x85, 0xf8, 0x30, 0x60, 0x00, 0x25, 0x26, 0x6a, - 0x86, 0xf8, 0x31, 0x50, 0x25, 0x6a, 0x04, 0x9e, 0xee, 0x62, 0x69, 0x62, - 0x0a, 0x82, 0x8b, 0x74, 0x22, 0x6a, 0x8a, 0x60, 0x43, 0x68, 0x0b, 0x60, - 0xc8, 0x60, 0x00, 0x23, 0x4b, 0x60, 0x43, 0x68, 0x03, 0xb1, 0x59, 0x60, - 0x41, 0x60, 0x02, 0xf1, 0x34, 0x00, 0x01, 0x78, 0x43, 0x78, 0x09, 0x19, - 0x0a, 0x7b, 0x9a, 0x43, 0x0a, 0x73, 0x04, 0xd1, 0x21, 0x79, 0x80, 0x78, - 0x21, 0xea, 0x00, 0x00, 0x20, 0x71, 0x70, 0xbd, 0x70, 0xb5, 0x27, 0x4c, - 0x04, 0xf5, 0xea, 0x75, 0x4f, 0xf4, 0xa0, 0x71, 0x28, 0x46, 0xff, 0xf7, - 0x4e, 0xfd, 0x00, 0x20, 0x23, 0xa1, 0x00, 0x26, 0x04, 0xeb, 0x00, 0x12, - 0x02, 0xf5, 0xea, 0x73, 0x40, 0x1c, 0x02, 0xf5, 0xf2, 0x72, 0x13, 0x28, - 0x1e, 0x70, 0x5a, 0x60, 0xd9, 0x60, 0xf3, 0xd3, 0x04, 0xeb, 0x00, 0x10, - 0x00, 0xf5, 0xea, 0x70, 0x06, 0x70, 0x46, 0x60, 0xc1, 0x60, 0xa5, 0x61, - 0x70, 0xbd, 0x10, 0xb5, 0x83, 0x68, 0x28, 0x33, 0x00, 0x24, 0x19, 0x80, - 0x5c, 0x60, 0x5a, 0x72, 0x19, 0x7a, 0x01, 0xf0, 0xdf, 0x01, 0x19, 0x72, - 0x19, 0x7a, 0x61, 0xb9, 0xdf, 0xf8, 0xc0, 0x12, 0x9c, 0x7b, 0x0a, 0x79, - 0x22, 0x43, 0x0a, 0x71, 0x01, 0x24, 0x1a, 0x7b, 0x5b, 0x7b, 0x51, 0x18, - 0x0a, 0x7b, 0x1a, 0x43, 0x0a, 0x73, 0x00, 0xf0, 0x02, 0xf8, 0x20, 0x46, - 0x10, 0xbd, 0x41, 0x68, 0x02, 0x68, 0x21, 0xb9, 0xc1, 0x68, 0x4a, 0x60, - 0x22, 0xb1, 0x00, 0x21, 0x01, 0xe0, 0x0a, 0x60, 0x02, 0xb1, 0x51, 0x60, - 0x80, 0x68, 0x00, 0x21, 0x41, 0x62, 0x70, 0x47, 0x90, 0xf3, 0x00, 0x20, - 0x20, 0xbd, 0x00, 0x20, 0x3f, 0x00, 0x00, 0x00, 0x68, 0x7a, 0x00, 0x20, - 0x48, 0x46, 0x05, 0xf0, 0x8d, 0xba, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, - 0x68, 0x62, 0x04, 0x46, 0x30, 0x78, 0x88, 0x46, 0x08, 0xb1, 0x00, 0x20, - 0x2e, 0xe0, 0x05, 0xf0, 0x7b, 0xfa, 0x71, 0x69, 0x0f, 0x00, 0x1c, 0xbf, - 0x49, 0x68, 0x71, 0x61, 0x05, 0xf0, 0x7a, 0xfa, 0x1f, 0xb3, 0x05, 0xf0, - 0x71, 0xfa, 0xdf, 0xf8, 0xb4, 0x15, 0x0a, 0x68, 0x15, 0x00, 0x16, 0xd0, - 0x12, 0x68, 0x0a, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x6c, 0x60, 0x04, 0xeb, - 0x88, 0x00, 0xa8, 0x60, 0xec, 0x60, 0x2c, 0x61, 0xa5, 0xf8, 0x14, 0x80, - 0x00, 0x20, 0xe8, 0x82, 0x02, 0x20, 0x38, 0x70, 0x00, 0x20, 0x38, 0x81, - 0x7d, 0x60, 0x38, 0x46, 0xff, 0xf7, 0xc7, 0xfc, 0x05, 0xe0, 0x71, 0x69, - 0x79, 0x60, 0x77, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x27, 0x38, 0x46, - 0xbd, 0xe8, 0xf0, 0x81, 0x10, 0xb5, 0x04, 0x46, 0x05, 0xf0, 0x48, 0xfa, - 0x61, 0x68, 0x4a, 0x68, 0xca, 0x60, 0x4a, 0x68, 0x0a, 0x61, 0x00, 0x22, - 0xca, 0x82, 0x80, 0xf3, 0x11, 0x88, 0x00, 0x20, 0x10, 0xbd, 0x2d, 0xe9, - 0xf0, 0x41, 0x07, 0x46, 0x0e, 0x46, 0x38, 0x78, 0x02, 0x28, 0x14, 0x46, - 0x18, 0xbf, 0x01, 0x20, 0x07, 0xd1, 0x71, 0x4d, 0x28, 0x78, 0x08, 0xb1, - 0x02, 0x20, 0x02, 0xe0, 0x68, 0x78, 0x18, 0xb1, 0x0d, 0x20, 0x20, 0x70, - 0x00, 0x20, 0x50, 0xe0, 0x05, 0xf0, 0x26, 0xfa, 0x80, 0x46, 0x78, 0x68, - 0xc1, 0x8a, 0x89, 0xb1, 0x02, 0x69, 0x12, 0x1d, 0x02, 0x61, 0x49, 0x1e, - 0x52, 0xf8, 0x04, 0x7d, 0x82, 0x68, 0xc1, 0x82, 0x01, 0x69, 0x91, 0x42, - 0x04, 0xbf, 0x41, 0x68, 0x01, 0x61, 0x00, 0xf0, 0x40, 0xf9, 0x00, 0x20, - 0x20, 0x70, 0x37, 0xe0, 0x28, 0x6a, 0x90, 0xf8, 0x30, 0x10, 0x41, 0xf0, - 0x04, 0x01, 0x80, 0xf8, 0x30, 0x10, 0x00, 0x20, 0x29, 0x6a, 0x81, 0xf8, - 0x31, 0x00, 0x28, 0x6a, 0xc6, 0x62, 0x38, 0x46, 0xff, 0xf7, 0x3e, 0xfc, - 0x00, 0xf0, 0x2b, 0xf9, 0xff, 0xf7, 0x78, 0xfc, 0x05, 0xf0, 0xfa, 0xf9, - 0x06, 0x46, 0x28, 0x6a, 0x00, 0xf1, 0x20, 0x01, 0x4a, 0x7c, 0x12, 0xb1, - 0x02, 0x2a, 0x03, 0xd0, 0x05, 0xe0, 0x0f, 0x68, 0x00, 0x20, 0x07, 0xe0, - 0x00, 0x27, 0x0e, 0x20, 0x04, 0xe0, 0x39, 0x46, 0xff, 0xf7, 0x4a, 0xfc, - 0x00, 0x27, 0x0a, 0x20, 0x20, 0x70, 0x00, 0x20, 0x29, 0x6a, 0x81, 0xf8, - 0x30, 0x00, 0x29, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x00, 0x21, 0x28, 0x6a, - 0xc1, 0x61, 0x01, 0x62, 0x00, 0xf0, 0x69, 0xf8, 0x38, 0x46, 0xbd, 0xe8, - 0xf0, 0x81, 0x01, 0x20, 0x20, 0x70, 0x00, 0x20, 0x70, 0x47, 0x70, 0xb5, - 0x06, 0x46, 0x0c, 0x46, 0x30, 0x78, 0x02, 0x28, 0x01, 0xd0, 0x01, 0x20, - 0x70, 0xbd, 0x05, 0xf0, 0xc7, 0xf9, 0x05, 0x46, 0xb0, 0x7a, 0x30, 0xb1, - 0x00, 0xf0, 0x46, 0xf8, 0x00, 0xf0, 0x4e, 0xf8, 0xff, 0xf7, 0x3a, 0xfc, - 0x14, 0xe0, 0x70, 0x68, 0xc1, 0x8a, 0x82, 0x8a, 0x91, 0x42, 0x00, 0xd3, - 0x40, 0xe0, 0xc2, 0x68, 0x12, 0x1d, 0xc2, 0x60, 0x49, 0x1c, 0x42, 0xf8, - 0x04, 0x4d, 0xc1, 0x82, 0x82, 0x68, 0xc1, 0x68, 0x91, 0x42, 0x04, 0xbf, - 0x41, 0x68, 0xc1, 0x60, 0x00, 0xf0, 0x36, 0xf8, 0x00, 0x20, 0x70, 0xbd, - 0x70, 0xb5, 0x06, 0x46, 0x0c, 0x46, 0x30, 0x78, 0x02, 0x28, 0x01, 0xd0, - 0x01, 0x20, 0x70, 0xbd, 0x05, 0xf0, 0x9c, 0xf9, 0x05, 0x46, 0xb0, 0x7a, - 0x30, 0xb1, 0x00, 0xf0, 0x1b, 0xf8, 0x00, 0xf0, 0x23, 0xf8, 0xff, 0xf7, - 0x0f, 0xfc, 0x13, 0xe0, 0x70, 0x68, 0xc1, 0x8a, 0x82, 0x8a, 0x91, 0x42, - 0x00, 0xd3, 0x15, 0xe0, 0x02, 0x69, 0x43, 0x68, 0x9a, 0x42, 0x04, 0xbf, - 0x82, 0x68, 0x02, 0x61, 0x02, 0x69, 0x12, 0x1f, 0x02, 0x61, 0x14, 0x60, - 0x49, 0x1c, 0xc1, 0x82, 0x00, 0xf0, 0x0c, 0xf8, 0x00, 0x20, 0x70, 0xbd, - 0x00, 0x23, 0x04, 0x22, 0x21, 0x46, 0x30, 0x46, 0xff, 0xf7, 0x80, 0xbb, - 0x00, 0xf0, 0x02, 0xf8, 0x1e, 0x20, 0x70, 0xbd, 0x28, 0x46, 0x05, 0xf0, - 0x75, 0xb9, 0x30, 0x46, 0x05, 0xf0, 0x72, 0xb9, 0x10, 0xb5, 0xdf, 0xf8, - 0x60, 0x46, 0x4f, 0xf4, 0x90, 0x71, 0x20, 0x46, 0xff, 0xf7, 0xdb, 0xfb, - 0x00, 0x20, 0x18, 0x21, 0x01, 0xfb, 0x00, 0xf2, 0x13, 0x19, 0x18, 0x33, - 0x40, 0x1c, 0x13, 0x51, 0x0b, 0x28, 0xf7, 0xd3, 0x01, 0xfb, 0x00, 0x40, - 0x00, 0x22, 0x02, 0x60, 0xdf, 0xf8, 0x7c, 0x03, 0x04, 0x60, 0x10, 0xbd, - 0x00, 0x00, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0x70, 0xb5, 0x00, 0xf0, - 0x17, 0xf8, 0x08, 0xb1, 0x00, 0x20, 0x70, 0xbd, 0x05, 0xf0, 0x46, 0xf9, - 0x69, 0x69, 0x0e, 0x00, 0x1c, 0xbf, 0x49, 0x68, 0x69, 0x61, 0x05, 0xf0, - 0x45, 0xf9, 0x3e, 0xb1, 0x03, 0x20, 0x30, 0x70, 0x34, 0x81, 0x00, 0x20, - 0x70, 0x60, 0x30, 0x46, 0xff, 0xf7, 0xa7, 0xfb, 0x30, 0x46, 0x70, 0xbd, - 0xdf, 0xf8, 0x20, 0x57, 0x04, 0x46, 0x28, 0x78, 0x70, 0x47, 0xdf, 0xf8, - 0x84, 0x77, 0x38, 0x78, 0x70, 0x47, 0x01, 0x22, 0x00, 0x21, 0x20, 0x46, - 0xff, 0xf7, 0x30, 0xbb, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0xf0, 0x52, 0xf8, - 0x18, 0xbf, 0x01, 0x20, 0x12, 0xd1, 0xff, 0xf7, 0xee, 0xff, 0x08, 0xb1, - 0x02, 0x20, 0x0d, 0xe0, 0x78, 0x78, 0x08, 0xb1, 0x0d, 0x20, 0x09, 0xe0, - 0x05, 0xf0, 0x14, 0xf9, 0x80, 0x46, 0x28, 0x89, 0x30, 0xb1, 0x40, 0x1e, - 0x28, 0x81, 0x00, 0xf0, 0x3a, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x34, 0xe0, - 0x38, 0x6a, 0x90, 0xf8, 0x30, 0x10, 0x41, 0xf0, 0x01, 0x01, 0x80, 0xf8, - 0x30, 0x10, 0x00, 0x20, 0x39, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x38, 0x6a, - 0xc6, 0x62, 0x28, 0x46, 0xff, 0xf7, 0x38, 0xfb, 0x00, 0xf0, 0x25, 0xf8, - 0xff, 0xf7, 0x72, 0xfb, 0x05, 0xf0, 0xf4, 0xf8, 0x06, 0x46, 0x38, 0x6a, - 0x90, 0xf8, 0x31, 0x10, 0x11, 0xb1, 0x02, 0x29, 0x02, 0xd0, 0x03, 0xe0, - 0x00, 0x20, 0x05, 0xe0, 0x0e, 0x20, 0x03, 0xe0, 0x29, 0x46, 0xff, 0xf7, - 0x47, 0xfb, 0x0a, 0x20, 0x20, 0x70, 0x00, 0x20, 0x39, 0x6a, 0x81, 0xf8, - 0x30, 0x00, 0x39, 0x6a, 0x81, 0xf8, 0x31, 0x00, 0x39, 0x6a, 0xc8, 0x61, - 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x41, 0x05, 0xf0, 0xdb, 0xb8, 0xbd, 0xe8, - 0xf0, 0x81, 0x40, 0x46, 0x05, 0xf0, 0xd6, 0xb8, 0x05, 0x46, 0x0e, 0x46, - 0x28, 0x78, 0x03, 0x28, 0x14, 0x46, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, - 0x20, 0x78, 0x03, 0x28, 0x01, 0xd0, 0x01, 0x20, 0x32, 0xbd, 0x05, 0xf0, - 0xc1, 0xf8, 0x05, 0x46, 0xa0, 0x7a, 0x38, 0xb1, 0x00, 0x23, 0xff, 0xf7, - 0x90, 0xff, 0xff, 0xf7, 0x47, 0xff, 0xff, 0xf7, 0x33, 0xfb, 0x08, 0xe0, - 0x20, 0x89, 0x4f, 0xf6, 0xff, 0x71, 0x88, 0x42, 0x05, 0xd0, 0x40, 0x1c, - 0x20, 0x81, 0xff, 0xf7, 0x3b, 0xff, 0x00, 0x20, 0x32, 0xbd, 0xff, 0xf7, - 0x37, 0xff, 0x33, 0x20, 0x32, 0xbd, 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, - 0x8b, 0x46, 0x90, 0x46, 0x99, 0x46, 0x05, 0xf0, 0x9f, 0xf8, 0xdf, 0xf8, - 0x64, 0x56, 0x29, 0x78, 0x19, 0xb1, 0x80, 0xf3, 0x11, 0x88, 0x3c, 0x20, - 0x33, 0xe0, 0x05, 0xeb, 0x89, 0x06, 0x31, 0x6b, 0x61, 0xbb, 0x01, 0x21, - 0x31, 0x63, 0x80, 0xf3, 0x11, 0x88, 0xdd, 0xf8, 0x3c, 0xa0, 0x10, 0x9f, - 0x12, 0x9c, 0x22, 0x46, 0x39, 0x46, 0x50, 0x46, 0x00, 0xf0, 0xc6, 0xf8, - 0x04, 0x98, 0x23, 0x46, 0x42, 0x46, 0x59, 0x46, 0x05, 0xf0, 0x1a, 0xf8, - 0x01, 0x46, 0x11, 0x98, 0x02, 0x94, 0x01, 0x90, 0x00, 0x97, 0x52, 0x46, - 0x0e, 0x9b, 0x48, 0x46, 0xff, 0xf7, 0xad, 0xfb, 0x04, 0x00, 0x05, 0xd1, - 0x68, 0x79, 0x01, 0x28, 0x08, 0xd1, 0xff, 0xf7, 0xeb, 0xfa, 0x05, 0xe0, - 0x05, 0xf0, 0x6c, 0xf8, 0x00, 0x21, 0x31, 0x63, 0x80, 0xf3, 0x11, 0x88, - 0x20, 0x46, 0x02, 0xe0, 0x80, 0xf3, 0x11, 0x88, 0x28, 0x20, 0x05, 0xb0, - 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0x74, 0x45, - 0x06, 0x46, 0x20, 0x78, 0x08, 0xb1, 0x40, 0x20, 0x64, 0xe0, 0x18, 0x2e, - 0x08, 0xbf, 0x3e, 0x20, 0x60, 0xd0, 0x05, 0xf0, 0x51, 0xf8, 0x80, 0x46, - 0xff, 0x2e, 0x04, 0xbf, 0x20, 0x6a, 0x90, 0xf8, 0x32, 0x60, 0x04, 0xeb, - 0x86, 0x05, 0x2e, 0x6b, 0x1e, 0xb9, 0xff, 0xf7, 0x72, 0xff, 0x43, 0x20, - 0x50, 0xe0, 0x01, 0x2e, 0x03, 0xd1, 0xff, 0xf7, 0x6c, 0xff, 0x3d, 0x20, - 0x4a, 0xe0, 0x06, 0xf1, 0x30, 0x07, 0x38, 0x79, 0x7a, 0x79, 0x00, 0x19, - 0x01, 0x7b, 0x91, 0x43, 0x01, 0x73, 0x38, 0x79, 0x00, 0x19, 0x00, 0x7b, - 0x18, 0xb9, 0x20, 0x79, 0xb9, 0x79, 0x88, 0x43, 0x20, 0x71, 0xf1, 0x69, - 0x11, 0xb1, 0x30, 0x46, 0xff, 0xf7, 0x8a, 0xfa, 0x70, 0x6a, 0x08, 0xb1, - 0xff, 0xf7, 0x83, 0xfd, 0x00, 0x20, 0xf0, 0x62, 0x38, 0x70, 0x78, 0x70, - 0x60, 0x78, 0xff, 0x28, 0x1c, 0xbf, 0x40, 0x1c, 0x60, 0x70, 0xff, 0xf7, - 0x46, 0xff, 0x05, 0xf0, 0x17, 0xf8, 0x80, 0x46, 0x60, 0x78, 0x08, 0xb1, - 0x40, 0x1e, 0x60, 0x70, 0x30, 0x46, 0x04, 0xf0, 0xa3, 0xff, 0xa0, 0x79, - 0x40, 0x1e, 0xa0, 0x71, 0x00, 0x20, 0x28, 0x63, 0xb1, 0x69, 0x70, 0x69, - 0x19, 0xb9, 0x81, 0x61, 0x70, 0x69, 0xe0, 0x62, 0x03, 0xe0, 0x48, 0x61, - 0x71, 0x69, 0xb0, 0x69, 0x88, 0x61, 0x60, 0x6a, 0x70, 0x61, 0x66, 0x62, - 0x1c, 0xa0, 0xf8, 0x61, 0xff, 0xf7, 0x25, 0xff, 0x60, 0x79, 0x01, 0x28, - 0x08, 0xbf, 0xff, 0xf7, 0x6f, 0xfa, 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x81, - 0xf8, 0xb5, 0xdf, 0xf8, 0x04, 0x75, 0x05, 0x46, 0x38, 0x78, 0x0e, 0x46, - 0x14, 0x46, 0x08, 0xb1, 0x12, 0x20, 0x15, 0xe0, 0x04, 0xf0, 0xe4, 0xff, - 0xff, 0x2d, 0x04, 0xbf, 0x39, 0x6a, 0x91, 0xf8, 0x32, 0x50, 0x07, 0xeb, - 0x85, 0x01, 0x09, 0x6b, 0x00, 0x29, 0x18, 0xbf, 0x01, 0x29, 0x03, 0xd1, - 0x04, 0xf0, 0xdc, 0xff, 0x43, 0x20, 0x03, 0xe0, 0xce, 0x64, 0x80, 0xf3, - 0x11, 0x88, 0x00, 0x20, 0x20, 0x70, 0xf1, 0xbd, 0x80, 0xb5, 0xdf, 0xf8, - 0xc0, 0x04, 0x00, 0x6a, 0x04, 0xf0, 0x60, 0xff, 0xbd, 0xe8, 0x02, 0x40, - 0xff, 0x20, 0x63, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0x02, 0xf0, 0x03, 0x02, 0x03, 0x2a, 0x04, 0xd1, 0x00, 0x29, 0x1c, 0xbf, - 0x89, 0x00, 0x05, 0xf0, 0x09, 0xb8, 0x70, 0x47, 0x70, 0xb5, 0xff, 0xf7, - 0x7f, 0xfe, 0x00, 0x28, 0x04, 0xbf, 0x68, 0x78, 0x00, 0x28, 0x16, 0xd1, - 0xac, 0xb1, 0x04, 0xf0, 0xab, 0xff, 0x29, 0x6a, 0x2c, 0x31, 0x0a, 0x7a, - 0x4e, 0x7a, 0x52, 0x19, 0x13, 0x7b, 0xb3, 0x43, 0x13, 0x73, 0x03, 0xd1, - 0x2a, 0x79, 0x8b, 0x7a, 0x9a, 0x43, 0x2a, 0x71, 0x0c, 0x60, 0x80, 0xf3, - 0x11, 0x88, 0xbd, 0xe8, 0x70, 0x40, 0xff, 0xf7, 0x13, 0xba, 0x70, 0xbd, - 0x8c, 0xf3, 0x00, 0x20, 0x10, 0xb5, 0x04, 0xf0, 0x91, 0xff, 0xdf, 0xf8, - 0x50, 0x14, 0x0c, 0x68, 0x80, 0xf3, 0x11, 0x88, 0x20, 0x46, 0x10, 0xbd, - 0xbd, 0xe8, 0x10, 0x40, 0x04, 0xf0, 0x8c, 0xbf, 0x2d, 0xe9, 0xf8, 0x43, - 0x06, 0x46, 0xdf, 0xf8, 0xc0, 0x03, 0x0a, 0x9c, 0x00, 0x78, 0x0f, 0x46, - 0x90, 0x46, 0x99, 0x46, 0x08, 0xb1, 0x8b, 0x20, 0x08, 0xe0, 0xff, 0xf7, - 0xfb, 0xf8, 0xdf, 0xf8, 0x20, 0x04, 0x05, 0x69, 0x2d, 0xb9, 0xff, 0xf7, - 0x0a, 0xf9, 0x86, 0x20, 0x20, 0x70, 0x00, 0x20, 0x20, 0xe0, 0xe9, 0x68, - 0x01, 0x61, 0x00, 0x21, 0xe9, 0x60, 0x29, 0x61, 0x41, 0x88, 0x49, 0x1c, - 0x41, 0x80, 0x01, 0x88, 0x49, 0x1e, 0x01, 0x80, 0x05, 0xf1, 0x24, 0x00, - 0x01, 0x21, 0x41, 0x70, 0x29, 0x1d, 0x4e, 0x61, 0x8f, 0x61, 0x80, 0xf8, - 0x00, 0x80, 0xc1, 0xf8, 0x00, 0x90, 0x08, 0x98, 0x48, 0x60, 0x09, 0x98, - 0x00, 0xb9, 0x8b, 0xa0, 0xc8, 0x61, 0xff, 0xf7, 0xe8, 0xf8, 0x00, 0x20, - 0x20, 0x70, 0x28, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x00, 0x00, 0x00, 0x00, - 0x38, 0xb5, 0x00, 0xf0, 0x74, 0xf8, 0x18, 0xbf, 0x89, 0x20, 0x1c, 0xd1, - 0x00, 0xf0, 0x6c, 0xf8, 0x08, 0xb1, 0x8b, 0x20, 0x17, 0xe0, 0xff, 0xf7, - 0xbf, 0xf8, 0x95, 0xf8, 0x25, 0x00, 0x03, 0x28, 0x0e, 0xd8, 0xdf, 0xe8, - 0x00, 0xf0, 0x09, 0x05, 0x05, 0x02, 0x28, 0x46, 0x00, 0xf0, 0x6c, 0xf9, - 0x28, 0x46, 0x00, 0xf0, 0xd9, 0xf8, 0x84, 0xe0, 0xff, 0xf7, 0xc3, 0xf8, - 0x87, 0x20, 0x02, 0xe0, 0xff, 0xf7, 0xbf, 0xf8, 0x8d, 0x20, 0x20, 0x70, - 0x00, 0x20, 0x32, 0xbd, 0x70, 0xb5, 0x00, 0xf0, 0x4e, 0xf8, 0x18, 0xbf, - 0x89, 0x20, 0x2c, 0xd1, 0x00, 0xf0, 0x46, 0xf8, 0x08, 0xb1, 0x8b, 0x20, - 0x27, 0xe0, 0xff, 0xf7, 0x99, 0xf8, 0x05, 0xf1, 0x24, 0x00, 0x41, 0x78, - 0x03, 0x29, 0x1d, 0xd8, 0xdf, 0xe8, 0x01, 0xf0, 0x18, 0x07, 0x13, 0x02, - 0xd2, 0x49, 0x68, 0x69, 0x49, 0x68, 0x46, 0x1a, 0x05, 0xe0, 0x00, 0x78, - 0xae, 0x69, 0x02, 0x28, 0x04, 0xbf, 0x00, 0x2e, 0xee, 0x69, 0xff, 0xf7, - 0x98, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x30, 0x46, 0x70, 0xbd, 0xff, 0xf7, - 0x92, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x70, 0xbd, 0xff, 0xf7, 0x8d, 0xf8, - 0x87, 0x20, 0x02, 0xe0, 0xff, 0xf7, 0x89, 0xf8, 0x8d, 0x20, 0x20, 0x70, - 0x00, 0x20, 0x70, 0xbd, 0x38, 0xb5, 0x00, 0xf0, 0x18, 0xf8, 0x18, 0xbf, - 0x89, 0x20, 0x03, 0xd1, 0x00, 0xf0, 0x10, 0xf8, 0x08, 0xb1, 0x8b, 0x20, - 0xbb, 0xe7, 0xff, 0xf7, 0x63, 0xf8, 0x95, 0xf8, 0x25, 0x50, 0x03, 0x2d, - 0x94, 0xbf, 0x00, 0x20, 0x8d, 0x20, 0x20, 0x70, 0xff, 0xf7, 0x6f, 0xf8, - 0x28, 0x46, 0x32, 0xbd, 0xb3, 0x48, 0x00, 0x78, 0x70, 0x47, 0x05, 0x46, - 0x0c, 0x46, 0x28, 0x78, 0x64, 0x28, 0x70, 0x47, 0x38, 0xb5, 0xff, 0xf7, - 0xf8, 0xff, 0x18, 0xbf, 0x89, 0x20, 0x1d, 0xd1, 0xff, 0xf7, 0xf0, 0xff, - 0x08, 0xb1, 0x8b, 0x20, 0x18, 0xe0, 0xff, 0xf7, 0x43, 0xf8, 0x95, 0xf8, - 0x25, 0x00, 0x03, 0x28, 0x0f, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x0a, 0x05, - 0x05, 0x02, 0x28, 0x46, 0x00, 0xf0, 0xf0, 0xf8, 0x00, 0x21, 0x28, 0x46, - 0x00, 0xf0, 0xca, 0xf8, 0x07, 0xe0, 0xff, 0xf7, 0x46, 0xf8, 0x87, 0x20, - 0x02, 0xe0, 0xff, 0xf7, 0x42, 0xf8, 0x8d, 0x20, 0x81, 0xe7, 0xff, 0xf7, - 0x3e, 0xf8, 0x00, 0x20, 0x20, 0x70, 0x01, 0x20, 0x32, 0xbd, 0x00, 0x00, - 0xf8, 0xb5, 0x05, 0x46, 0x0f, 0x46, 0x28, 0x78, 0x64, 0x28, 0x16, 0x46, - 0x1c, 0x46, 0x18, 0xbf, 0x89, 0x20, 0x3a, 0xd1, 0xff, 0xf7, 0xc0, 0xff, - 0x08, 0xb1, 0x8b, 0x20, 0x35, 0xe0, 0xff, 0xf7, 0x13, 0xf8, 0x95, 0xf8, - 0x25, 0x00, 0x03, 0x28, 0x2c, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, 0x27, 0x21, - 0x21, 0x02, 0x28, 0x46, 0x00, 0xf0, 0xc0, 0xf8, 0x00, 0x20, 0x20, 0x70, - 0xaf, 0xb1, 0x03, 0x2f, 0x02, 0xd0, 0x04, 0x2f, 0x06, 0xd0, 0x0e, 0xe0, - 0x6a, 0x68, 0x10, 0x00, 0x18, 0xbf, 0xa9, 0x68, 0x04, 0xd1, 0x06, 0xe0, - 0x6a, 0x68, 0x10, 0x00, 0x03, 0xd0, 0x31, 0x46, 0x28, 0x46, 0x90, 0x47, - 0x03, 0xe0, 0x8f, 0x20, 0x00, 0xe0, 0x84, 0x20, 0x20, 0x70, 0xff, 0xf7, - 0x02, 0xf8, 0x03, 0xe0, 0xfe, 0xf7, 0xff, 0xff, 0x8e, 0x20, 0x20, 0x70, - 0x01, 0x20, 0xf2, 0xbd, 0xfe, 0xf7, 0xf9, 0xff, 0x87, 0x20, 0x02, 0xe0, - 0xfe, 0xf7, 0xf5, 0xff, 0x8d, 0x20, 0x20, 0x70, 0x00, 0x20, 0xf2, 0xbd, - 0x78, 0x48, 0xc0, 0x68, 0xff, 0xf7, 0x8a, 0xbd, 0x00, 0xf1, 0x24, 0x01, - 0x00, 0x22, 0x4a, 0x70, 0x0a, 0x70, 0x09, 0xa1, 0x01, 0x62, 0xc2, 0x61, - 0x42, 0x61, 0x42, 0x60, 0x82, 0x60, 0x02, 0x61, 0x70, 0x49, 0x0a, 0x69, - 0xc2, 0x60, 0x08, 0x61, 0x48, 0x88, 0x40, 0x1e, 0x48, 0x80, 0x08, 0x88, - 0x40, 0x1c, 0x08, 0x80, 0x70, 0x47, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, - 0x74, 0xec, 0x00, 0x20, 0x70, 0xb5, 0x68, 0x4c, 0x86, 0xb0, 0x4f, 0xf4, - 0x70, 0x71, 0x04, 0xf1, 0x54, 0x00, 0xff, 0xf7, 0xa6, 0xf8, 0x40, 0x21, - 0x04, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0xa1, 0xf8, 0x00, 0x20, 0x5f, 0xa1, - 0x28, 0x22, 0x02, 0xfb, 0x00, 0x43, 0x03, 0xf1, 0x54, 0x05, 0x64, 0x26, - 0x2e, 0x70, 0x40, 0x1c, 0x00, 0x26, 0x7c, 0x33, 0x17, 0x28, 0x85, 0xf8, - 0x25, 0x60, 0xeb, 0x60, 0x29, 0x62, 0xf0, 0xd3, 0x02, 0xfb, 0x00, 0x40, - 0x64, 0x22, 0x00, 0xf8, 0x54, 0x2f, 0x80, 0xf8, 0x25, 0x60, 0xc6, 0x60, - 0x01, 0x62, 0x18, 0x20, 0x20, 0x80, 0x66, 0x60, 0x04, 0xf1, 0x54, 0x00, - 0x20, 0x61, 0x66, 0x80, 0x01, 0x20, 0xff, 0xf7, 0xb7, 0xfc, 0xa0, 0x60, - 0x00, 0x20, 0xff, 0xf7, 0xb3, 0xfc, 0x03, 0x21, 0x04, 0x91, 0xe0, 0x60, - 0x80, 0x21, 0x02, 0x91, 0x4f, 0xf6, 0xfd, 0x71, 0x4a, 0x48, 0x01, 0x90, - 0x00, 0x91, 0x00, 0xf5, 0xfe, 0x72, 0x03, 0x96, 0x02, 0x23, 0x00, 0x21, - 0x0f, 0xf2, 0xa1, 0x00, 0xff, 0xf7, 0x47, 0xfd, 0x05, 0xaa, 0x0f, 0xf2, - 0x14, 0x11, 0x02, 0x20, 0xff, 0xf7, 0xf8, 0xfd, 0x06, 0xb0, 0x70, 0xbd, - 0x10, 0xb5, 0x03, 0x22, 0x80, 0xf8, 0x25, 0x20, 0x01, 0x29, 0x3d, 0x4a, - 0x53, 0x68, 0x1a, 0xbf, 0x81, 0x69, 0x00, 0x29, 0xc1, 0x69, 0x59, 0x18, - 0x41, 0x61, 0x01, 0x7d, 0x01, 0xf0, 0x07, 0x01, 0x02, 0xeb, 0xc1, 0x01, - 0x14, 0x31, 0x8a, 0x88, 0x0b, 0x68, 0x1b, 0xb9, 0x00, 0x22, 0xc2, 0x60, - 0x01, 0x22, 0x02, 0xe0, 0xc3, 0x60, 0x18, 0x61, 0x52, 0x1c, 0x8a, 0x80, - 0x08, 0x60, 0x00, 0x21, 0x01, 0x61, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0xf1, - 0x0c, 0x01, 0x2d, 0x4a, 0x0b, 0x7a, 0x03, 0xf0, 0x07, 0x03, 0x02, 0xeb, - 0xc3, 0x02, 0x52, 0xf8, 0x14, 0x4f, 0x0b, 0x68, 0x84, 0x42, 0x05, 0xd1, - 0x18, 0x00, 0x10, 0x60, 0x06, 0xd0, 0x00, 0x23, 0x03, 0x61, 0x03, 0xe0, - 0x48, 0x68, 0xc3, 0x60, 0x03, 0xb1, 0x18, 0x61, 0x01, 0x20, 0x48, 0x76, - 0x00, 0x20, 0x08, 0x60, 0x48, 0x60, 0x90, 0x88, 0x40, 0x1e, 0x90, 0x80, - 0x10, 0xbd, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0xf8, 0xb5, 0x1c, 0x4c, - 0x01, 0xe0, 0xfe, 0xf7, 0x34, 0xff, 0xe0, 0x68, 0x6a, 0x46, 0x00, 0x21, - 0xff, 0xf7, 0x70, 0xfc, 0xfe, 0xf7, 0x18, 0xff, 0x60, 0x68, 0x40, 0x1c, - 0x60, 0x60, 0x00, 0xf0, 0x07, 0x00, 0x04, 0xeb, 0xc0, 0x00, 0x45, 0x69, - 0x00, 0x2d, 0x08, 0xe0, 0x02, 0x21, 0x41, 0x70, 0x32, 0x68, 0x10, 0x00, - 0x02, 0xd0, 0x71, 0x68, 0x28, 0x46, 0x90, 0x47, 0x3d, 0x00, 0xe2, 0xd0, - 0x2e, 0x1d, 0x60, 0x68, 0x31, 0x69, 0xb7, 0x68, 0x88, 0x42, 0xf7, 0xd1, - 0x28, 0x46, 0xff, 0xf7, 0xb3, 0xff, 0x05, 0xf1, 0x24, 0x00, 0x01, 0x78, - 0x02, 0x29, 0xe7, 0xd1, 0x01, 0x21, 0x28, 0x46, 0xff, 0xf7, 0x88, 0xff, - 0xe4, 0xe7, 0x00, 0x00, 0x20, 0xbd, 0x00, 0x20, 0x3f, 0x00, 0x00, 0x00, - 0x90, 0xf3, 0x00, 0x20, 0x68, 0xdb, 0x00, 0x20, 0x68, 0x78, 0x00, 0x20, - 0x75, 0x43, 0x2f, 0x4f, 0x53, 0x2d, 0x49, 0x49, 0x20, 0x54, 0x6d, 0x72, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x04, 0xf0, 0xb1, 0xbd, 0xf0, 0xb4, - 0x01, 0x68, 0x44, 0x68, 0x83, 0x68, 0x09, 0x18, 0x01, 0xeb, 0x54, 0x02, - 0xe4, 0x07, 0x48, 0xbf, 0x4b, 0x44, 0x0c, 0x30, 0x91, 0x42, 0x2b, 0xd0, - 0x11, 0xf8, 0x01, 0x4b, 0x14, 0xf0, 0x03, 0x05, 0x04, 0xbf, 0x11, 0xf8, - 0x01, 0x5b, 0xed, 0x1c, 0x26, 0x09, 0x0f, 0x2e, 0x07, 0xd1, 0x11, 0xf8, - 0x01, 0x6b, 0x0f, 0x36, 0x03, 0xe0, 0x11, 0xf8, 0x01, 0x7b, 0x03, 0xf8, - 0x01, 0x7b, 0x6d, 0x1e, 0xf9, 0xd1, 0x00, 0x2e, 0xe6, 0xd0, 0xa4, 0x08, - 0x11, 0xf8, 0x01, 0x5b, 0x04, 0xf0, 0x03, 0x04, 0x03, 0x2c, 0x08, 0xbf, - 0x11, 0xf8, 0x01, 0x4b, 0x05, 0xeb, 0x04, 0x24, 0x1c, 0x1b, 0xb5, 0x1c, - 0xd8, 0xd0, 0x14, 0xf8, 0x01, 0x6b, 0x03, 0xf8, 0x01, 0x6b, 0x6d, 0x1e, - 0xf9, 0xd1, 0xd1, 0xe7, 0xf0, 0xbc, 0x70, 0x47, 0x10, 0xb5, 0xef, 0xf3, - 0x10, 0x82, 0x72, 0xb6, 0x66, 0x4b, 0x4f, 0xf6, 0xfe, 0x64, 0x00, 0xf1, - 0x8c, 0x40, 0x44, 0xe0, 0x30, 0xb5, 0x00, 0xf1, 0x8c, 0x40, 0xef, 0xf3, - 0x10, 0x83, 0x72, 0xb6, 0x60, 0x4c, 0x4f, 0xf6, 0xfe, 0x65, 0x25, 0x60, - 0x05, 0x78, 0x8d, 0x43, 0x11, 0x40, 0x29, 0x43, 0x01, 0x70, 0x00, 0x20, - 0x20, 0x60, 0x83, 0xf3, 0x10, 0x88, 0x30, 0xbd, 0xf0, 0xb5, 0x00, 0xf0, - 0x23, 0xf8, 0x0b, 0xe0, 0x72, 0xb6, 0x4f, 0xf6, 0xfe, 0x66, 0x2e, 0x60, - 0x30, 0xf8, 0x14, 0x70, 0x66, 0x5c, 0x07, 0xf1, 0x8c, 0x47, 0x3e, 0x70, - 0x00, 0xf0, 0x10, 0xf8, 0x94, 0x42, 0xf1, 0xd3, 0xf0, 0xbd, 0x10, 0xb5, - 0x00, 0x23, 0x06, 0xe0, 0x30, 0xf8, 0x13, 0x40, 0x04, 0xf1, 0x8c, 0x44, - 0x24, 0x78, 0x5c, 0x54, 0x5b, 0x1c, 0x93, 0x42, 0xf6, 0xd3, 0x10, 0xbd, - 0x00, 0x26, 0x2e, 0x60, 0x83, 0xf3, 0x10, 0x88, 0x64, 0x1c, 0x70, 0x47, - 0xef, 0xf3, 0x10, 0x83, 0x00, 0x24, 0x45, 0x4d, 0x70, 0x47, 0x10, 0xb5, - 0x00, 0xf0, 0x0a, 0xf8, 0x1c, 0x60, 0x01, 0x60, 0x01, 0xe0, 0x1c, 0x60, - 0x01, 0x70, 0x00, 0x20, 0x18, 0x60, 0x82, 0xf3, 0x10, 0x88, 0x10, 0xbd, - 0xef, 0xf3, 0x10, 0x82, 0x72, 0xb6, 0x3c, 0x4b, 0x3c, 0x4c, 0x70, 0x47, - 0x3c, 0x49, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x02, 0x06, 0x2a, 0x02, 0xbf, - 0xc1, 0xf3, 0xc2, 0x01, 0x01, 0x40, 0x81, 0x42, 0x0c, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0x70, 0x47, 0x35, 0x49, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x02, - 0x06, 0x2a, 0x03, 0xbf, 0x00, 0xea, 0x91, 0x11, 0x81, 0x42, 0x01, 0x20, - 0x00, 0x20, 0x70, 0x47, 0x1c, 0xb5, 0x0f, 0xf2, 0xcc, 0x02, 0x18, 0xca, - 0x69, 0x46, 0x03, 0x28, 0x18, 0xc1, 0x01, 0xd3, 0x00, 0x20, 0x16, 0xbd, - 0x00, 0xf0, 0x03, 0x00, 0x3d, 0xf8, 0x10, 0x00, 0x00, 0xf1, 0x8c, 0x41, - 0x00, 0x22, 0x08, 0x78, 0x01, 0xe0, 0x00, 0x22, 0x18, 0x46, 0x0b, 0x78, - 0x83, 0x42, 0xfa, 0xd1, 0x52, 0x1c, 0x05, 0x2a, 0xf9, 0xd3, 0x16, 0xbd, - 0x38, 0xb5, 0x04, 0x46, 0x00, 0x22, 0x04, 0x21, 0x40, 0xf2, 0x16, 0x50, - 0xff, 0xf7, 0x70, 0xff, 0x1e, 0x4d, 0x0c, 0xb9, 0x28, 0x78, 0x32, 0xbd, - 0x01, 0x2c, 0x01, 0xd1, 0x28, 0x79, 0x32, 0xbd, 0xa0, 0x1e, 0xc2, 0x00, - 0xd2, 0xb2, 0x18, 0x21, 0x40, 0xf2, 0x17, 0x50, 0xff, 0xf7, 0x60, 0xff, - 0x28, 0x7a, 0x32, 0xbd, 0x80, 0xb5, 0xff, 0xf7, 0xe3, 0xff, 0x0f, 0xf2, - 0x64, 0x01, 0x40, 0x56, 0x02, 0xbd, 0x38, 0xb5, 0x02, 0x00, 0x0c, 0x46, - 0x10, 0x4d, 0x40, 0xf2, 0x16, 0x50, 0x07, 0xd1, 0x0c, 0x22, 0x1c, 0x21, - 0xff, 0xf7, 0x4c, 0xff, 0x00, 0xf0, 0x1a, 0xf8, 0x28, 0x78, 0x0a, 0xe0, - 0x01, 0x2a, 0x07, 0xd1, 0x14, 0x22, 0x1c, 0x21, 0xff, 0xf7, 0x42, 0xff, - 0x00, 0xf0, 0x10, 0xf8, 0x28, 0x79, 0x00, 0xe0, 0x00, 0x20, 0x0f, 0xf2, - 0x28, 0x01, 0x40, 0x56, 0x32, 0xbd, 0x00, 0x00, 0x48, 0x00, 0x00, 0x50, - 0x00, 0x00, 0xab, 0xab, 0xb3, 0x01, 0x00, 0x46, 0x0b, 0x05, 0x00, 0x46, - 0x21, 0x46, 0x4f, 0xf4, 0xa0, 0x60, 0x21, 0xe7, 0xb0, 0x04, 0xb3, 0x04, - 0xb6, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfd, 0xfd, 0xfd, - 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfa, - 0xfa, 0xfa, 0xf9, 0xf9, 0xf9, 0xf9, 0xf8, 0xf8, 0xf7, 0xf7, 0xf7, 0xf6, - 0xf6, 0xf5, 0xf5, 0xf4, 0xf4, 0xf3, 0xf3, 0xf2, 0xf1, 0xf1, 0xf0, 0xef, - 0xee, 0xed, 0xeb, 0xea, 0xe8, 0xe5, 0xe2, 0xdc, 0x10, 0xb5, 0x01, 0x20, - 0x04, 0xf0, 0x13, 0xfe, 0x79, 0x4c, 0x18, 0x21, 0x04, 0xf1, 0x14, 0x00, - 0xff, 0xf7, 0xb6, 0xfe, 0x01, 0x22, 0x02, 0x21, 0x20, 0x1d, 0x04, 0xf0, - 0x61, 0xfc, 0xa0, 0x1c, 0x00, 0x21, 0x01, 0x80, 0x0e, 0x20, 0x04, 0xf0, - 0x56, 0xfe, 0x00, 0x22, 0x80, 0x21, 0x40, 0xf6, 0x6e, 0x10, 0xff, 0xf7, - 0xed, 0xfe, 0x6f, 0x48, 0x4f, 0xf0, 0x40, 0x71, 0xc1, 0x62, 0x01, 0x60, - 0x0e, 0x20, 0x06, 0x21, 0x04, 0xf0, 0x53, 0xfe, 0x0e, 0x20, 0x04, 0xf0, - 0x35, 0xfe, 0xbd, 0xe8, 0x10, 0x40, 0x19, 0xe0, 0x03, 0x28, 0x00, 0xdb, - 0x70, 0x47, 0x30, 0xb5, 0x02, 0x29, 0x0b, 0xda, 0x63, 0x4c, 0x01, 0xeb, - 0x41, 0x05, 0x2d, 0x19, 0x45, 0x19, 0x2a, 0x72, 0x0c, 0x22, 0x02, 0xfb, - 0x01, 0x41, 0x01, 0xeb, 0x80, 0x00, 0x43, 0x61, 0x30, 0xbd, 0x00, 0x23, - 0x00, 0x22, 0xe9, 0xe7, 0x0e, 0x20, 0x04, 0xf0, 0x28, 0xbe, 0x00, 0xbf, - 0x0e, 0x20, 0x04, 0xf0, 0x1b, 0xbe, 0x70, 0xb5, 0x04, 0x46, 0x57, 0x4d, - 0x66, 0x19, 0xb0, 0x78, 0x70, 0xb9, 0x01, 0x20, 0xa0, 0x40, 0xff, 0xf7, - 0x17, 0xff, 0x48, 0xb1, 0x05, 0xeb, 0x44, 0x00, 0x00, 0xf1, 0x10, 0x01, - 0x32, 0x46, 0x20, 0x46, 0x04, 0xf0, 0x84, 0xf8, 0x01, 0x20, 0xb0, 0x70, - 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xe6, 0xff, 0x4b, 0x48, - 0x00, 0xeb, 0x44, 0x00, 0x00, 0x8a, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, - 0xff, 0xf7, 0xdd, 0xff, 0x46, 0x48, 0x20, 0x5c, 0x10, 0xbd, 0x2d, 0xe9, - 0xf8, 0x4f, 0x00, 0x20, 0x00, 0x90, 0x00, 0x27, 0x42, 0x4c, 0xe8, 0x46, - 0x0d, 0xf1, 0x02, 0x06, 0x00, 0xe0, 0x0f, 0xb9, 0x1b, 0x20, 0x00, 0xe0, - 0x1c, 0x20, 0x04, 0xf0, 0x5e, 0xfe, 0x0f, 0xf2, 0x04, 0x10, 0x3e, 0x49, - 0x50, 0xf8, 0x27, 0x00, 0x08, 0x60, 0x01, 0x20, 0xb8, 0x40, 0xff, 0xf7, - 0xe1, 0xfe, 0x10, 0xb3, 0x04, 0xeb, 0x47, 0x0a, 0x17, 0xf8, 0x04, 0x90, - 0xba, 0xf8, 0x10, 0xb0, 0x3d, 0x19, 0x2a, 0x46, 0x0a, 0xf1, 0x10, 0x01, - 0x38, 0x46, 0x04, 0xf0, 0x49, 0xf8, 0xa8, 0x78, 0x10, 0xb9, 0x01, 0x20, - 0xb8, 0x55, 0x09, 0xe0, 0xba, 0xf8, 0x10, 0x00, 0x58, 0x45, 0x14, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0xb8, 0x55, 0x38, 0x5d, 0x48, 0x45, 0x01, 0xd0, - 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x07, 0xf8, 0x08, 0x00, 0x01, 0x20, - 0xa8, 0x70, 0x7f, 0x1c, 0x02, 0x2f, 0xc8, 0xd3, 0x00, 0x27, 0x38, 0x19, - 0x00, 0x79, 0x00, 0xb3, 0x00, 0x25, 0x17, 0xf8, 0x08, 0x00, 0x48, 0xb9, - 0xb8, 0x5d, 0xb8, 0xb1, 0x04, 0xf1, 0x08, 0x00, 0x07, 0xeb, 0x47, 0x01, - 0x08, 0x18, 0x28, 0x5c, 0x01, 0x28, 0x0f, 0xd1, 0x04, 0xf1, 0x14, 0x00, - 0x0c, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x50, 0xf8, 0x25, 0x30, 0x18, 0x00, - 0x06, 0xd0, 0x04, 0xf1, 0x10, 0x00, 0x30, 0xf8, 0x17, 0x10, 0x3a, 0x5d, - 0xf8, 0xb2, 0x98, 0x47, 0x6d, 0x1c, 0x03, 0x2d, 0xdf, 0xd3, 0x7f, 0x1c, - 0x02, 0x2f, 0xd8, 0xd3, 0xbd, 0xe8, 0xf1, 0x8f, 0x12, 0x48, 0x4f, 0xf4, - 0x40, 0x51, 0x01, 0x60, 0xc1, 0x68, 0x41, 0xf4, 0x40, 0x51, 0xc1, 0x60, - 0x70, 0x47, 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0x00, 0x50, 0x4f, 0xf4, - 0x80, 0x50, 0x0b, 0x4a, 0x01, 0x29, 0x0c, 0xbf, 0x11, 0x68, 0x51, 0x68, - 0x08, 0x40, 0x70, 0x47, 0x00, 0x28, 0x07, 0x49, 0x0c, 0xbf, 0x4f, 0xf4, - 0x00, 0x50, 0x4f, 0xf4, 0x80, 0x50, 0x08, 0x60, 0x70, 0x47, 0x00, 0x00, - 0x3c, 0xee, 0x00, 0x20, 0x14, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x50, - 0x40, 0x00, 0x00, 0x58, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, - 0xd2, 0xb2, 0x20, 0x3a, 0x22, 0xbf, 0x21, 0xfa, 0x02, 0xf0, 0x00, 0x21, - 0x70, 0x47, 0x20, 0x32, 0xd1, 0x41, 0xd0, 0x40, 0x48, 0x40, 0x91, 0x40, - 0xd1, 0x40, 0x48, 0x40, 0x70, 0x47, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, - 0x10, 0xb5, 0x04, 0x46, 0x18, 0x22, 0x63, 0x00, 0x01, 0x20, 0x00, 0x21, - 0x9a, 0x40, 0x03, 0xf0, 0x17, 0xff, 0x02, 0x46, 0x04, 0xf1, 0x18, 0x00, - 0x0b, 0x46, 0x40, 0x00, 0x04, 0xf0, 0x52, 0xfe, 0xc0, 0xb2, 0x10, 0xbd, - 0x38, 0xb5, 0xdf, 0xf8, 0x00, 0x4d, 0x25, 0x68, 0x00, 0xf0, 0x6b, 0xfb, - 0x05, 0x28, 0x04, 0xbf, 0x28, 0x0c, 0x60, 0xf3, 0x82, 0x05, 0x00, 0xf0, - 0x78, 0xfb, 0x06, 0x28, 0x04, 0xbf, 0x68, 0x0c, 0x60, 0xf3, 0xc3, 0x05, - 0x65, 0x60, 0x31, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x00, 0x14, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0xd3, 0xfc, 0x68, 0x68, 0x00, 0xf0, - 0xc5, 0xfa, 0xdf, 0xf8, 0x30, 0x0d, 0x00, 0xeb, 0x84, 0x00, 0x45, 0x60, - 0xfe, 0xf7, 0x50, 0xfc, 0x01, 0x21, 0x28, 0x46, 0x00, 0xf0, 0x38, 0xfe, - 0x88, 0xe1, 0xf0, 0xb5, 0x83, 0xb0, 0x0c, 0x46, 0xef, 0xf3, 0x05, 0x80, - 0x08, 0xb1, 0x00, 0xf0, 0xbb, 0xfe, 0x00, 0xf0, 0xaf, 0xfe, 0x06, 0x46, - 0x00, 0xf0, 0x64, 0xfa, 0x05, 0x00, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0x04, 0xf0, 0xb1, 0xfc, 0x05, 0xf1, 0x1c, 0x07, 0x30, 0x02, 0x40, 0xf0, - 0x02, 0x00, 0x38, 0x60, 0x07, 0x20, 0x04, 0xf0, 0x6c, 0xfd, 0x68, 0x68, - 0xdf, 0xf8, 0xdc, 0x6c, 0x01, 0xab, 0x00, 0x22, 0x17, 0x21, 0xfe, 0xf7, - 0x3d, 0xff, 0x30, 0x68, 0x39, 0x46, 0xff, 0xf7, 0xce, 0xf8, 0x8d, 0xf8, - 0x04, 0x00, 0x40, 0x1e, 0x00, 0xf0, 0x45, 0xfc, 0x0d, 0xf1, 0x05, 0x00, - 0x00, 0x90, 0x23, 0x46, 0x68, 0x68, 0x82, 0x22, 0x02, 0x21, 0xfe, 0xf7, - 0x9f, 0xfe, 0x9d, 0xf8, 0x05, 0x10, 0x00, 0xf0, 0x37, 0xfc, 0x02, 0x20, - 0x04, 0xf0, 0x54, 0xfe, 0xef, 0xf3, 0x11, 0x84, 0x60, 0x20, 0x80, 0xf3, - 0x11, 0x88, 0xdf, 0xf8, 0xa8, 0x7c, 0xdf, 0xf8, 0xa8, 0x1c, 0x3d, 0x68, - 0x4f, 0xf0, 0x00, 0x40, 0x08, 0x60, 0x04, 0xf0, 0xd9, 0xfe, 0x03, 0x28, - 0x04, 0xbf, 0x96, 0xf8, 0x54, 0x03, 0x03, 0x28, 0x03, 0xd1, 0xdf, 0xf8, - 0xbc, 0x1c, 0x01, 0x20, 0x08, 0x70, 0x05, 0xf0, 0x00, 0x40, 0x38, 0x60, - 0x84, 0xf3, 0x11, 0x88, 0x00, 0x20, 0xfe, 0xbd, 0x38, 0xb5, 0xef, 0xf3, - 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x60, 0xfe, 0x00, 0xf0, 0x54, 0xfe, - 0x00, 0xf0, 0x09, 0xfa, 0x05, 0x00, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0x04, 0xf0, 0x57, 0xfc, 0x20, 0x02, 0x40, 0xf0, 0x03, 0x00, 0x45, 0xf8, - 0x1c, 0x0f, 0x00, 0x21, 0x08, 0x20, 0x04, 0xf0, 0x22, 0xfd, 0xdf, 0xf8, - 0x2c, 0x0c, 0x00, 0x68, 0x29, 0x46, 0xff, 0xf7, 0x7a, 0xf8, 0x40, 0x1e, - 0x00, 0xf0, 0xf3, 0xfb, 0x00, 0x20, 0x32, 0xbd, 0x70, 0xb5, 0x0c, 0x46, - 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x3b, 0xfe, 0x00, 0xf0, - 0x2f, 0xfe, 0x05, 0x46, 0x00, 0xf0, 0xe4, 0xf9, 0x06, 0x00, 0x14, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0x31, 0xfc, 0x06, 0xf1, 0x1c, 0x01, - 0x44, 0xea, 0x05, 0x20, 0x08, 0x60, 0xdf, 0xf8, 0xe8, 0x0b, 0x00, 0x68, - 0xff, 0xf7, 0x59, 0xf8, 0x40, 0x1e, 0x00, 0xf0, 0xd2, 0xfb, 0x00, 0x20, - 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x03, 0x20, 0x04, 0xf0, 0xe1, 0xfc, - 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x04, 0x21, 0xd4, 0xe7, 0x10, 0xb5, - 0x04, 0x46, 0x20, 0x68, 0xc0, 0xb2, 0x81, 0x42, 0x0c, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0x04, 0xf0, 0x0e, 0xfc, 0xdf, 0xf8, 0xac, 0x0b, 0x00, 0x68, - 0x21, 0x46, 0xff, 0xf7, 0x65, 0xf8, 0x40, 0x1e, 0x00, 0xf0, 0xb3, 0xfb, - 0x00, 0x20, 0x10, 0xbd, 0xdf, 0xf8, 0x94, 0x1b, 0x91, 0xf8, 0x60, 0x23, - 0x0a, 0xb1, 0x00, 0x20, 0x70, 0x47, 0x01, 0x22, 0x81, 0xf8, 0x60, 0x23, - 0x00, 0x21, 0xde, 0xe7, 0x01, 0x21, 0xdc, 0xe7, 0x10, 0xb5, 0x04, 0x46, - 0x17, 0x20, 0x04, 0xf0, 0xb4, 0xfc, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, - 0x08, 0x21, 0xd2, 0xe7, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x82, 0xb0, - 0x21, 0x46, 0x09, 0x20, 0x04, 0xf0, 0xc6, 0xfc, 0x01, 0x21, 0x08, 0x20, - 0x04, 0xf0, 0xb3, 0xfc, 0xe0, 0xb2, 0x00, 0xf0, 0xcb, 0xfd, 0x06, 0x46, - 0x03, 0x20, 0x30, 0x76, 0x0c, 0xb1, 0xc5, 0xf3, 0x02, 0x10, 0xdf, 0xf8, - 0x3c, 0x5b, 0x85, 0xf8, 0x54, 0x03, 0x02, 0x20, 0x04, 0xf0, 0x7e, 0xfd, - 0x70, 0x68, 0x6b, 0x46, 0x01, 0x22, 0x02, 0x21, 0xfe, 0xf7, 0x66, 0xfe, - 0x05, 0xf1, 0x4c, 0x00, 0x01, 0x21, 0x81, 0x72, 0x04, 0x80, 0x00, 0x21, - 0xc1, 0x72, 0x00, 0xf0, 0x6b, 0xfb, 0x00, 0x20, 0x76, 0xbd, 0x70, 0xb5, - 0x04, 0x46, 0xdf, 0xf8, 0x08, 0x5b, 0x60, 0x88, 0x1c, 0x21, 0x01, 0xfb, - 0x00, 0x50, 0x00, 0x2c, 0x90, 0xf8, 0x40, 0x61, 0x14, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0x04, 0xf0, 0xae, 0xfb, 0x00, 0x20, 0x20, 0x63, 0x00, 0x2e, - 0x0c, 0xbf, 0x05, 0xf5, 0x4b, 0x70, 0x05, 0xf5, 0x4c, 0x70, 0x01, 0x68, - 0x11, 0xb9, 0x04, 0x60, 0x70, 0xbd, 0x01, 0x46, 0x08, 0x6b, 0x00, 0x28, - 0xfb, 0xd1, 0x0c, 0x63, 0x70, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xfe, 0xf7, - 0x1f, 0xfb, 0xdf, 0xf8, 0xc0, 0x0a, 0x00, 0xf5, 0x4b, 0x71, 0x00, 0x2c, - 0x0c, 0xbf, 0x09, 0x68, 0x49, 0x68, 0x71, 0xb1, 0x89, 0x78, 0x1c, 0x22, - 0x02, 0xfb, 0x01, 0x04, 0x94, 0xf8, 0x30, 0x01, 0x03, 0x28, 0x06, 0xd1, - 0x84, 0xf8, 0x30, 0x01, 0xfe, 0xf7, 0x1f, 0xfb, 0x04, 0xf5, 0x98, 0x70, - 0x10, 0xbd, 0xc9, 0xe0, 0x70, 0xb5, 0x04, 0x00, 0x14, 0xbf, 0x01, 0x26, - 0x00, 0x26, 0x30, 0x46, 0x04, 0xf0, 0x77, 0xfb, 0x30, 0x46, 0x04, 0xf0, - 0x74, 0xfb, 0x61, 0x88, 0xdf, 0xf8, 0x74, 0x0a, 0x1c, 0x22, 0x02, 0xfb, - 0x01, 0x01, 0x91, 0xf8, 0x40, 0x11, 0x00, 0x29, 0x0c, 0xbf, 0x00, 0xf5, - 0x4b, 0x70, 0x00, 0xf5, 0x4c, 0x70, 0x01, 0x68, 0xa1, 0x42, 0x06, 0xd1, - 0x09, 0x6b, 0x01, 0x60, 0x00, 0x20, 0x20, 0x63, 0x70, 0xbd, 0x0d, 0x46, - 0x09, 0x6b, 0x00, 0x29, 0x18, 0xbf, 0xa1, 0x42, 0xf9, 0xd1, 0xa1, 0x42, - 0x03, 0xd1, 0x08, 0x6b, 0x28, 0x63, 0x00, 0x20, 0x08, 0x63, 0x70, 0xbd, - 0x38, 0xb5, 0xdf, 0xf8, 0x30, 0x1a, 0x1c, 0x22, 0x02, 0xfb, 0x00, 0x11, - 0x01, 0xf5, 0x98, 0x74, 0x00, 0xf0, 0xf4, 0xf8, 0x05, 0x46, 0xfe, 0xf7, - 0xcb, 0xfa, 0x20, 0x78, 0x01, 0x28, 0x1c, 0xbf, 0x03, 0x28, 0x02, 0x28, - 0x02, 0xd1, 0x28, 0x46, 0xff, 0xf7, 0xbc, 0xff, 0xbd, 0xe8, 0x31, 0x40, - 0xfe, 0xf7, 0xd3, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0xfe, 0xf7, - 0xb9, 0xfa, 0x00, 0xf0, 0xa4, 0xf8, 0x0c, 0xbf, 0x4c, 0x68, 0x8c, 0x68, - 0xac, 0xb1, 0xa2, 0x78, 0x1c, 0x23, 0x03, 0xfb, 0x02, 0x00, 0x90, 0xf8, - 0x30, 0x21, 0x03, 0x2a, 0x00, 0xd0, 0x8c, 0xe0, 0x4f, 0xf0, 0xff, 0x32, - 0x0a, 0x60, 0x04, 0x21, 0x80, 0xf8, 0x30, 0x11, 0x20, 0x46, 0xff, 0xf7, - 0x9b, 0xff, 0x00, 0xf0, 0x86, 0xf8, 0x00, 0xf0, 0xc1, 0xfa, 0xfe, 0xf7, - 0xb0, 0xfa, 0x00, 0x20, 0x16, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, 0x83, 0xb0, - 0x88, 0x46, 0x14, 0x46, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, - 0x07, 0xfd, 0xfe, 0xf7, 0x8d, 0xfa, 0x00, 0xf0, 0xf9, 0xfc, 0xc7, 0xb2, - 0x38, 0x46, 0x00, 0xf0, 0xef, 0xfc, 0x05, 0x46, 0xdf, 0xf8, 0x8c, 0x99, - 0x1c, 0x20, 0x00, 0xfb, 0x07, 0x90, 0x00, 0xf5, 0x98, 0x76, 0x01, 0x20, - 0x30, 0x70, 0x39, 0x46, 0x0a, 0x20, 0x04, 0xf0, 0xd5, 0xfb, 0x28, 0x46, - 0xff, 0xf7, 0x31, 0xff, 0x38, 0x02, 0x40, 0xf0, 0x07, 0x00, 0x70, 0x61, - 0x06, 0xf1, 0x14, 0x01, 0xdf, 0xf8, 0x98, 0x0c, 0x00, 0x68, 0xfe, 0xf7, - 0x16, 0xff, 0x40, 0x1e, 0x00, 0xf0, 0x8f, 0xfa, 0xfe, 0xf7, 0x7b, 0xfa, - 0x01, 0xa8, 0x00, 0x90, 0x43, 0x46, 0x68, 0x68, 0x83, 0x22, 0x10, 0x21, - 0xfe, 0xf7, 0xe8, 0xfc, 0x9d, 0xf8, 0x04, 0x10, 0x00, 0xf0, 0x80, 0xfa, - 0x03, 0x20, 0x04, 0xf0, 0x9d, 0xfc, 0x09, 0xf6, 0x6c, 0x40, 0x20, 0x60, - 0x00, 0x20, 0xbd, 0xe8, 0xfe, 0x83, 0x10, 0xb5, 0xef, 0xf3, 0x05, 0x80, - 0x08, 0xb1, 0x00, 0xf0, 0xc3, 0xfc, 0xfe, 0xf7, 0x49, 0xfa, 0x00, 0xf0, - 0xb5, 0xfc, 0x00, 0xf0, 0x6a, 0xf8, 0xdf, 0xf8, 0x0c, 0x19, 0xe4, 0xb2, - 0x1c, 0x22, 0x02, 0xfb, 0x04, 0x11, 0x00, 0x20, 0x81, 0xf8, 0x30, 0x01, - 0xfe, 0xf7, 0x4f, 0xfa, 0x00, 0x20, 0x10, 0xbd, 0x10, 0xb5, 0x82, 0xb0, - 0x04, 0x46, 0xfe, 0xf7, 0x33, 0xfa, 0x00, 0xf0, 0x1e, 0xf8, 0x0c, 0xbf, - 0x4c, 0x68, 0x8c, 0x68, 0x7c, 0xb1, 0xa2, 0x78, 0x0a, 0x60, 0x1c, 0x23, - 0x03, 0xfb, 0x02, 0x00, 0x02, 0x21, 0x80, 0xf8, 0x30, 0x11, 0x03, 0x20, - 0x04, 0xf0, 0x4a, 0xfc, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0xf0, 0x42, 0xfa, - 0x7f, 0xe7, 0xfe, 0xf7, 0x30, 0xfa, 0x01, 0x20, 0x16, 0xbd, 0x60, 0x68, - 0x6b, 0x46, 0x01, 0x22, 0x10, 0x21, 0xfe, 0xf7, 0x29, 0xbd, 0xdf, 0xf8, - 0xa8, 0x08, 0x00, 0xf5, 0x4a, 0x71, 0x00, 0x2c, 0x70, 0x47, 0x2d, 0xe9, - 0xfc, 0x41, 0x04, 0x46, 0x88, 0x46, 0x16, 0x46, 0xef, 0xf3, 0x05, 0x80, - 0x08, 0xb1, 0x00, 0xf0, 0x7b, 0xfc, 0xfe, 0xf7, 0x01, 0xfa, 0x00, 0xf0, - 0x6d, 0xfc, 0x05, 0x46, 0x00, 0xf0, 0x22, 0xf8, 0x07, 0x46, 0xdf, 0xf8, - 0x78, 0x08, 0xed, 0xb2, 0x1c, 0x21, 0x01, 0xfb, 0x05, 0x01, 0x01, 0xf5, - 0x98, 0x71, 0x03, 0x22, 0x00, 0xf6, 0x6c, 0x40, 0x0a, 0x70, 0x48, 0x60, - 0xce, 0x60, 0x0c, 0x74, 0xfe, 0xf7, 0xff, 0xf9, 0x01, 0xa8, 0x00, 0x90, - 0x43, 0x46, 0x78, 0x68, 0x83, 0x22, 0x10, 0x21, 0xfe, 0xf7, 0x6c, 0xfc, - 0x9d, 0xf8, 0x04, 0x10, 0x00, 0xf0, 0x04, 0xfa, 0x00, 0x20, 0xbd, 0xe8, - 0xf6, 0x81, 0x04, 0x46, 0xc0, 0xb2, 0x00, 0xf0, 0x3f, 0xbc, 0x30, 0xb5, - 0xdf, 0xf8, 0x2c, 0x48, 0x87, 0xb0, 0x14, 0x21, 0x04, 0xf2, 0x84, 0x40, - 0xfe, 0xf7, 0xc3, 0xfd, 0x20, 0x60, 0x00, 0xf0, 0x39, 0xf8, 0x03, 0x21, - 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, 0x80, 0x21, 0x02, 0x91, 0x03, 0x21, - 0xdf, 0xf8, 0x68, 0x0c, 0x01, 0x90, 0x00, 0x91, 0x00, 0xf5, 0xfe, 0x72, - 0x03, 0x23, 0x00, 0x21, 0x0f, 0xf6, 0xa9, 0x10, 0xfe, 0xf7, 0x8d, 0xff, - 0x40, 0x1e, 0x00, 0xf0, 0xdc, 0xf9, 0x05, 0xaa, 0x0f, 0xf2, 0x38, 0x01, - 0x03, 0x20, 0xff, 0xf7, 0x3b, 0xf8, 0x04, 0xf1, 0x4c, 0x00, 0x00, 0x21, - 0x01, 0x81, 0x04, 0xf5, 0x51, 0x75, 0x4f, 0xf6, 0xff, 0x71, 0x01, 0x80, - 0x4f, 0xf0, 0xff, 0x31, 0x29, 0x60, 0x69, 0x60, 0x00, 0x21, 0x81, 0x72, - 0x04, 0xf5, 0x59, 0x70, 0xe8, 0x60, 0x00, 0xf0, 0x44, 0xf8, 0x00, 0x20, - 0x28, 0x72, 0x28, 0x77, 0x07, 0xb0, 0x30, 0xbd, 0x43, 0x74, 0x72, 0x6c, - 0x54, 0x73, 0x6b, 0x00, 0x00, 0xb1, 0x01, 0x20, 0x04, 0xf0, 0x07, 0xba, - 0xf8, 0xb5, 0x00, 0x25, 0x00, 0x21, 0xdf, 0xf8, 0x98, 0x67, 0x20, 0xfa, - 0x01, 0xf2, 0xd2, 0x07, 0x03, 0xd5, 0x06, 0xeb, 0x81, 0x02, 0xd4, 0x6f, - 0x34, 0xb9, 0x49, 0x1c, 0x07, 0x29, 0xf4, 0xd3, 0x28, 0x46, 0xf2, 0xbd, - 0x00, 0x25, 0x14, 0x46, 0xe2, 0x6a, 0x00, 0x2a, 0xf5, 0xd0, 0x63, 0x7b, - 0xa5, 0x7b, 0x2b, 0x42, 0xf6, 0xd0, 0x01, 0x21, 0x20, 0x46, 0x00, 0xf0, - 0x7d, 0xfb, 0x20, 0x7b, 0x01, 0x25, 0x07, 0x46, 0x07, 0x28, 0xb4, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x04, 0xf0, 0xdf, 0xf9, 0x00, 0x20, 0xe0, 0x62, - 0x06, 0xeb, 0x87, 0x00, 0xc1, 0x6f, 0xc4, 0x67, 0x00, 0x29, 0xdf, 0xd0, - 0xe1, 0x62, 0xdd, 0xe7, 0xdf, 0xf8, 0x38, 0x07, 0x90, 0xf8, 0x54, 0x03, - 0x70, 0x47, 0xdf, 0xf8, 0xfc, 0x0b, 0x40, 0x89, 0x00, 0xf0, 0x03, 0x01, - 0xc0, 0xf3, 0x01, 0x10, 0x03, 0x28, 0x04, 0xd1, 0x03, 0x29, 0x0c, 0xd1, - 0x01, 0x20, 0x02, 0x21, 0x1f, 0xe0, 0x01, 0x28, 0x18, 0xbf, 0x02, 0x28, - 0x0d, 0xd1, 0x03, 0x29, 0x09, 0xd1, 0x01, 0x28, 0x13, 0xd1, 0x03, 0x20, - 0x14, 0xe0, 0x01, 0x29, 0x18, 0xbf, 0x02, 0x29, 0x0f, 0xd1, 0x08, 0x46, - 0x0f, 0xe0, 0x01, 0x28, 0x01, 0xd0, 0x02, 0x28, 0x09, 0xd1, 0x01, 0x29, - 0x18, 0xbf, 0x02, 0x29, 0x05, 0xd1, 0x01, 0x28, 0x01, 0xd1, 0x08, 0x46, - 0x02, 0xe0, 0x00, 0x20, 0x01, 0xe0, 0x00, 0x20, 0x00, 0x21, 0x40, 0xea, - 0x81, 0x00, 0xdf, 0xf8, 0xd0, 0x16, 0x81, 0xf8, 0xb8, 0x03, 0x70, 0x47, - 0xdf, 0xf8, 0xc4, 0x26, 0x92, 0xf8, 0xb8, 0x23, 0x01, 0x23, 0x03, 0xfa, - 0x00, 0xf0, 0x00, 0x21, 0x00, 0xea, 0x02, 0x03, 0x13, 0xf0, 0x03, 0x0f, - 0x18, 0xbf, 0x01, 0x21, 0x05, 0xd1, 0x00, 0xea, 0x92, 0x00, 0x10, 0xf0, - 0x03, 0x0f, 0x18, 0xbf, 0x02, 0x21, 0xdf, 0xf8, 0x68, 0x0b, 0x40, 0x89, - 0x01, 0xea, 0x10, 0x10, 0x40, 0x1e, 0x40, 0xb2, 0x70, 0x47, 0xdf, 0xf8, - 0x8c, 0x06, 0xd0, 0xf8, 0x64, 0x13, 0xca, 0x03, 0x05, 0xd5, 0x90, 0xf8, - 0xba, 0x23, 0x05, 0x2a, 0x01, 0xd1, 0x05, 0x20, 0x70, 0x47, 0x49, 0x07, - 0x03, 0xd5, 0x90, 0xf8, 0xba, 0x03, 0x01, 0x28, 0x00, 0xd0, 0xff, 0x20, - 0x70, 0x47, 0xdf, 0xf8, 0x64, 0x06, 0xd0, 0xf8, 0x64, 0x13, 0x8a, 0x03, - 0x05, 0xd5, 0x90, 0xf8, 0xbb, 0x23, 0x06, 0x2a, 0x01, 0xd1, 0x06, 0x20, - 0x70, 0x47, 0x09, 0x07, 0x03, 0xd5, 0x90, 0xf8, 0xbb, 0x03, 0x02, 0x28, - 0x00, 0xd0, 0xff, 0x20, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, - 0x47, 0xfb, 0x84, 0x42, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x10, 0xbd, - 0x2d, 0xe9, 0xf1, 0x4f, 0x0c, 0x46, 0xdf, 0xf8, 0x24, 0x86, 0xdf, 0xf8, - 0xf0, 0xaa, 0x15, 0x46, 0x01, 0x26, 0x04, 0xf0, 0x04, 0x0b, 0x08, 0xf2, - 0xb9, 0x39, 0x00, 0x98, 0xf0, 0x40, 0xc0, 0x07, 0x6d, 0xd5, 0x08, 0xeb, - 0x86, 0x00, 0xc7, 0x6f, 0x23, 0xe0, 0x38, 0x78, 0x05, 0x28, 0x09, 0xd1, - 0xff, 0xf7, 0xb5, 0xff, 0x85, 0x42, 0x66, 0xd0, 0x03, 0x2d, 0x03, 0xd1, - 0x99, 0xf8, 0x03, 0x00, 0x00, 0x28, 0x60, 0xd1, 0x38, 0x78, 0x06, 0x28, - 0x09, 0xd1, 0xff, 0xf7, 0xbc, 0xff, 0x85, 0x42, 0x59, 0xd0, 0x03, 0x2d, - 0x03, 0xd1, 0x99, 0xf8, 0x03, 0x00, 0x00, 0x28, 0x53, 0xd1, 0x38, 0x78, - 0x01, 0x28, 0x01, 0xd1, 0xe1, 0x07, 0x4e, 0xd4, 0x02, 0x28, 0x01, 0xd1, - 0xa0, 0x07, 0x4a, 0xd4, 0xff, 0x6a, 0x00, 0x2f, 0x43, 0xd0, 0x78, 0x7b, - 0x00, 0x28, 0xf9, 0xd0, 0x79, 0x88, 0xd8, 0xf8, 0x48, 0x03, 0x11, 0xf8, - 0x0a, 0x10, 0xc8, 0x40, 0xc0, 0x07, 0xf1, 0xd5, 0x38, 0x7b, 0x01, 0x28, - 0x18, 0xbf, 0x04, 0x28, 0x25, 0xd0, 0x05, 0x28, 0xc7, 0xd0, 0x02, 0x28, - 0x1f, 0xd1, 0x39, 0x78, 0x99, 0xf8, 0x00, 0x00, 0x03, 0x29, 0x0c, 0xd1, - 0xbb, 0xf1, 0x00, 0x0f, 0xe0, 0xd0, 0x03, 0x2d, 0x29, 0xd0, 0x01, 0x2d, - 0x02, 0xd1, 0xc0, 0x07, 0xda, 0xd5, 0x24, 0xe0, 0x02, 0x2d, 0xd7, 0xd1, - 0x0b, 0xe0, 0x04, 0x29, 0xd4, 0xd1, 0x21, 0x07, 0xd2, 0xd5, 0x03, 0x2d, - 0x1b, 0xd0, 0x02, 0x2d, 0x01, 0xd1, 0x00, 0x07, 0xf0, 0xe7, 0x01, 0x2d, - 0xca, 0xd1, 0x80, 0x07, 0xec, 0xe7, 0x03, 0x28, 0xc6, 0xd1, 0x39, 0x78, - 0x03, 0x29, 0x03, 0xd1, 0xbb, 0xf1, 0x00, 0x0f, 0x04, 0xd1, 0xbf, 0xe7, - 0x04, 0x29, 0xbd, 0xd1, 0x20, 0x07, 0xbb, 0xd5, 0x03, 0x2d, 0xb9, 0xd1, - 0x03, 0xe0, 0x76, 0x1c, 0x07, 0x2e, 0x8a, 0xdb, 0x00, 0x27, 0x38, 0x46, - 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0xec, 0x59, - 0x80, 0x46, 0x95, 0xf8, 0x4c, 0x00, 0xc0, 0x07, 0x0e, 0x46, 0x04, 0xd5, - 0x28, 0x7a, 0x01, 0x28, 0x08, 0xbf, 0x00, 0x20, 0x2d, 0xd0, 0x2c, 0x6d, - 0xc6, 0xf3, 0x02, 0x17, 0x4c, 0xb1, 0x20, 0x46, 0xff, 0xf7, 0xaa, 0xfe, - 0x28, 0xb1, 0x3a, 0x46, 0x31, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x5e, 0xff, - 0x20, 0xb9, 0x3a, 0x46, 0x31, 0x46, 0x7f, 0x20, 0xff, 0xf7, 0x58, 0xff, - 0x00, 0x28, 0xa9, 0x7a, 0x14, 0xbf, 0x07, 0x7b, 0x00, 0x27, 0x79, 0xb1, - 0x2e, 0x88, 0xf0, 0xb2, 0x00, 0xf0, 0x8a, 0xfa, 0xb8, 0xf1, 0x00, 0x0f, - 0x04, 0xbf, 0x00, 0x7b, 0xb8, 0x42, 0x0c, 0xd0, 0xe8, 0x7a, 0x50, 0xb9, - 0xf0, 0xb2, 0x00, 0xf0, 0x07, 0xf9, 0x06, 0xe0, 0x00, 0x2e, 0x04, 0xd4, - 0x18, 0xb1, 0x40, 0x88, 0x31, 0x46, 0xff, 0xf7, 0x9d, 0xfc, 0x00, 0x20, - 0xbd, 0xe8, 0xf0, 0x81, 0x70, 0xb5, 0x04, 0x00, 0x14, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0x04, 0xf0, 0x7e, 0xf8, 0x20, 0x68, 0x0f, 0x28, 0x00, 0xf0, - 0x28, 0xf8, 0x25, 0x68, 0xdf, 0xf8, 0x80, 0x24, 0xd2, 0xf8, 0xbc, 0x60, - 0x28, 0x46, 0x41, 0x08, 0x02, 0xeb, 0xc1, 0x01, 0x01, 0xf1, 0xc0, 0x03, - 0xf8, 0x31, 0xc6, 0x40, 0xf6, 0x07, 0x04, 0xd5, 0xbd, 0xe8, 0x70, 0x40, - 0x01, 0x21, 0x04, 0xf0, 0xa7, 0xb9, 0x1d, 0x60, 0x01, 0x25, 0x64, 0x68, - 0x5c, 0x60, 0x05, 0xfa, 0x00, 0xf0, 0xd2, 0xf8, 0xbc, 0x40, 0x20, 0x43, - 0xc2, 0xf8, 0xbc, 0x00, 0x0d, 0x60, 0x4b, 0x60, 0x08, 0x46, 0xbd, 0xe8, - 0x70, 0x40, 0x5d, 0xe4, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, 0x80, 0x41, - 0xc0, 0x0f, 0x04, 0xf0, 0x4e, 0xb8, 0xf8, 0xb5, 0x06, 0x46, 0x37, 0x68, - 0x0e, 0x2f, 0x20, 0xd2, 0x00, 0x21, 0x38, 0x46, 0xdf, 0xf8, 0x1c, 0x44, - 0x04, 0xf0, 0x6e, 0xf9, 0x04, 0xf1, 0x54, 0x05, 0xf8, 0xb2, 0x29, 0x78, - 0x05, 0xf0, 0x56, 0xfb, 0x00, 0x28, 0x40, 0xf0, 0xa6, 0x80, 0x6f, 0xb1, - 0x02, 0x2f, 0x10, 0xd0, 0x04, 0x2f, 0x19, 0xd0, 0x06, 0x2f, 0x5f, 0xd0, - 0x08, 0x2f, 0x4f, 0xd0, 0x0a, 0x2f, 0x69, 0xd0, 0x0c, 0x2f, 0x00, 0xf0, - 0x80, 0x80, 0x93, 0xe0, 0x70, 0x68, 0x00, 0xf0, 0x8f, 0xfb, 0x00, 0x20, - 0xf2, 0xbd, 0x74, 0x68, 0x0e, 0x20, 0x04, 0xf0, 0xe6, 0xf8, 0x01, 0x20, - 0x28, 0x70, 0x00, 0x21, 0x20, 0x46, 0x05, 0xf0, 0xbd, 0xfb, 0xf2, 0xe7, - 0x10, 0x20, 0x04, 0xf0, 0xdc, 0xf8, 0x04, 0xf0, 0x0c, 0xfe, 0x01, 0x00, - 0x06, 0xd0, 0x04, 0x20, 0x04, 0xf0, 0x52, 0xf9, 0x04, 0x20, 0x00, 0xf0, - 0x62, 0xfb, 0xe4, 0xe7, 0x04, 0x20, 0x28, 0x70, 0x1c, 0x21, 0x00, 0x20, - 0xa8, 0x64, 0x04, 0xf1, 0xa0, 0x00, 0x03, 0xf0, 0x59, 0xfe, 0x00, 0xf0, - 0xfd, 0xfb, 0x48, 0xb1, 0x4f, 0xf0, 0x7f, 0x42, 0x40, 0xf6, 0xff, 0x73, - 0x00, 0x20, 0x00, 0xf0, 0x0d, 0xf9, 0x68, 0x46, 0x05, 0xf0, 0x7d, 0xfb, - 0xff, 0xf7, 0x06, 0xfb, 0x07, 0x22, 0x00, 0x23, 0x03, 0x20, 0x00, 0xf0, - 0x03, 0xf9, 0x04, 0x20, 0x00, 0xf0, 0x41, 0xfb, 0x00, 0x25, 0x6c, 0x20, - 0x00, 0xfb, 0x05, 0x40, 0x00, 0xf2, 0x14, 0x50, 0x05, 0xf0, 0x32, 0xfc, - 0x6d, 0x1c, 0x12, 0x2d, 0xf5, 0xd3, 0xb8, 0xe7, 0x74, 0x68, 0x12, 0x20, - 0x04, 0xf0, 0xa1, 0xf8, 0x21, 0x46, 0x00, 0x20, 0x05, 0xf0, 0x2a, 0xfc, - 0x01, 0x46, 0x08, 0x20, 0x04, 0xf0, 0x16, 0xf9, 0x08, 0x20, 0xc2, 0xe7, - 0x74, 0x68, 0x11, 0x20, 0x04, 0xf0, 0x93, 0xf8, 0x21, 0x46, 0x01, 0x20, - 0x05, 0xf0, 0x1c, 0xfc, 0x01, 0x46, 0x06, 0x20, 0x04, 0xf0, 0x08, 0xf9, - 0x06, 0x20, 0xb4, 0xe7, 0x74, 0x68, 0x14, 0x20, 0x04, 0xf0, 0x85, 0xf8, - 0x29, 0x78, 0xe0, 0xb2, 0x05, 0xf0, 0xc6, 0xfa, 0x48, 0xb9, 0xc4, 0xf3, - 0x42, 0x10, 0x03, 0x28, 0x04, 0xd1, 0x01, 0x21, 0x20, 0x46, 0x00, 0xf0, - 0xf9, 0xfb, 0x00, 0xe0, 0x04, 0x20, 0x01, 0x46, 0x0a, 0x20, 0x04, 0xf0, - 0xef, 0xf8, 0x0a, 0x20, 0x9b, 0xe7, 0x74, 0x68, 0x20, 0x06, 0x45, 0x0f, - 0x13, 0x20, 0x04, 0xf0, 0x6a, 0xf8, 0x03, 0x2d, 0x18, 0xbf, 0x02, 0x2d, - 0x11, 0xbf, 0x04, 0x20, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0xe2, 0xfb, - 0x01, 0x46, 0x0c, 0x20, 0x04, 0xf0, 0xda, 0xf8, 0x0c, 0x20, 0x86, 0xe7, - 0x03, 0xf0, 0x95, 0xff, 0x6b, 0xe7, 0x80, 0x28, 0x03, 0xd1, 0x38, 0x46, - 0x00, 0xf0, 0xe3, 0xfa, 0x65, 0xe7, 0x01, 0x46, 0x38, 0x46, 0x04, 0xf0, - 0xcb, 0xf8, 0xf6, 0xe7, 0x10, 0xb5, 0x82, 0xb0, 0x00, 0xf0, 0x74, 0xf9, - 0x04, 0x46, 0x20, 0x7e, 0x05, 0x28, 0x1c, 0xbf, 0x04, 0x20, 0x20, 0x76, - 0x02, 0x20, 0x04, 0xf0, 0x2b, 0xf9, 0x60, 0x68, 0x6b, 0x46, 0x01, 0x22, - 0x01, 0x21, 0xfe, 0xf7, 0x13, 0xfa, 0xff, 0xf7, 0x1f, 0xff, 0xdf, 0xf8, - 0x70, 0x1b, 0x01, 0x20, 0x81, 0xf8, 0x57, 0x00, 0x06, 0x20, 0x04, 0xf0, - 0x30, 0xf8, 0x00, 0x20, 0x16, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0xff, 0xf7, 0x12, 0xfd, 0x06, 0x46, 0xb0, 0x7b, 0x28, 0xb1, 0xe0, 0xb2, - 0x00, 0xf0, 0xb2, 0xf8, 0x05, 0x20, 0x04, 0xf0, 0x20, 0xf8, 0x00, 0x20, - 0x70, 0x73, 0xb0, 0x73, 0x01, 0x21, 0x30, 0x46, 0x00, 0xf0, 0xea, 0xf8, - 0xe0, 0xb2, 0x05, 0xf0, 0x57, 0xfb, 0xdf, 0xf8, 0x2c, 0x1b, 0x01, 0xeb, - 0x84, 0x01, 0x00, 0x20, 0x48, 0x60, 0x30, 0x69, 0xff, 0xf7, 0x3e, 0xfd, - 0x70, 0x6a, 0x33, 0x69, 0x00, 0x22, 0x29, 0x46, 0x98, 0x47, 0x00, 0x20, - 0x70, 0xbd, 0xf0, 0xb5, 0x83, 0xb0, 0x07, 0x46, 0x00, 0xf0, 0x2c, 0xf9, - 0x04, 0x46, 0x02, 0x20, 0x04, 0xf0, 0x06, 0xf9, 0x20, 0x7e, 0xdf, 0xf8, - 0xf8, 0x5a, 0x05, 0x28, 0x05, 0xf1, 0x4c, 0x06, 0x11, 0xd1, 0x01, 0x21, - 0x38, 0x46, 0xff, 0xf7, 0xc4, 0xff, 0x30, 0x7a, 0x05, 0x28, 0x0a, 0xd1, - 0x03, 0x20, 0x30, 0x72, 0x04, 0xf0, 0x13, 0xfc, 0x00, 0xf0, 0x35, 0xf8, - 0x04, 0xf0, 0x1e, 0xf9, 0x00, 0x20, 0x00, 0xf0, 0x74, 0xfa, 0x00, 0x20, - 0x60, 0x73, 0x02, 0x20, 0x20, 0x76, 0x4f, 0xf6, 0xff, 0x70, 0x30, 0x80, - 0x00, 0x20, 0x70, 0x81, 0x00, 0x2f, 0x04, 0xbf, 0x30, 0x7a, 0x05, 0x28, - 0x0a, 0xd1, 0x08, 0x20, 0x00, 0x90, 0x4f, 0xf0, 0xff, 0x30, 0x01, 0x90, - 0x68, 0x46, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0x20, 0x00, 0xf0, 0x5b, 0xfa, - 0x20, 0x7b, 0x05, 0xeb, 0x80, 0x01, 0x01, 0x22, 0xc9, 0x6f, 0x04, 0xe0, - 0x4b, 0x7b, 0x01, 0x2b, 0x08, 0xbf, 0x00, 0x22, 0xc9, 0x6a, 0x00, 0x29, - 0xf8, 0xd1, 0x32, 0xb1, 0xf1, 0x6c, 0x01, 0x22, 0x02, 0xfa, 0x00, 0xf0, - 0x21, 0xea, 0x00, 0x00, 0xf0, 0x64, 0x00, 0x20, 0xfe, 0xbd, 0x07, 0x22, - 0x00, 0x23, 0x02, 0x20, 0x00, 0x21, 0x04, 0xf0, 0x39, 0xb8, 0xf8, 0xb5, - 0x06, 0x46, 0x00, 0x20, 0x00, 0xf0, 0xd4, 0xf8, 0xdf, 0xf8, 0x50, 0x5a, - 0xd5, 0xf8, 0xc8, 0x70, 0x05, 0xf1, 0x54, 0x04, 0xa0, 0x6e, 0x80, 0x08, - 0x00, 0xf0, 0x01, 0x00, 0x03, 0xf0, 0xd9, 0xfe, 0x02, 0x2f, 0x0c, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0xd3, 0xfe, 0x71, 0x68, 0xc9, 0xb2, - 0x38, 0x46, 0x04, 0xf0, 0x0f, 0xf8, 0x38, 0x46, 0x00, 0xf0, 0x1f, 0xfa, - 0x70, 0x68, 0x70, 0xb9, 0x05, 0xf0, 0x93, 0xfc, 0x48, 0xb1, 0x03, 0x20, - 0x20, 0x70, 0x01, 0x20, 0x85, 0xf8, 0x4c, 0x03, 0x04, 0xf0, 0xab, 0xfb, - 0xff, 0xf7, 0xcd, 0xff, 0x08, 0xe0, 0x02, 0x20, 0x05, 0xe0, 0x95, 0xf8, - 0x4c, 0x03, 0x00, 0x28, 0x14, 0xbf, 0x03, 0x20, 0x02, 0x20, 0x20, 0x70, - 0x01, 0x21, 0x00, 0x20, 0xff, 0xf7, 0x45, 0xff, 0x00, 0x20, 0xf2, 0xbd, - 0x80, 0xb5, 0x00, 0xf0, 0x99, 0xf8, 0x00, 0x21, 0x81, 0x73, 0x02, 0x7b, - 0xdf, 0xf8, 0xd4, 0x19, 0x01, 0xeb, 0x82, 0x02, 0xd2, 0xf8, 0xa0, 0x30, - 0x5b, 0x1e, 0xc2, 0xf8, 0xa0, 0x30, 0x00, 0x7b, 0x01, 0xeb, 0x80, 0x02, - 0xd2, 0xf8, 0xa0, 0x20, 0x42, 0xb9, 0xd1, 0xf8, 0x9c, 0x20, 0x01, 0x23, - 0x03, 0xfa, 0x00, 0xf0, 0x22, 0xea, 0x00, 0x00, 0xc1, 0xf8, 0x9c, 0x00, - 0x00, 0x20, 0x02, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x20, 0x7b, - 0x06, 0x46, 0x07, 0x28, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, - 0x82, 0xfe, 0x00, 0x20, 0xe0, 0x62, 0x00, 0x2d, 0x23, 0x48, 0x0c, 0xbf, - 0x60, 0x30, 0x7c, 0x30, 0x50, 0xf8, 0x26, 0x10, 0x19, 0xb9, 0x40, 0xf8, - 0x26, 0x40, 0x04, 0xe0, 0x01, 0x46, 0xc8, 0x6a, 0x00, 0x28, 0xfb, 0xd1, - 0xcc, 0x62, 0x00, 0x20, 0x70, 0xbd, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x20, - 0xf8, 0xb5, 0x06, 0x46, 0x0f, 0x46, 0x30, 0x7b, 0x04, 0x46, 0x07, 0x28, - 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x60, 0xfe, 0xdf, 0xf8, - 0x48, 0x19, 0x00, 0x2f, 0x0c, 0xbf, 0x01, 0xf1, 0x60, 0x02, 0x01, 0xf1, - 0x7c, 0x02, 0x52, 0xf8, 0x24, 0x00, 0xb0, 0x42, 0x11, 0xd1, 0xc3, 0x6a, - 0x42, 0xf8, 0x24, 0x30, 0x3b, 0xb9, 0x04, 0x7b, 0xd1, 0xf8, 0x98, 0x20, - 0x01, 0x23, 0xa3, 0x40, 0x9a, 0x43, 0xc1, 0xf8, 0x98, 0x20, 0x00, 0x21, - 0xc1, 0x62, 0x00, 0x20, 0xf2, 0xbd, 0x05, 0x46, 0xc0, 0x6a, 0x00, 0x28, - 0x18, 0xbf, 0xb0, 0x42, 0xf9, 0xd1, 0xb0, 0x42, 0x02, 0xd1, 0xc1, 0x6a, - 0xe9, 0x62, 0xf0, 0xe7, 0x01, 0x20, 0xf2, 0xbd, 0xb8, 0x04, 0x00, 0x20, - 0xdf, 0xf8, 0xf0, 0x18, 0xdf, 0xf8, 0xc4, 0x24, 0xd1, 0xf8, 0x50, 0x13, - 0x80, 0x5c, 0x1d, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, - 0x10, 0xb5, 0x04, 0x46, 0x04, 0x2c, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0x03, 0xf0, 0x21, 0xfe, 0xdf, 0xf8, 0xc8, 0x08, 0x00, 0xeb, 0x84, 0x00, - 0xd0, 0xf8, 0xa8, 0x43, 0x04, 0xf0, 0x4a, 0xf8, 0xa0, 0x42, 0x34, 0xbf, - 0x20, 0x1a, 0x00, 0x20, 0x10, 0xbd, 0x00, 0x00, 0x65, 0x2c, 0x00, 0x20, - 0xdf, 0xf8, 0xa8, 0x18, 0x01, 0xeb, 0x80, 0x00, 0x40, 0x68, 0x70, 0x47, - 0x80, 0xb5, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0x00, 0xf0, 0x04, 0xf8, - 0xdf, 0xf8, 0x94, 0x08, 0x00, 0x68, 0x02, 0xbd, 0x00, 0x20, 0x03, 0xf0, - 0xfe, 0xbd, 0x80, 0xb5, 0xff, 0xf7, 0xf0, 0xff, 0xdf, 0xf8, 0x54, 0x14, - 0x40, 0x5c, 0x02, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, 0x78, 0x48, 0x20, 0x68, - 0x10, 0xf1, 0x01, 0x0f, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, - 0xec, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0xe6, 0xff, - 0x20, 0x68, 0xc0, 0xb2, 0xff, 0xf7, 0xd2, 0xff, 0x04, 0x00, 0x14, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0xdd, 0xfd, 0x60, 0x68, 0x10, 0xbd, - 0xf8, 0xb5, 0x00, 0xf0, 0x56, 0xf8, 0x0e, 0x46, 0x14, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0x03, 0xf0, 0xd2, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, - 0xff, 0xf7, 0xcc, 0xff, 0x67, 0x00, 0x01, 0x20, 0x00, 0x21, 0x07, 0xf1, - 0x18, 0x02, 0x02, 0xf0, 0xe5, 0xff, 0x04, 0x46, 0x0d, 0x46, 0x01, 0x20, - 0x00, 0x21, 0x07, 0xf1, 0x19, 0x02, 0x02, 0xf0, 0xdd, 0xff, 0x03, 0x2e, - 0x14, 0xd8, 0xdf, 0xe8, 0x06, 0xf0, 0x02, 0x07, 0x0a, 0x0d, 0x22, 0x46, - 0x2b, 0x46, 0x20, 0x46, 0x29, 0x46, 0x09, 0xe0, 0x22, 0x46, 0x2b, 0x46, - 0x04, 0xe0, 0x02, 0x46, 0x0b, 0x46, 0x03, 0xe0, 0x02, 0x46, 0x0b, 0x46, - 0x00, 0x20, 0x00, 0x21, 0x03, 0xf0, 0xf6, 0xfe, 0x00, 0x20, 0xf2, 0xbd, - 0x10, 0xb5, 0x82, 0xb0, 0xff, 0xf7, 0x96, 0xff, 0xc0, 0xb2, 0xff, 0xf7, - 0x8d, 0xff, 0x00, 0xf0, 0x1a, 0xf8, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0x03, 0xf0, 0x97, 0xfd, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, - 0x91, 0xff, 0x60, 0x68, 0x6b, 0x46, 0x00, 0x22, 0x08, 0x21, 0xfe, 0xf7, - 0x29, 0xf8, 0xff, 0xf7, 0x35, 0xfd, 0xa0, 0x6a, 0x69, 0x46, 0xfe, 0xf7, - 0xbd, 0xfc, 0xff, 0xf7, 0x2f, 0xfd, 0x00, 0x20, 0x16, 0xbd, 0x04, 0x46, - 0xdf, 0xf8, 0x8c, 0x07, 0x00, 0x68, 0x10, 0xf1, 0x01, 0x0f, 0x70, 0x47, - 0x00, 0xb5, 0xdf, 0xf8, 0x80, 0x07, 0x83, 0xb0, 0x00, 0x68, 0x10, 0xf1, - 0x01, 0x0f, 0x14, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x6f, 0xfd, - 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0x69, 0xff, 0xff, 0xf7, - 0x71, 0xff, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x08, 0x21, - 0xfd, 0xf7, 0x72, 0xff, 0x00, 0x20, 0x0e, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, - 0x82, 0xb0, 0x04, 0xf0, 0xa8, 0xf8, 0xdf, 0xf8, 0x44, 0x07, 0xdf, 0xf8, - 0x38, 0x47, 0x03, 0xf0, 0x5b, 0xfe, 0x04, 0xf1, 0x54, 0x05, 0x02, 0x20, - 0x28, 0x70, 0x01, 0x26, 0x00, 0x20, 0xc0, 0x46, 0x07, 0x22, 0x00, 0x23, - 0x01, 0x20, 0xff, 0xf7, 0x5b, 0xfe, 0x03, 0xf0, 0x9d, 0xff, 0x20, 0x65, - 0x09, 0xe0, 0x40, 0x46, 0xff, 0xf7, 0x57, 0xfe, 0x21, 0x6d, 0x48, 0x46, - 0xff, 0xf7, 0x76, 0xfc, 0x01, 0x20, 0x03, 0xf0, 0x07, 0xff, 0x20, 0x68, - 0x6a, 0x46, 0x00, 0x21, 0xfe, 0xf7, 0xfb, 0xf8, 0x80, 0x46, 0x01, 0x20, - 0xd8, 0xf8, 0x00, 0xa0, 0x03, 0xf0, 0xde, 0xfe, 0x5f, 0xfa, 0x8a, 0xf0, - 0x0a, 0x28, 0x4f, 0xea, 0x1a, 0x27, 0x4f, 0xf0, 0x00, 0x09, 0xe5, 0xd8, - 0xdf, 0xe8, 0x00, 0xf0, 0x08, 0x13, 0x37, 0x46, 0x4a, 0x06, 0x06, 0x06, - 0x07, 0x56, 0x69, 0x00, 0xdc, 0xe7, 0xd8, 0xe7, 0x84, 0xf8, 0x60, 0x93, - 0x03, 0xf0, 0x70, 0xff, 0x01, 0x46, 0x21, 0x65, 0x02, 0x20, 0x03, 0xf0, - 0xf7, 0xfd, 0xb1, 0x46, 0xd0, 0xe7, 0xb4, 0xf8, 0xc0, 0x03, 0xd8, 0xf8, - 0x04, 0x30, 0x04, 0xeb, 0xc0, 0x00, 0x00, 0xf5, 0x71, 0x72, 0xd3, 0xe9, - 0x00, 0x01, 0xc2, 0xe9, 0x00, 0x01, 0xd8, 0xf8, 0x04, 0x00, 0xff, 0xf7, - 0xb4, 0xfc, 0xb4, 0xf8, 0xc0, 0x03, 0xdf, 0xf8, 0x94, 0x16, 0x09, 0x68, - 0x04, 0xeb, 0x80, 0x00, 0xc0, 0xf8, 0x44, 0x14, 0xb4, 0xf8, 0xc0, 0x03, - 0x40, 0x1c, 0xa4, 0xf8, 0xc0, 0x03, 0x80, 0xb2, 0x10, 0x28, 0xaf, 0xdb, - 0xa4, 0xf8, 0xc0, 0x93, 0xac, 0xe7, 0x28, 0x78, 0x05, 0x28, 0xa9, 0xd0, - 0xf8, 0xb2, 0xff, 0xf7, 0xd7, 0xfe, 0x02, 0x7b, 0x69, 0x6c, 0x06, 0xfa, - 0x02, 0xf2, 0x11, 0x43, 0x69, 0x64, 0x06, 0x76, 0x46, 0x73, 0x9d, 0xe7, - 0xf8, 0xb2, 0xff, 0xf7, 0x9a, 0xfd, 0x99, 0xe7, 0xf8, 0xb2, 0xff, 0xf7, - 0xc7, 0xfe, 0x07, 0x46, 0x01, 0x21, 0xff, 0xf7, 0x69, 0xfe, 0x01, 0x21, - 0x38, 0x46, 0xff, 0xf7, 0x43, 0xfe, 0x8d, 0xe7, 0xf8, 0xb2, 0xff, 0xf7, - 0xbb, 0xfe, 0x02, 0x7b, 0xa9, 0x6c, 0x06, 0xfa, 0x02, 0xf2, 0x11, 0x43, - 0xa9, 0x64, 0x01, 0x7b, 0x04, 0xeb, 0x81, 0x01, 0xd1, 0xf8, 0xa0, 0x20, - 0x52, 0x1c, 0xc1, 0xf8, 0xa0, 0x20, 0x86, 0x73, 0x7a, 0xe7, 0xf8, 0xb2, - 0xff, 0xf7, 0x0c, 0xfe, 0x76, 0xe7, 0xdf, 0xf8, 0x08, 0x06, 0xdf, 0xf8, - 0xf8, 0x25, 0x00, 0x68, 0x41, 0x68, 0x11, 0x60, 0x90, 0xf8, 0x32, 0x10, - 0x01, 0x20, 0x03, 0xf0, 0x8f, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x72, 0xb6, - 0x03, 0xf0, 0xc1, 0xfd, 0xdf, 0xf8, 0xd4, 0x05, 0xd0, 0xf8, 0xbc, 0x10, - 0x01, 0x22, 0xa2, 0x40, 0x91, 0x43, 0xc0, 0xf8, 0xbc, 0x10, 0x62, 0xb6, - 0x10, 0xbd, 0x00, 0x00, 0x88, 0xf2, 0x00, 0x20, 0xfe, 0xb5, 0x0f, 0x20, - 0xdf, 0xf8, 0xb4, 0x55, 0x03, 0xf0, 0x57, 0xfd, 0x05, 0xf1, 0x4c, 0x04, - 0x20, 0x7a, 0x01, 0x28, 0x10, 0xd1, 0xa0, 0x7a, 0x28, 0xb1, 0x05, 0x20, - 0x20, 0x72, 0x00, 0x20, 0xff, 0xf7, 0xfe, 0xfc, 0x3f, 0xe0, 0x08, 0x20, - 0x01, 0x90, 0x4f, 0xf0, 0xff, 0x30, 0x02, 0x90, 0x01, 0xa8, 0xff, 0xf7, - 0x94, 0xfd, 0x33, 0xe0, 0x68, 0x46, 0x05, 0xf0, 0x25, 0xfb, 0x68, 0x46, - 0x05, 0xf0, 0xf5, 0xfa, 0x05, 0x20, 0x20, 0x72, 0x01, 0x26, 0x04, 0xf0, - 0x54, 0xf9, 0x05, 0xeb, 0x86, 0x00, 0x47, 0x68, 0x8f, 0xb1, 0x78, 0x88, - 0x22, 0x88, 0xc1, 0xb2, 0x91, 0x42, 0x08, 0xd1, 0x39, 0x7e, 0x05, 0x29, - 0x05, 0xd0, 0xc0, 0xb2, 0xff, 0xf7, 0xda, 0xfc, 0x05, 0x20, 0x38, 0x76, - 0x03, 0xe0, 0x01, 0x21, 0xc0, 0xb2, 0xff, 0xf7, 0xf2, 0xfc, 0x76, 0x1c, - 0x12, 0x2e, 0xe6, 0xdb, 0x20, 0x88, 0x4f, 0xf6, 0xff, 0x71, 0x88, 0x42, - 0x0d, 0xd1, 0x05, 0xf0, 0x1e, 0xfa, 0x50, 0xb1, 0x03, 0x20, 0x20, 0x72, - 0x04, 0xf0, 0x39, 0xf9, 0xff, 0xf7, 0x5b, 0xfd, 0x03, 0xf0, 0x44, 0xfe, - 0x00, 0x20, 0xff, 0xf7, 0x9a, 0xff, 0x00, 0x20, 0xfe, 0xbd, 0x10, 0xb5, - 0x82, 0xb0, 0xef, 0xf3, 0x05, 0x80, 0x08, 0xb1, 0xff, 0xf7, 0x3c, 0xfe, - 0xff, 0xf7, 0x30, 0xfe, 0xff, 0xf7, 0x42, 0xfe, 0x04, 0x00, 0x14, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x03, 0xf0, 0x33, 0xfc, 0x6b, 0x46, 0x02, 0x22, - 0x01, 0x21, 0x20, 0x46, 0xfd, 0xf7, 0xd4, 0xfd, 0x00, 0xf0, 0x01, 0x00, - 0x16, 0xbd, 0x10, 0xb5, 0x00, 0x24, 0xc0, 0xf3, 0x47, 0x12, 0x00, 0x2a, - 0x18, 0xbf, 0x01, 0x2a, 0x00, 0xf0, 0x1f, 0x00, 0x14, 0xd1, 0x02, 0x29, - 0x10, 0xd2, 0x0c, 0x23, 0x58, 0x43, 0x00, 0x2a, 0x0c, 0xbf, 0xdf, 0xf8, - 0xd0, 0x24, 0xdf, 0xf8, 0xd0, 0x24, 0x80, 0x18, 0x82, 0x68, 0x50, 0xf8, - 0x21, 0x10, 0xdf, 0xf8, 0xc8, 0x04, 0x05, 0xf0, 0x1d, 0xfb, 0x02, 0xe0, - 0x05, 0x24, 0x00, 0xe0, 0x04, 0x24, 0x20, 0x46, 0x10, 0xbd, 0x00, 0x00, - 0x68, 0x76, 0x00, 0x20, 0xf8, 0xb5, 0xdf, 0xf8, 0x90, 0x04, 0xd0, 0xf8, - 0x50, 0x03, 0x05, 0x68, 0x16, 0x48, 0x44, 0x89, 0x04, 0xf0, 0x03, 0x00, - 0xc4, 0xf3, 0x83, 0x01, 0x41, 0xea, 0x00, 0x11, 0x41, 0xea, 0x80, 0x11, - 0x41, 0xea, 0x00, 0x21, 0x41, 0xea, 0x80, 0x21, 0x41, 0xea, 0x00, 0x30, - 0x00, 0xea, 0x05, 0x06, 0xff, 0xf7, 0x6d, 0xfa, 0x05, 0x28, 0x0c, 0xbf, - 0x01, 0x27, 0x00, 0x27, 0xff, 0xf7, 0x7b, 0xfa, 0x06, 0x28, 0x0c, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x47, 0xea, 0x40, 0x00, 0x15, 0xea, 0x00, 0x40, - 0x07, 0xd0, 0x00, 0x90, 0x00, 0x98, 0x80, 0x0b, 0x00, 0xea, 0x94, 0x00, - 0x00, 0xf0, 0x0c, 0x00, 0x06, 0x43, 0x30, 0x46, 0xf2, 0xbd, 0x00, 0x00, - 0x78, 0x29, 0x00, 0x20, 0xf4, 0x1e, 0x00, 0x20, 0x04, 0x05, 0x00, 0x20, - 0xdf, 0xf8, 0x1c, 0x14, 0xd1, 0xf8, 0x64, 0x13, 0xc1, 0x40, 0x01, 0xf0, - 0x01, 0x00, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xba, 0xff, - 0xe0, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, - 0x00, 0x24, 0x85, 0xb0, 0x03, 0x46, 0xde, 0xb2, 0x0f, 0x46, 0x18, 0x0a, - 0x40, 0x2e, 0x4f, 0xea, 0x13, 0x4c, 0x00, 0xf0, 0x0f, 0x01, 0xdf, 0xf8, - 0xe4, 0x83, 0xdf, 0xf8, 0xfc, 0x53, 0x18, 0xbf, 0x41, 0x2e, 0x0c, 0xf0, - 0x01, 0x0e, 0x00, 0xf0, 0x03, 0x00, 0xc3, 0xf3, 0x07, 0x22, 0x08, 0xf5, - 0x51, 0x79, 0x2b, 0xd0, 0x42, 0x2e, 0x2e, 0xd0, 0x43, 0x2e, 0x32, 0xd0, - 0x44, 0x2e, 0x25, 0xd0, 0x60, 0x2e, 0x35, 0xd0, 0x61, 0x2e, 0x00, 0xf0, - 0x73, 0x81, 0x62, 0x2e, 0x68, 0xd0, 0x63, 0x2e, 0x00, 0xf0, 0x4d, 0x81, - 0x64, 0x2e, 0x00, 0xf0, 0x7b, 0x81, 0x65, 0x2e, 0x00, 0xf0, 0x80, 0x80, - 0x66, 0x2e, 0x00, 0xf0, 0x9c, 0x80, 0x67, 0x2e, 0x00, 0xf0, 0x1f, 0x81, - 0x69, 0x2e, 0x00, 0xf0, 0x39, 0x81, 0x6a, 0x2e, 0x00, 0xf0, 0x7a, 0x81, - 0x6b, 0x2e, 0x00, 0xf0, 0x7f, 0x81, 0x6c, 0x2e, 0x03, 0xd0, 0x6d, 0x2e, - 0x00, 0xf0, 0x3e, 0x81, 0x7d, 0xe1, 0x00, 0x2f, 0x00, 0xf0, 0x7a, 0x81, - 0x05, 0xf0, 0x17, 0xfb, 0x77, 0xe1, 0xc3, 0xf3, 0x07, 0x41, 0x10, 0x46, - 0xff, 0xf7, 0x3f, 0xff, 0x3f, 0xe1, 0x14, 0x22, 0xdf, 0xf8, 0x74, 0x13, - 0x28, 0x46, 0x05, 0xf0, 0x71, 0xfa, 0x6a, 0xe1, 0x16, 0x46, 0xe0, 0x46, - 0x30, 0x46, 0x05, 0xf0, 0x15, 0xfb, 0x00, 0x28, 0x00, 0xf0, 0xfb, 0x80, - 0x00, 0x2f, 0x30, 0x46, 0x11, 0xd0, 0x05, 0xf0, 0x6b, 0xfb, 0x18, 0xb9, - 0x08, 0xf0, 0x1f, 0x01, 0x00, 0x22, 0x06, 0xe0, 0x4f, 0xea, 0x08, 0x62, - 0x10, 0x0f, 0x08, 0xf0, 0x0f, 0x01, 0x00, 0xf0, 0x01, 0x02, 0x30, 0x46, - 0x05, 0xf0, 0x37, 0xfb, 0x4d, 0xe1, 0x05, 0xf0, 0x20, 0xfb, 0x07, 0x46, - 0x30, 0x46, 0x05, 0xf0, 0x4b, 0xfb, 0x80, 0x46, 0x30, 0x46, 0x05, 0xf0, - 0x51, 0xfb, 0x3f, 0x02, 0x18, 0xb9, 0x08, 0xf0, 0x1f, 0x00, 0x38, 0x43, - 0x36, 0xe1, 0xb8, 0xf1, 0x13, 0x0f, 0x08, 0xbf, 0x2f, 0x60, 0xe9, 0xd0, - 0x08, 0xf0, 0x0f, 0x00, 0x38, 0x43, 0x40, 0xf0, 0x10, 0x00, 0x2b, 0xe1, - 0x00, 0x2f, 0x40, 0xf0, 0x2f, 0x81, 0x00, 0x20, 0xfe, 0xf7, 0x69, 0xfd, - 0x06, 0x46, 0x00, 0x20, 0xfe, 0xf7, 0x6e, 0xfd, 0x46, 0xea, 0x00, 0x40, - 0x04, 0x90, 0x01, 0x20, 0xfe, 0xf7, 0x5f, 0xfd, 0x06, 0x46, 0x01, 0x20, - 0xfe, 0xf7, 0x64, 0xfd, 0x46, 0xea, 0x00, 0x40, 0x03, 0x90, 0x04, 0x22, - 0x04, 0xa9, 0x28, 0x46, 0x05, 0xf0, 0x1c, 0xfa, 0x04, 0x22, 0x03, 0xa9, - 0x28, 0x1d, 0x02, 0xe1, 0xd9, 0xf8, 0x00, 0x00, 0x00, 0x2f, 0xda, 0xd0, - 0x0f, 0x29, 0x03, 0xd1, 0x28, 0x68, 0xc9, 0xf8, 0x00, 0x00, 0x11, 0xe0, - 0xc3, 0xf3, 0x00, 0x32, 0x02, 0xeb, 0x41, 0x01, 0x14, 0x29, 0x28, 0xbf, - 0x04, 0x24, 0x01, 0x22, 0x02, 0xfa, 0x01, 0xf1, 0x9a, 0x04, 0x4c, 0xbf, - 0x08, 0x43, 0x88, 0x43, 0x00, 0x2c, 0xc9, 0xf8, 0x00, 0x00, 0x01, 0xd1, - 0xfe, 0xf7, 0xfc, 0xfd, 0xf3, 0xe0, 0x56, 0x1e, 0x07, 0x2e, 0xc3, 0xf3, - 0x01, 0x41, 0xbc, 0xd8, 0xdf, 0xe8, 0x06, 0xf0, 0x04, 0x20, 0x57, 0x62, - 0x4c, 0x4c, 0x6c, 0x12, 0x00, 0x2f, 0x67, 0xd0, 0x5f, 0xfa, 0x8c, 0xf1, - 0x01, 0xf0, 0x03, 0x00, 0x49, 0x07, 0x02, 0xd5, 0xfc, 0xf7, 0x9c, 0xff, - 0xdd, 0xe0, 0xfc, 0xf7, 0x8b, 0xff, 0xda, 0xe0, 0x00, 0x2f, 0x76, 0x46, - 0x58, 0xd0, 0x29, 0x46, 0x30, 0x46, 0x03, 0xf0, 0x34, 0xf8, 0x00, 0x28, - 0x52, 0xd0, 0x29, 0x46, 0x30, 0x46, 0x02, 0xf0, 0xe4, 0xff, 0xcc, 0xe0, - 0xc3, 0xf3, 0x83, 0x46, 0x00, 0x2f, 0x18, 0xbf, 0x00, 0x2e, 0x0d, 0x46, - 0x46, 0xd0, 0x00, 0x27, 0x25, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x1b, 0xd5, - 0x00, 0x2f, 0x14, 0xbf, 0x09, 0x20, 0x08, 0x20, 0x98, 0xf8, 0x54, 0x10, - 0x03, 0x29, 0x04, 0xd0, 0xd9, 0xf8, 0x20, 0x10, 0xc1, 0x40, 0xc8, 0x07, - 0x04, 0xd4, 0x31, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xe5, 0xfd, 0x09, 0xe0, - 0x38, 0x46, 0x05, 0xf0, 0xc4, 0xfd, 0x08, 0xb1, 0x01, 0x24, 0xa8, 0xe0, - 0x31, 0x46, 0x38, 0x46, 0x05, 0xf0, 0xc7, 0xfd, 0x7f, 0x1c, 0x02, 0x2f, - 0xdc, 0xd3, 0xa0, 0xe0, 0x00, 0x2f, 0x1f, 0xd0, 0x05, 0x2a, 0x0c, 0xbf, - 0x00, 0x20, 0x01, 0x20, 0x0f, 0xfa, 0x8c, 0xf1, 0x06, 0xf0, 0x6e, 0xfb, - 0x95, 0xe0, 0x00, 0x2f, 0x14, 0xd0, 0x0d, 0x46, 0x28, 0x46, 0x07, 0xf0, - 0x6f, 0xff, 0x29, 0x46, 0x00, 0x20, 0x05, 0xf0, 0x56, 0xfd, 0x8a, 0xe0, - 0x00, 0x2f, 0x09, 0xd0, 0x0d, 0x46, 0x01, 0x20, 0x05, 0xf0, 0x4f, 0xfd, - 0x28, 0x46, 0x07, 0xf0, 0x73, 0xff, 0x80, 0xe0, 0x00, 0x2f, 0x0c, 0x46, - 0x7c, 0xd0, 0x98, 0xf8, 0x54, 0x00, 0x03, 0x28, 0x78, 0xd1, 0x00, 0x25, - 0x24, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x44, 0xbf, 0x28, 0x46, 0x05, 0xf0, - 0x9c, 0xfd, 0x6d, 0x1c, 0x02, 0x2d, 0xf5, 0xd3, 0x6c, 0xe0, 0x0e, 0xeb, - 0x41, 0x00, 0xc0, 0xb2, 0x06, 0x46, 0x13, 0x2e, 0x01, 0xdb, 0x05, 0x24, - 0x65, 0xe0, 0x7f, 0xb1, 0xfe, 0xf7, 0x58, 0xfd, 0x00, 0x28, 0x60, 0xd1, - 0x56, 0x48, 0x30, 0x5c, 0x08, 0xeb, 0x80, 0x00, 0x02, 0xab, 0x40, 0x68, - 0x40, 0x68, 0x01, 0x22, 0x28, 0x21, 0xfd, 0xf7, 0xe9, 0xfc, 0x54, 0xe0, - 0xfe, 0xf7, 0x48, 0xfd, 0x28, 0x70, 0x50, 0xe0, 0x00, 0x2f, 0x4d, 0xd0, - 0xff, 0xf7, 0x42, 0xfc, 0x4b, 0xe0, 0x27, 0xb1, 0xd5, 0xe9, 0x00, 0x23, - 0x04, 0xf0, 0xa2, 0xfc, 0x13, 0xe0, 0x07, 0xf0, 0xcd, 0xff, 0xc5, 0xe9, - 0x00, 0x01, 0x40, 0xe0, 0x4f, 0xea, 0x8c, 0x56, 0x18, 0x0b, 0xb6, 0x0d, - 0x00, 0xf0, 0x03, 0x00, 0x4f, 0xb1, 0x02, 0x28, 0xa8, 0xbf, 0x07, 0x24, - 0x35, 0xda, 0x0a, 0x46, 0x31, 0x46, 0x08, 0xf0, 0x58, 0xfc, 0x04, 0x46, - 0x2f, 0xe0, 0xea, 0x1c, 0x29, 0x46, 0x08, 0xf0, 0x7a, 0xfc, 0x2a, 0xe0, - 0x7f, 0xb9, 0x03, 0xf0, 0x7f, 0xfc, 0x06, 0x46, 0x04, 0x2e, 0x05, 0xd1, - 0x04, 0xf0, 0x3d, 0xfc, 0x46, 0xea, 0x00, 0x10, 0x00, 0x90, 0x00, 0xe0, - 0x00, 0x96, 0x04, 0x22, 0x69, 0x46, 0x09, 0xe0, 0x0f, 0xb1, 0x02, 0x24, - 0x17, 0xe0, 0x03, 0xf0, 0x63, 0xfc, 0x00, 0xf0, 0x0f, 0x00, 0x01, 0x90, - 0x04, 0x22, 0x01, 0xa9, 0x28, 0x46, 0x05, 0xf0, 0x13, 0xf9, 0x0c, 0xe0, - 0x17, 0xb1, 0x04, 0xf0, 0x20, 0xfc, 0x08, 0xe0, 0x04, 0xf0, 0x21, 0xfc, - 0x28, 0x60, 0x04, 0xe0, 0x17, 0xb1, 0x08, 0xf0, 0x3f, 0xff, 0x00, 0xe0, - 0x03, 0x24, 0xe0, 0xb2, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x38, 0xb5, - 0x04, 0x46, 0x1a, 0x48, 0x90, 0xf8, 0xb8, 0x03, 0x0d, 0x46, 0x00, 0xf0, - 0x03, 0x01, 0x03, 0x29, 0xc0, 0xf3, 0x81, 0x00, 0x01, 0xd1, 0xb0, 0xb9, - 0x03, 0xe0, 0x00, 0x29, 0x08, 0xbf, 0x03, 0x28, 0x11, 0xd1, 0x0b, 0x20, - 0x05, 0xf0, 0xea, 0xf9, 0x13, 0x28, 0x01, 0xd1, 0x01, 0x20, 0x32, 0xbd, - 0x1c, 0xb9, 0x0b, 0x20, 0x05, 0xf0, 0x9c, 0xf9, 0x02, 0xe0, 0x0b, 0x20, - 0x05, 0xf0, 0x8f, 0xf9, 0x28, 0x46, 0x01, 0xf0, 0xf9, 0xfe, 0x00, 0x20, - 0x32, 0xbd, 0x08, 0x48, 0xd0, 0xf8, 0xa8, 0x03, 0x70, 0x47, 0x06, 0x48, - 0xd0, 0xf8, 0xb4, 0x03, 0x70, 0x47, 0x04, 0x48, 0xd0, 0xf8, 0xac, 0x03, - 0x70, 0x47, 0x02, 0x48, 0x90, 0xf8, 0x54, 0x00, 0x70, 0x47, 0x00, 0x00, - 0xb8, 0x04, 0x00, 0x20, 0x60, 0xf3, 0x00, 0x20, 0x49, 0x3d, 0x00, 0x01, - 0x08, 0x00, 0x00, 0x49, 0x48, 0xbd, 0x00, 0x20, 0x98, 0x68, 0x01, 0x01, - 0xa8, 0x6f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, - 0xc8, 0x20, 0x00, 0x20, 0xdf, 0xf8, 0x84, 0x07, 0x00, 0x68, 0x70, 0x47, - 0x28, 0x21, 0x42, 0xf6, 0x2c, 0x40, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x00, 0x22, 0x00, 0xf0, 0x44, 0xf8, 0x40, 0xf2, 0xc9, 0x66, 0x80, 0x21, - 0x30, 0x46, 0xfe, 0xf7, 0x7b, 0xfa, 0x00, 0x21, 0x30, 0x46, 0xfe, 0xf7, - 0x77, 0xfa, 0xdf, 0xf8, 0x5c, 0x07, 0xdf, 0xf8, 0x5c, 0x17, 0x40, 0x6b, - 0x46, 0x00, 0x30, 0x46, 0x00, 0x27, 0x01, 0xe0, 0x40, 0x08, 0x7f, 0x1c, - 0x88, 0x42, 0xfb, 0xd2, 0x06, 0x2f, 0xb4, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0x03, 0xf0, 0x7d, 0xf9, 0x7a, 0x01, 0xd2, 0xb2, 0xe0, 0x21, 0x00, 0xf0, - 0x23, 0xf8, 0xdf, 0xf8, 0x28, 0x07, 0xfe, 0x40, 0x06, 0x60, 0x04, 0x22, - 0x00, 0xf0, 0x1b, 0xf8, 0xdf, 0xf8, 0x24, 0x07, 0xdf, 0xf8, 0x24, 0x17, - 0xdf, 0xf8, 0x24, 0x27, 0x04, 0x80, 0x45, 0x80, 0x30, 0x20, 0x08, 0x80, - 0xdf, 0xf8, 0x1c, 0x17, 0x08, 0x80, 0x0f, 0x21, 0xdf, 0xf8, 0x18, 0x07, - 0x01, 0x80, 0x30, 0x21, 0x11, 0x80, 0x01, 0x80, 0x70, 0x21, 0x01, 0x80, - 0xb0, 0x21, 0x01, 0x80, 0xf0, 0x21, 0x01, 0x80, 0xf1, 0xbd, 0x04, 0x21, - 0x4f, 0xf4, 0x8c, 0x70, 0xfe, 0xf7, 0x42, 0xba, 0x2d, 0xe9, 0xf8, 0x4f, - 0xdf, 0xf8, 0xf4, 0x66, 0xdf, 0xf8, 0xf4, 0x16, 0xdf, 0xf8, 0xd0, 0x26, - 0x18, 0xb9, 0xd2, 0xe9, 0x06, 0x5b, 0xc8, 0x6a, 0x03, 0xe0, 0xd2, 0xe9, - 0x08, 0x5b, 0x08, 0x6c, 0x50, 0x36, 0x30, 0x21, 0xb0, 0xfb, 0xf1, 0xf9, - 0x50, 0x21, 0x30, 0x46, 0x02, 0xf0, 0x8e, 0xff, 0x01, 0x27, 0x09, 0xfb, - 0x07, 0xf0, 0x00, 0x21, 0x15, 0xeb, 0x00, 0x08, 0x4b, 0xeb, 0x01, 0x0a, - 0x28, 0x1a, 0x6b, 0xeb, 0x01, 0x01, 0x08, 0xf0, 0x83, 0xff, 0x01, 0x21, - 0x00, 0x28, 0x01, 0xfa, 0x07, 0xf4, 0x03, 0xd5, 0xb0, 0x6c, 0x20, 0x43, - 0xb0, 0x64, 0x04, 0xe0, 0x06, 0xeb, 0x80, 0x00, 0x41, 0x6a, 0x21, 0x43, - 0x41, 0x62, 0x40, 0x46, 0x51, 0x46, 0x08, 0xf0, 0x71, 0xff, 0x00, 0x28, - 0x03, 0xd5, 0xf0, 0x6c, 0x20, 0x43, 0xf0, 0x64, 0x04, 0xe0, 0x56, 0xf8, - 0x20, 0x10, 0x21, 0x43, 0x46, 0xf8, 0x20, 0x10, 0x7f, 0x1c, 0x18, 0x2f, - 0xd3, 0xd3, 0xbd, 0xe8, 0xf1, 0x8f, 0x2d, 0xe9, 0xf8, 0x4f, 0x89, 0x46, - 0x17, 0x46, 0xdf, 0xf8, 0x48, 0x16, 0xdf, 0xf8, 0x64, 0x26, 0x15, 0x68, - 0x00, 0x28, 0x07, 0xbf, 0xd0, 0x6a, 0xd1, 0xe9, 0x00, 0x48, 0x10, 0x6c, - 0xd1, 0xe9, 0x02, 0x48, 0x01, 0x09, 0x00, 0x07, 0x2a, 0x46, 0x00, 0x23, - 0x02, 0xf0, 0x08, 0xfc, 0x30, 0x22, 0x00, 0x23, 0x02, 0xf0, 0x04, 0xfc, - 0x06, 0x46, 0x8a, 0x46, 0xdf, 0xb1, 0x07, 0xf1, 0x18, 0x00, 0x31, 0x28, - 0x17, 0xd2, 0xfa, 0x17, 0xa6, 0xfb, 0x07, 0x01, 0x06, 0xfb, 0x02, 0x11, - 0x0a, 0xfb, 0x07, 0x11, 0x27, 0x1a, 0x28, 0x46, 0x68, 0xeb, 0x01, 0x0b, - 0xa0, 0xfb, 0x07, 0x23, 0x00, 0xfb, 0x0b, 0x33, 0x12, 0x0f, 0x42, 0xea, - 0x03, 0x10, 0x19, 0x0f, 0x08, 0xf0, 0x2a, 0xff, 0x05, 0x46, 0x00, 0x2d, - 0x01, 0xd5, 0x00, 0x20, 0x20, 0xe0, 0x3a, 0x46, 0x5b, 0x46, 0x48, 0x46, - 0x08, 0xf0, 0x78, 0xfe, 0x2a, 0x46, 0x20, 0x46, 0x41, 0x46, 0x08, 0xf0, - 0x38, 0xfe, 0x04, 0x46, 0x0f, 0x46, 0x2a, 0x46, 0x30, 0x46, 0x51, 0x46, - 0x08, 0xf0, 0x31, 0xfe, 0x06, 0x46, 0xdf, 0xf8, 0xd8, 0x25, 0x24, 0x09, - 0x00, 0x0f, 0x44, 0xea, 0x07, 0x74, 0x40, 0xea, 0x01, 0x10, 0x14, 0x60, - 0x40, 0xf4, 0x00, 0x40, 0x10, 0x81, 0x30, 0x01, 0x50, 0x60, 0x01, 0x20, - 0xbd, 0xe8, 0xf2, 0x8f, 0xdf, 0xf8, 0xb8, 0x15, 0x08, 0x80, 0x70, 0x47, - 0x4f, 0xf0, 0x82, 0x41, 0x02, 0x68, 0x0a, 0x60, 0x42, 0x68, 0x4a, 0x60, - 0x02, 0x89, 0x0a, 0x81, 0x42, 0x89, 0x4a, 0x81, 0x82, 0x89, 0x8a, 0x81, - 0xc2, 0x89, 0xca, 0x87, 0xdf, 0xf8, 0x98, 0x15, 0x02, 0x8a, 0x0a, 0x80, - 0x40, 0x8a, 0x48, 0x80, 0x00, 0x21, 0xdf, 0xf8, 0x90, 0x05, 0x41, 0x80, - 0x81, 0x82, 0xc1, 0x82, 0x1f, 0x21, 0x01, 0x80, 0x00, 0x21, 0x81, 0x80, - 0xc1, 0x80, 0x70, 0x47, 0x38, 0xb5, 0x0c, 0x46, 0x01, 0xf0, 0x8a, 0xfe, - 0xdf, 0xf8, 0x74, 0x15, 0x02, 0xf0, 0x24, 0xf8, 0x05, 0x46, 0x20, 0x46, - 0x01, 0xf0, 0x82, 0xfe, 0x29, 0x46, 0x02, 0xf0, 0x1d, 0xf8, 0xdf, 0xf8, - 0x64, 0x15, 0x01, 0xf0, 0x8b, 0xfe, 0x08, 0xf0, 0x17, 0xff, 0x04, 0x46, - 0x03, 0xf0, 0xab, 0xf8, 0x20, 0x28, 0x28, 0xbf, 0x1f, 0x20, 0x01, 0x21, - 0x01, 0xfa, 0x00, 0xf2, 0x43, 0x1e, 0xa2, 0x1a, 0x99, 0x40, 0x8a, 0x42, - 0x28, 0xbf, 0x40, 0xf0, 0x20, 0x00, 0x80, 0xb2, 0x32, 0xbd, 0x00, 0xf0, - 0x1f, 0x01, 0x01, 0x22, 0x8a, 0x40, 0xc0, 0xf3, 0x40, 0x10, 0x49, 0x1e, - 0x88, 0x40, 0x80, 0x18, 0x70, 0x47, 0xdf, 0xf8, 0x24, 0x25, 0x4f, 0xf6, - 0xff, 0x73, 0x13, 0x81, 0x01, 0xb1, 0x04, 0x21, 0x00, 0xf0, 0x03, 0x00, - 0x08, 0x18, 0x00, 0x02, 0x40, 0xf4, 0x10, 0x40, 0x10, 0x80, 0x70, 0x47, - 0xdf, 0xf8, 0x04, 0x05, 0x01, 0x88, 0x01, 0xf4, 0x73, 0x61, 0x41, 0xf0, - 0x80, 0x01, 0x01, 0x80, 0x70, 0x47, 0xf0, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x83, 0xb0, 0x00, 0xf0, 0x0c, 0xf9, 0xdf, 0xf8, 0xec, 0x64, 0xdf, 0xf8, - 0xec, 0x74, 0xff, 0xf7, 0x3b, 0xfa, 0x30, 0x60, 0x06, 0x21, 0x03, 0x20, - 0x03, 0xf0, 0x8d, 0xf8, 0x4f, 0xf6, 0xff, 0x70, 0xb8, 0x80, 0x4f, 0xf6, - 0xf5, 0x30, 0xb8, 0x81, 0x03, 0x20, 0x03, 0xf0, 0x69, 0xf8, 0x03, 0x20, - 0x03, 0xf0, 0x6c, 0xf8, 0x30, 0x68, 0x00, 0xf0, 0xed, 0xf8, 0x29, 0x46, - 0xe0, 0xb2, 0xff, 0xf7, 0xc4, 0xff, 0x01, 0xa8, 0x00, 0x90, 0x41, 0xf2, - 0x88, 0x33, 0x30, 0x68, 0x03, 0x22, 0x05, 0x21, 0xfd, 0xf7, 0x22, 0xfa, - 0x39, 0x88, 0xc0, 0x07, 0x04, 0xd5, 0x2f, 0x20, 0x03, 0xf0, 0xcf, 0xf8, - 0x01, 0x24, 0x0d, 0xe0, 0x40, 0xf2, 0x0a, 0x40, 0x08, 0x40, 0x02, 0x28, - 0x04, 0xd1, 0x30, 0x20, 0x03, 0xf0, 0xc5, 0xf8, 0x00, 0x24, 0x03, 0xe0, - 0x31, 0x20, 0x03, 0xf0, 0xc0, 0xf8, 0x03, 0x24, 0x00, 0xf0, 0x68, 0xf8, - 0x03, 0x20, 0x03, 0xf0, 0x4a, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0xc8, 0xf8, - 0x20, 0x46, 0xfe, 0xbd, 0x00, 0x28, 0x08, 0xd5, 0xdf, 0xf8, 0x60, 0x34, - 0x40, 0x42, 0x53, 0xf8, 0x20, 0x30, 0x13, 0x60, 0xdf, 0xf8, 0x58, 0x24, - 0x06, 0xe0, 0xdf, 0xf8, 0x58, 0x34, 0x53, 0xf8, 0x20, 0x30, 0x13, 0x60, - 0xdf, 0xf8, 0x50, 0x24, 0x52, 0xf8, 0x20, 0x00, 0x08, 0x60, 0x70, 0x47, - 0xdf, 0xf8, 0x48, 0x14, 0xdf, 0xf8, 0x48, 0x34, 0x08, 0x22, 0x0a, 0x80, - 0x00, 0x22, 0x4a, 0x83, 0x8a, 0x83, 0x00, 0x21, 0xdf, 0xf8, 0x3c, 0x24, - 0x11, 0x80, 0x30, 0xf8, 0x11, 0x20, 0x23, 0xf8, 0x11, 0x20, 0x49, 0x1c, - 0x18, 0x29, 0xf8, 0xd3, 0xdf, 0xf8, 0x2c, 0x14, 0x42, 0x8e, 0x0a, 0x80, - 0xc2, 0x8e, 0x4a, 0x82, 0x02, 0x8f, 0x8a, 0x82, 0x42, 0x8f, 0xca, 0x82, - 0x82, 0x8f, 0x0a, 0x83, 0xc2, 0x8f, 0x4a, 0x83, 0xb0, 0xf8, 0x40, 0x00, - 0x88, 0x83, 0x00, 0x20, 0x48, 0x80, 0x88, 0x80, 0x70, 0x47, 0x10, 0xb5, - 0x01, 0xb1, 0x04, 0x21, 0x00, 0xf0, 0x03, 0x00, 0x08, 0x18, 0xdf, 0xf8, - 0xd0, 0x13, 0xdf, 0xf8, 0xc0, 0x33, 0x00, 0x02, 0x08, 0x80, 0x40, 0xf4, - 0x30, 0x40, 0x94, 0x8e, 0x5c, 0x82, 0x40, 0xf0, 0x40, 0x00, 0x4f, 0xf6, - 0xff, 0x74, 0x0c, 0x81, 0x9c, 0x8a, 0x44, 0xf4, 0x7f, 0x44, 0x9c, 0x82, - 0x1c, 0x8b, 0x44, 0xf4, 0x00, 0x44, 0x1c, 0x83, 0x12, 0x8e, 0x1a, 0x80, - 0x08, 0x80, 0x10, 0xbd, 0xdf, 0xf8, 0x98, 0x03, 0x01, 0x88, 0x01, 0xf4, - 0x73, 0x61, 0x41, 0xf4, 0x03, 0x51, 0x01, 0x80, 0x70, 0x47, 0x2d, 0xe9, - 0xfc, 0x41, 0x06, 0x46, 0x0f, 0x46, 0x90, 0x46, 0x00, 0xf0, 0x55, 0xf8, - 0xdf, 0xf8, 0x7c, 0x43, 0xdf, 0xf8, 0x7c, 0x53, 0xff, 0xf7, 0x84, 0xf9, - 0x20, 0x60, 0x06, 0x21, 0x03, 0x20, 0x02, 0xf0, 0xd6, 0xff, 0x4f, 0xf6, - 0xff, 0x70, 0xa8, 0x80, 0x4f, 0xf6, 0x35, 0x30, 0xa8, 0x81, 0x03, 0x20, - 0x02, 0xf0, 0xb2, 0xff, 0x03, 0x20, 0x02, 0xf0, 0xb5, 0xff, 0x42, 0x46, - 0x39, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xb3, 0xff, 0x01, 0xa8, 0x00, 0x90, - 0x41, 0xf2, 0x88, 0x33, 0x20, 0x68, 0x03, 0x22, 0x05, 0x21, 0xfd, 0xf7, - 0x6d, 0xf9, 0x02, 0x46, 0x28, 0x88, 0xd2, 0x07, 0x04, 0xd5, 0x2f, 0x20, - 0x03, 0xf0, 0x19, 0xf8, 0x01, 0x25, 0x13, 0xe0, 0x4f, 0xf4, 0x99, 0x62, - 0x10, 0x42, 0x04, 0xd0, 0x31, 0x20, 0x03, 0xf0, 0x10, 0xf8, 0x02, 0x25, - 0x0a, 0xe0, 0x80, 0x07, 0x04, 0xd5, 0x30, 0x20, 0x03, 0xf0, 0x09, 0xf8, - 0x00, 0x25, 0x03, 0xe0, 0x31, 0x20, 0x03, 0xf0, 0x04, 0xf8, 0x03, 0x25, - 0xff, 0xf7, 0xac, 0xff, 0x03, 0x20, 0x02, 0xf0, 0x8e, 0xff, 0x20, 0x68, - 0x00, 0xf0, 0x06, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x09, 0xf8, 0x28, 0x46, - 0xbd, 0xe8, 0xf6, 0x81, 0x01, 0xab, 0x00, 0x22, 0x04, 0x21, 0xfd, 0xf7, - 0xc9, 0xb9, 0x01, 0x21, 0x2d, 0x20, 0x02, 0xf0, 0xfc, 0xbf, 0x00, 0xf5, - 0x4a, 0x70, 0x00, 0x23, 0x03, 0x60, 0x01, 0x71, 0x42, 0x71, 0x70, 0x47, - 0x30, 0xb5, 0x00, 0x24, 0x00, 0x23, 0x50, 0xf8, 0x24, 0x20, 0x01, 0xeb, - 0xc4, 0x05, 0x64, 0x1c, 0xc5, 0xe9, 0x00, 0x23, 0x18, 0x2c, 0xf6, 0xd3, - 0x30, 0xbd, 0x30, 0xb5, 0x00, 0x24, 0x50, 0xf8, 0x24, 0x20, 0x01, 0xeb, - 0xc4, 0x05, 0xd3, 0x17, 0xc5, 0xe9, 0x00, 0x23, 0x64, 0x1c, 0x18, 0x2c, - 0xf5, 0xd3, 0x30, 0xbd, 0x70, 0xb5, 0x02, 0x46, 0x0b, 0x46, 0x00, 0x26, - 0x03, 0xeb, 0xc6, 0x00, 0x00, 0x21, 0xd0, 0xe9, 0x00, 0x45, 0x52, 0xf8, - 0x26, 0x00, 0x00, 0xf0, 0x11, 0xf8, 0xf5, 0xd3, 0x70, 0xbd, 0x70, 0xb5, - 0x02, 0x46, 0x0b, 0x46, 0x00, 0x26, 0x03, 0xeb, 0xc6, 0x00, 0xd0, 0xe9, - 0x00, 0x45, 0x52, 0xf8, 0x26, 0x00, 0xc1, 0x17, 0x00, 0xf0, 0x02, 0xf8, - 0xf5, 0xd3, 0x70, 0xbd, 0x20, 0x18, 0x03, 0xeb, 0xc6, 0x04, 0x69, 0x41, - 0xc4, 0xe9, 0x00, 0x01, 0x76, 0x1c, 0x18, 0x2e, 0x70, 0x47, 0x2d, 0xe9, - 0xf0, 0x47, 0x04, 0x46, 0x04, 0xf5, 0x16, 0x75, 0xd4, 0xf8, 0x28, 0x13, - 0xdf, 0xf8, 0x3c, 0x82, 0xdf, 0xf8, 0x3c, 0x92, 0xdf, 0xf8, 0x2c, 0xa2, - 0xdf, 0xf8, 0x2c, 0x02, 0x00, 0x29, 0x04, 0xf5, 0xc8, 0x76, 0x04, 0xf1, - 0xc8, 0x07, 0x21, 0x46, 0x11, 0xd0, 0xff, 0xf7, 0xc1, 0xff, 0x39, 0x46, - 0x50, 0x46, 0xff, 0xf7, 0xbd, 0xff, 0x31, 0x46, 0x48, 0x46, 0xff, 0xf7, - 0xc8, 0xff, 0x29, 0x46, 0x40, 0x46, 0xff, 0xf7, 0xc4, 0xff, 0xd4, 0xf8, - 0x28, 0x03, 0x40, 0x1c, 0x0e, 0xe0, 0xff, 0xf7, 0x95, 0xff, 0x39, 0x46, - 0x50, 0x46, 0xff, 0xf7, 0x91, 0xff, 0x31, 0x46, 0x48, 0x46, 0xff, 0xf7, - 0x9a, 0xff, 0x29, 0x46, 0x40, 0x46, 0xff, 0xf7, 0x96, 0xff, 0x01, 0x20, - 0xc4, 0xf8, 0x28, 0x03, 0xbd, 0xe8, 0xf0, 0x87, 0xc1, 0xb2, 0x01, 0xeb, - 0x10, 0x20, 0x70, 0x47, 0xf0, 0xb5, 0x4b, 0x6e, 0x03, 0x66, 0x01, 0x22, - 0x00, 0x24, 0x00, 0x25, 0x00, 0x23, 0x17, 0x26, 0x02, 0x27, 0x0a, 0xe0, - 0x01, 0xeb, 0x83, 0x0c, 0xdc, 0xf8, 0x04, 0xc0, 0xa4, 0x45, 0xd8, 0xbf, - 0x64, 0x46, 0x65, 0x45, 0xb8, 0xbf, 0x65, 0x46, 0x5b, 0x1c, 0x9e, 0x42, - 0xf2, 0xd2, 0x19, 0x23, 0x2f, 0x26, 0x7f, 0x1e, 0xf9, 0xd1, 0x23, 0x46, - 0x2c, 0x46, 0x6f, 0xf3, 0x0b, 0x04, 0xb4, 0xf1, 0x00, 0x6f, 0x6f, 0xf3, - 0x0b, 0x03, 0x04, 0xdc, 0x13, 0xf1, 0x00, 0x6f, 0x04, 0xdb, 0x00, 0x24, - 0x17, 0xe0, 0xb4, 0xf1, 0x80, 0x5f, 0x05, 0xda, 0x13, 0xf1, 0x80, 0x5f, - 0x05, 0xdb, 0x01, 0x24, 0x01, 0x25, 0x13, 0xe0, 0xb4, 0xf1, 0x00, 0x5f, - 0x04, 0xda, 0x13, 0xf1, 0x00, 0x5f, 0x04, 0xdb, 0x02, 0x24, 0x06, 0xe0, - 0xb4, 0xf1, 0x80, 0x4f, 0x05, 0xda, 0x13, 0xf1, 0x80, 0x4f, 0x02, 0xdb, - 0x03, 0x24, 0x25, 0x46, 0x02, 0xe0, 0x03, 0x24, 0x03, 0x25, 0x00, 0x22, - 0x00, 0x23, 0x17, 0x26, 0x02, 0x27, 0x08, 0xe0, 0x01, 0xeb, 0x83, 0x0c, - 0xdc, 0xf8, 0x04, 0xc0, 0x4c, 0xfa, 0x05, 0xfc, 0x40, 0xf8, 0x23, 0xc0, - 0x5b, 0x1c, 0x9e, 0x42, 0xf4, 0xd2, 0x19, 0x23, 0x2f, 0x26, 0x7f, 0x1e, - 0xf9, 0xd1, 0x44, 0xf0, 0x30, 0x03, 0x20, 0xf8, 0xc0, 0x3f, 0x09, 0x68, - 0x41, 0x60, 0x10, 0x46, 0xf0, 0xbd, 0x3e, 0xb5, 0x0f, 0xf2, 0x34, 0x12, - 0x38, 0xca, 0x69, 0x46, 0x03, 0x28, 0x38, 0xc1, 0x34, 0xbf, 0x5d, 0xf8, - 0x20, 0x00, 0x00, 0x20, 0x3e, 0xbd, 0x70, 0xb5, 0x0f, 0xf2, 0x10, 0x13, - 0x84, 0xb0, 0x70, 0xcb, 0x6a, 0x46, 0x03, 0x28, 0x70, 0xc2, 0x11, 0xd2, - 0x5d, 0xf8, 0x20, 0x00, 0x01, 0xfa, 0x00, 0xf2, 0x03, 0x23, 0x03, 0xfa, - 0x00, 0xf0, 0x19, 0x42, 0x40, 0xf0, 0xc0, 0x00, 0x06, 0xd0, 0x81, 0xb2, - 0x92, 0xb2, 0x24, 0x48, 0x00, 0xf0, 0xaf, 0xf8, 0x01, 0x20, 0x00, 0xe0, - 0x00, 0x20, 0x04, 0xb0, 0x70, 0xbd, 0x20, 0x49, 0x09, 0x88, 0x01, 0x80, - 0x32, 0x49, 0x09, 0x88, 0x41, 0x80, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, - 0x1b, 0x48, 0x21, 0x88, 0x00, 0xf0, 0xfa, 0xf8, 0x61, 0x88, 0x2d, 0x48, - 0xbd, 0xe8, 0x10, 0x40, 0x00, 0xf0, 0xf4, 0xb8, 0x10, 0xb5, 0x00, 0x03, - 0x0c, 0x46, 0x00, 0xf4, 0x40, 0x52, 0x4f, 0xf4, 0x40, 0x51, 0x13, 0x48, - 0x00, 0xf0, 0xfa, 0xf8, 0x04, 0xf0, 0x3c, 0x01, 0xbd, 0xe8, 0x10, 0x40, - 0xff, 0xe7, 0x23, 0x48, 0x00, 0xf0, 0xe2, 0xb8, 0x80, 0xb5, 0x22, 0x49, - 0x4f, 0xf6, 0xff, 0x70, 0x08, 0x80, 0x6b, 0x46, 0x14, 0x48, 0x00, 0x68, - 0x01, 0x22, 0x04, 0x21, 0xfd, 0xf7, 0x82, 0xf8, 0x01, 0xbd, 0x00, 0x00, - 0x80, 0xf3, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, 0x01, 0xd0, 0x12, 0x13, - 0xfc, 0x01, 0x00, 0x41, 0xc0, 0x02, 0x00, 0x41, 0xc0, 0x06, 0x00, 0x41, - 0xc0, 0x04, 0x00, 0x41, 0x02, 0x08, 0x00, 0x41, 0x08, 0xef, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0x40, 0x00, 0x00, 0x41, 0x0c, 0x00, 0x00, 0x41, - 0x58, 0x00, 0x00, 0x41, 0xb0, 0x00, 0x00, 0x41, 0xbd, 0x37, 0x86, 0x35, - 0x00, 0x00, 0x40, 0x42, 0x00, 0x08, 0x00, 0x41, 0x7c, 0xf3, 0x00, 0x20, - 0x08, 0x08, 0x00, 0x41, 0x00, 0x16, 0x00, 0x41, 0x80, 0x16, 0x00, 0x41, - 0x00, 0x17, 0x00, 0x41, 0x80, 0x17, 0x00, 0x41, 0x3e, 0x00, 0x00, 0x41, - 0x80, 0x00, 0x00, 0x41, 0x04, 0x08, 0x00, 0x41, 0xb2, 0x00, 0x00, 0x41, - 0xfe, 0x01, 0x00, 0x41, 0x14, 0x08, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x41, - 0x00, 0x04, 0x00, 0x41, 0x00, 0x06, 0x00, 0x41, 0xdf, 0xf8, 0x10, 0x14, - 0x28, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x81, 0x7f, 0xc2, 0x7f, 0x90, 0xf8, - 0x20, 0x00, 0x41, 0xea, 0x02, 0x21, 0x41, 0xea, 0x00, 0x40, 0x70, 0x47, - 0xdf, 0xf8, 0xf4, 0x13, 0x28, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x10, 0xf8, - 0x21, 0x1f, 0x40, 0x78, 0x00, 0xf0, 0x07, 0x00, 0x41, 0xea, 0x00, 0x20, - 0x70, 0x47, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, - 0xdf, 0xf8, 0xd4, 0x13, 0xdf, 0xf8, 0xd4, 0x33, 0x09, 0x68, 0x4f, 0xf0, - 0x00, 0x42, 0x1a, 0x60, 0x70, 0x47, 0xdf, 0xf8, 0xc4, 0x33, 0x01, 0xf0, - 0x00, 0x42, 0x1a, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x70, 0xb5, - 0x00, 0xf0, 0x56, 0xf8, 0x00, 0xf0, 0x79, 0xf8, 0xbd, 0xe8, 0x70, 0x40, - 0xef, 0xe7, 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0x88, 0x46, 0xff, 0xf7, - 0xdc, 0xff, 0x00, 0xf0, 0x36, 0xf8, 0x20, 0xb1, 0x41, 0x46, 0x30, 0x46, - 0xfd, 0xf7, 0x3e, 0xfe, 0x01, 0x27, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, - 0xde, 0xff, 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x16, 0x46, 0x01, 0x20, 0x00, 0x27, 0x00, 0xe0, 0x7f, 0x1c, - 0xb7, 0x42, 0x06, 0xd2, 0x79, 0x5d, 0x34, 0xf8, 0x17, 0x00, 0xff, 0xf7, - 0xdc, 0xff, 0x00, 0x28, 0xf5, 0xd1, 0xf2, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, - 0x06, 0x46, 0x89, 0x46, 0x90, 0x46, 0xff, 0xf7, 0xb4, 0xff, 0x00, 0xf0, - 0x0e, 0xf8, 0x28, 0xb1, 0x42, 0x46, 0x49, 0x46, 0x30, 0x46, 0xfd, 0xf7, - 0x1f, 0xfe, 0x01, 0x27, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, 0xb5, 0xff, - 0x38, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x04, 0x46, 0xdf, 0xf8, 0x2c, 0x03, - 0x00, 0x78, 0x00, 0x27, 0x0d, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x00, 0xf0, - 0x06, 0xf8, 0x00, 0xf0, 0x17, 0xf8, 0x0a, 0xb1, 0x25, 0x70, 0x01, 0x26, - 0x0e, 0xe0, 0x04, 0x46, 0x0d, 0x46, 0x90, 0xe7, 0x04, 0x46, 0x0d, 0x46, - 0x16, 0x46, 0x8c, 0xe7, 0x70, 0xb5, 0xff, 0xf7, 0xf6, 0xff, 0x00, 0xf0, - 0x07, 0xf8, 0x0a, 0xb1, 0x25, 0x80, 0x01, 0x26, 0xff, 0xf7, 0x91, 0xff, - 0x30, 0x46, 0x70, 0xbd, 0xba, 0x4a, 0x12, 0x78, 0x00, 0x26, 0x70, 0x47, - 0xf8, 0xb5, 0xff, 0xf7, 0xe9, 0xff, 0x00, 0xf0, 0x08, 0xf8, 0x12, 0xb1, - 0x00, 0xf0, 0x09, 0xf8, 0x01, 0x27, 0xff, 0xf7, 0x80, 0xff, 0x38, 0x46, - 0xf2, 0xbd, 0xb2, 0x4a, 0x12, 0x78, 0x00, 0x27, 0x70, 0x47, 0x22, 0x88, - 0xaa, 0x43, 0x05, 0xea, 0x06, 0x03, 0x1a, 0x43, 0x22, 0x80, 0x70, 0x47, - 0x70, 0xb5, 0xff, 0xf7, 0xce, 0xff, 0xff, 0xf7, 0xdf, 0xff, 0x0a, 0xb1, - 0x25, 0x60, 0x01, 0x26, 0xd6, 0xe7, 0x10, 0xb5, 0x04, 0x46, 0x04, 0x22, - 0x21, 0x46, 0x0f, 0xf2, 0xb4, 0x20, 0xfd, 0xf7, 0xee, 0xfd, 0x01, 0x22, - 0x21, 0x1d, 0x0f, 0xf2, 0xb0, 0x20, 0xfd, 0xf7, 0xe8, 0xfd, 0xa2, 0x48, - 0x00, 0x68, 0xa0, 0x60, 0x10, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x04, 0x22, 0x21, 0x46, 0x0f, 0xf2, 0x8c, 0x20, 0xff, 0xf7, 0x74, 0xff, - 0x55, 0xb9, 0xa0, 0x68, 0x9a, 0x49, 0x08, 0x60, 0x21, 0x1d, 0xbd, 0xe8, - 0x38, 0x40, 0x01, 0x22, 0x0f, 0xf2, 0x7c, 0x20, 0xfd, 0xf7, 0xbc, 0xbd, - 0x31, 0xbd, 0x38, 0xb5, 0x20, 0xb9, 0x01, 0x24, 0x40, 0xf6, 0x12, 0x05, - 0x80, 0x21, 0x03, 0xe0, 0x02, 0x24, 0x40, 0xf6, 0x13, 0x05, 0x40, 0x21, - 0x00, 0x22, 0x40, 0xf6, 0x14, 0x00, 0xff, 0xf7, 0x69, 0xff, 0x00, 0x22, - 0xc0, 0x21, 0x28, 0x46, 0xff, 0xf7, 0x64, 0xff, 0x21, 0x46, 0x4f, 0xf4, - 0x82, 0x70, 0xff, 0xf7, 0x38, 0xff, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x22, - 0x33, 0x21, 0x4f, 0xf4, 0xa9, 0x60, 0x57, 0xe7, 0x80, 0xb5, 0x85, 0x48, - 0x01, 0x6d, 0x03, 0x20, 0x01, 0xf0, 0x0e, 0xfa, 0x03, 0x20, 0x01, 0xf0, - 0x23, 0xfa, 0x18, 0xb9, 0xff, 0xf7, 0x45, 0xf8, 0x00, 0x28, 0xf7, 0xd0, - 0xbd, 0xe8, 0x02, 0x40, 0x03, 0x20, 0x01, 0xf0, 0x91, 0xb9, 0x77, 0x48, - 0x90, 0xf8, 0x43, 0x20, 0x04, 0xe0, 0x75, 0x48, 0x90, 0xf8, 0x6b, 0x00, - 0x40, 0xf0, 0x20, 0x02, 0x3f, 0x21, 0x40, 0xf6, 0x15, 0x00, 0x37, 0xe7, - 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, 0x07, 0xf0, 0x0c, 0xfd, 0x01, 0x20, - 0xff, 0xf7, 0xde, 0xfe, 0x04, 0x46, 0x01, 0x20, 0xff, 0xf7, 0xcc, 0xfe, - 0x82, 0x46, 0x03, 0x20, 0xff, 0xf7, 0xd6, 0xfe, 0x05, 0x46, 0x03, 0x20, - 0xff, 0xf7, 0xc4, 0xfe, 0x06, 0x46, 0x6c, 0x48, 0x6c, 0x4a, 0x41, 0x78, - 0x00, 0x78, 0x13, 0x78, 0x40, 0xea, 0x01, 0x20, 0x40, 0x05, 0x40, 0x0d, - 0x01, 0x21, 0x03, 0xf0, 0x03, 0x07, 0x02, 0x2f, 0x4f, 0xf0, 0x00, 0x0b, - 0x08, 0xbf, 0x02, 0x21, 0x02, 0xd0, 0x03, 0x2f, 0x08, 0xbf, 0x04, 0x21, - 0xdf, 0x06, 0x48, 0xbf, 0x49, 0x00, 0x9b, 0x06, 0x48, 0xbf, 0x49, 0x00, - 0x52, 0x78, 0x52, 0x07, 0x4c, 0xbf, 0x01, 0xeb, 0x81, 0x01, 0x89, 0x00, - 0x00, 0x91, 0x02, 0x27, 0x54, 0x49, 0x91, 0xf8, 0x89, 0x20, 0x91, 0xf8, - 0x39, 0x10, 0x8b, 0x1a, 0x01, 0x2b, 0x03, 0xdb, 0x07, 0xfa, 0x01, 0xf1, - 0x01, 0x27, 0x08, 0xe0, 0x00, 0x2b, 0x03, 0xd5, 0x59, 0x42, 0x8c, 0x40, - 0x0a, 0xfa, 0x01, 0xfa, 0x07, 0xfa, 0x02, 0xf1, 0x00, 0x27, 0x05, 0xfa, - 0x07, 0xf2, 0xa2, 0x1a, 0x50, 0x4b, 0x03, 0xfb, 0x02, 0xa2, 0x01, 0x92, - 0x48, 0x43, 0x01, 0x9b, 0x00, 0x9a, 0xc1, 0x17, 0x06, 0xfa, 0x07, 0xf4, - 0xcd, 0xe9, 0x02, 0x01, 0x1b, 0x1b, 0x83, 0xfb, 0x02, 0x89, 0x00, 0x25, - 0x07, 0xe0, 0xae, 0x19, 0x01, 0x99, 0x00, 0x98, 0x06, 0xfa, 0x07, 0xf2, - 0x89, 0x1a, 0x81, 0xfb, 0x00, 0x89, 0xdd, 0xe9, 0x02, 0x23, 0x40, 0x46, - 0x49, 0x46, 0x01, 0xf0, 0xf9, 0xfe, 0xdd, 0xe9, 0x02, 0x23, 0x04, 0x46, - 0x8a, 0x46, 0xa2, 0xfb, 0x04, 0x01, 0x02, 0xfb, 0x0a, 0x11, 0x03, 0xfb, - 0x04, 0x11, 0xb8, 0xeb, 0x00, 0x00, 0x79, 0xeb, 0x01, 0x01, 0x08, 0xbf, - 0x00, 0x28, 0x08, 0xd0, 0x00, 0x2d, 0xde, 0xd1, 0x38, 0x48, 0x86, 0x42, - 0xac, 0xbf, 0x4f, 0xf0, 0xff, 0x35, 0x01, 0x25, 0xd7, 0xe7, 0xb5, 0xb1, - 0x30, 0x02, 0x01, 0x0e, 0x40, 0xf2, 0x45, 0x30, 0xff, 0xf7, 0x81, 0xfe, - 0x30, 0x04, 0x01, 0x0e, 0x4f, 0xf4, 0x51, 0x70, 0xff, 0xf7, 0x7b, 0xfe, - 0xf1, 0xb2, 0x40, 0xf2, 0x43, 0x30, 0xff, 0xf7, 0x76, 0xfe, 0x00, 0x22, - 0x00, 0x21, 0x40, 0xf2, 0x41, 0x30, 0xff, 0xf7, 0x97, 0xfe, 0x60, 0x42, - 0x00, 0x02, 0x23, 0x4e, 0x00, 0x0a, 0x40, 0xf0, 0x40, 0x70, 0x30, 0x60, - 0x20, 0x22, 0x4f, 0xf4, 0x80, 0x50, 0x70, 0x60, 0x20, 0x21, 0x40, 0xf6, - 0x15, 0x00, 0xff, 0xf7, 0x87, 0xfe, 0x00, 0x22, 0x01, 0x21, 0x4f, 0xf4, - 0x60, 0x70, 0xfd, 0xf7, 0xaf, 0xfc, 0x04, 0x98, 0x01, 0x28, 0x23, 0xdb, - 0x30, 0x68, 0x04, 0x99, 0x20, 0xf0, 0xf0, 0x40, 0x40, 0xea, 0xc1, 0x60, - 0x40, 0xf0, 0x80, 0x60, 0x30, 0x60, 0x4f, 0xf4, 0x7a, 0x71, 0x03, 0x20, - 0x01, 0xf0, 0x2c, 0xf9, 0x30, 0x68, 0x40, 0x01, 0x07, 0xd5, 0x03, 0x20, - 0x01, 0xf0, 0x3e, 0xf9, 0x18, 0xb9, 0xfe, 0xf7, 0x60, 0xff, 0x00, 0x28, - 0xf4, 0xd0, 0x30, 0x68, 0x40, 0x01, 0x04, 0xd5, 0xfe, 0xf7, 0x59, 0xff, - 0x08, 0xb9, 0x4f, 0xf0, 0x01, 0x0b, 0x03, 0x20, 0x01, 0xf0, 0xa6, 0xf8, - 0x58, 0x46, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x68, 0xee, 0x00, 0x20, - 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, 0x65, 0x2c, 0x00, 0x20, - 0x10, 0x00, 0x00, 0x45, 0x4c, 0x1f, 0x00, 0x20, 0x41, 0x01, 0x00, 0x46, - 0x01, 0x01, 0x00, 0x46, 0x00, 0xf8, 0x7f, 0x00, 0x01, 0xfc, 0x3f, 0x00, - 0x48, 0x05, 0x12, 0x08, 0x13, 0x08, 0x14, 0x08, 0x80, 0x03, 0x00, 0x00, - 0x10, 0xb5, 0x00, 0x24, 0x00, 0x21, 0xe0, 0xb2, 0x00, 0xf0, 0xad, 0xf8, - 0x01, 0x21, 0xe0, 0xb2, 0x00, 0xf0, 0xe1, 0xf8, 0x64, 0x1c, 0x02, 0x2c, - 0xf4, 0xd3, 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xff, 0xf7, - 0xe4, 0xfe, 0x00, 0x2c, 0x0c, 0xbf, 0x01, 0x21, 0x10, 0x21, 0x40, 0xf2, - 0x49, 0x50, 0xfd, 0xf7, 0x45, 0xfc, 0x2e, 0x00, 0x18, 0xbf, 0x01, 0x2d, - 0x04, 0xd1, 0x7e, 0x21, 0x40, 0xf2, 0x0b, 0x20, 0xfd, 0xf7, 0x3c, 0xfc, - 0x00, 0x2c, 0x0c, 0xbf, 0x00, 0x20, 0x04, 0x20, 0x05, 0xf0, 0x03, 0x01, - 0x01, 0xfa, 0x00, 0xf2, 0x03, 0x21, 0x81, 0x40, 0xd2, 0xb2, 0xc9, 0xb2, - 0x4f, 0xf4, 0xa9, 0x60, 0xff, 0xf7, 0x08, 0xfe, 0x01, 0x2d, 0x18, 0xbf, - 0x02, 0x2d, 0x10, 0xd1, 0x00, 0x2c, 0x07, 0xbf, 0x08, 0x24, 0x40, 0xf2, - 0x42, 0x50, 0x10, 0x24, 0x40, 0xf2, 0x43, 0x50, 0x00, 0x22, 0xc0, 0x21, - 0xff, 0xf7, 0xf8, 0xfd, 0x21, 0x46, 0x4f, 0xf4, 0x82, 0x70, 0xff, 0xf7, - 0xcc, 0xfd, 0x01, 0x20, 0x70, 0xbd, 0xff, 0xf7, 0x97, 0xbe, 0x00, 0xb1, - 0x04, 0x20, 0x41, 0x49, 0x09, 0x78, 0xc1, 0x40, 0x01, 0xf0, 0x03, 0x00, - 0x70, 0x47, 0x10, 0xb5, 0x02, 0x46, 0x00, 0x21, 0x53, 0x68, 0x18, 0x46, - 0x01, 0xf0, 0xca, 0xfb, 0x08, 0xd2, 0x10, 0x68, 0x3a, 0x4c, 0x19, 0x46, - 0x01, 0xf0, 0x2e, 0xf9, 0x20, 0x60, 0x00, 0x20, 0xc4, 0xe9, 0x02, 0x00, - 0x10, 0xbd, 0x38, 0xb5, 0x36, 0x4a, 0x35, 0x4d, 0xd2, 0xe9, 0x08, 0x01, - 0xd5, 0xe9, 0x02, 0x23, 0x99, 0x42, 0x08, 0xbf, 0x90, 0x42, 0x3f, 0xd0, - 0xc5, 0xe9, 0x02, 0x01, 0x31, 0x4a, 0x00, 0x23, 0x01, 0xf0, 0x16, 0xfe, - 0x00, 0x24, 0x80, 0xb2, 0xb0, 0xf5, 0x95, 0x7f, 0xb8, 0xbf, 0xff, 0x24, - 0x1a, 0xdb, 0xb0, 0xf5, 0xd5, 0x6f, 0x17, 0xdc, 0x40, 0xf2, 0x29, 0x11, - 0x40, 0x1a, 0x00, 0xb2, 0x41, 0x11, 0x00, 0xeb, 0x91, 0x61, 0x89, 0x02, - 0x09, 0x0c, 0x0f, 0xf2, 0x74, 0x12, 0x8b, 0x5c, 0xa0, 0xeb, 0x81, 0x10, - 0x89, 0x18, 0x00, 0xb2, 0x49, 0x78, 0x59, 0x1a, 0x48, 0x43, 0x41, 0x11, - 0x00, 0xeb, 0x91, 0x60, 0xa3, 0xeb, 0xa0, 0x14, 0xe0, 0xb2, 0x01, 0xf0, - 0xe3, 0xf8, 0x29, 0x68, 0x01, 0xf0, 0x7e, 0xfa, 0x01, 0xf0, 0xe8, 0xfa, - 0x84, 0xb2, 0xff, 0x2c, 0xc8, 0xbf, 0xff, 0x24, 0xe1, 0xb2, 0x40, 0xf2, - 0x44, 0x50, 0xfd, 0xf7, 0xb5, 0xfb, 0xe1, 0xb2, 0xbd, 0xe8, 0x34, 0x40, - 0x40, 0xf2, 0x45, 0x50, 0xfd, 0xf7, 0xae, 0xbb, 0x31, 0xbd, 0x00, 0x28, - 0x0c, 0xbf, 0x40, 0xf2, 0x46, 0x50, 0x40, 0xf2, 0x47, 0x50, 0x01, 0xf0, - 0x03, 0x02, 0x03, 0x21, 0xfd, 0xf7, 0xac, 0xbb, 0x70, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x08, 0xf0, 0x6d, 0xf9, 0x2f, 0x26, 0x03, 0x28, 0x08, 0xd1, - 0x00, 0x21, 0x8d, 0x42, 0x08, 0x48, 0x03, 0xd8, 0x84, 0x42, 0x38, 0xbf, - 0x2d, 0x26, 0x00, 0xd3, 0x2e, 0x26, 0x30, 0x46, 0x70, 0xbd, 0x00, 0x00, - 0x48, 0x05, 0x00, 0x46, 0x08, 0xf3, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, - 0x40, 0x42, 0x0f, 0x00, 0x00, 0x28, 0x6b, 0xee, 0x00, 0x28, 0x0c, 0xbf, - 0x40, 0xf2, 0x5e, 0x40, 0x40, 0xf2, 0x5f, 0x40, 0xfd, 0xf7, 0x7c, 0xbb, - 0x00, 0xf0, 0x0f, 0x02, 0x0f, 0x21, 0x4f, 0xf4, 0xc1, 0x70, 0xfd, 0xf7, - 0x7f, 0xbb, 0x00, 0x28, 0x0c, 0xbf, 0x40, 0xf2, 0x46, 0x50, 0x40, 0xf2, - 0x47, 0x50, 0x89, 0x00, 0x01, 0xf0, 0x0c, 0x02, 0x0c, 0x21, 0xfd, 0xf7, - 0x73, 0xbb, 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0xa8, 0x60, 0x40, 0xf2, - 0x41, 0x50, 0x8a, 0x01, 0xd2, 0xb2, 0xc0, 0x21, 0xfd, 0xf7, 0x68, 0xbb, - 0x00, 0x28, 0x0c, 0xbf, 0x4f, 0xf4, 0xa8, 0x60, 0x40, 0xf2, 0x41, 0x50, - 0x01, 0xf0, 0x3f, 0x02, 0x3f, 0x21, 0xfd, 0xf7, 0x5d, 0xbb, 0x10, 0xb5, - 0x00, 0xf0, 0x17, 0xf8, 0xfd, 0xf7, 0x7f, 0xfb, 0x21, 0x46, 0xbd, 0xe8, - 0x10, 0x40, 0x05, 0x22, 0x0f, 0xf2, 0x48, 0x00, 0xfd, 0xf7, 0x77, 0xbb, - 0x10, 0xb5, 0x00, 0xf0, 0x0a, 0xf8, 0xff, 0xf7, 0x0b, 0xfd, 0x21, 0x46, - 0xbd, 0xe8, 0x10, 0x40, 0x05, 0x22, 0x0f, 0xf2, 0x30, 0x00, 0xfd, 0xf7, - 0x57, 0xbb, 0x04, 0x46, 0x03, 0x22, 0x61, 0x1d, 0x0f, 0xf2, 0x2c, 0x00, - 0x70, 0x47, 0x00, 0xb1, 0x04, 0x20, 0x01, 0xf0, 0x01, 0x01, 0x01, 0xfa, - 0x00, 0xf2, 0x01, 0x21, 0x81, 0x40, 0xd2, 0xb2, 0xc9, 0xb2, 0x4f, 0xf4, - 0xaa, 0x60, 0xfd, 0xf7, 0x2f, 0xbb, 0x00, 0x00, 0x40, 0x05, 0x41, 0x05, - 0x50, 0x05, 0x49, 0x05, 0x0b, 0x02, 0x00, 0x00, 0x48, 0x05, 0x42, 0x05, - 0x43, 0x05, 0x00, 0x00, 0xff, 0xc1, 0x97, 0x7a, 0x65, 0x57, 0x4b, 0x42, - 0x3a, 0x33, 0x2d, 0x27, 0x22, 0x1d, 0x1a, 0x16, 0x13, 0x10, 0x0d, 0x0a, - 0x06, 0x03, 0x00, 0x00, 0x70, 0xb5, 0x04, 0x46, 0x00, 0x25, 0x0f, 0xf2, - 0x60, 0x66, 0x36, 0xf9, 0x15, 0x20, 0xe9, 0xb2, 0x20, 0x46, 0x00, 0xf0, - 0x29, 0xf8, 0x6d, 0x1c, 0x04, 0x2d, 0xf6, 0xd3, 0x70, 0xbd, 0x10, 0xb5, - 0x08, 0x22, 0x08, 0x21, 0x4f, 0xf4, 0x8c, 0x70, 0xfd, 0xf7, 0x02, 0xfb, - 0x00, 0x24, 0x20, 0x46, 0xff, 0xf7, 0xe6, 0xff, 0x64, 0x1c, 0x02, 0x2c, - 0xf9, 0xd3, 0xdf, 0xf8, 0xac, 0x05, 0x4f, 0xf4, 0x80, 0x71, 0x81, 0x61, - 0x42, 0x6a, 0x42, 0xf4, 0x80, 0x72, 0x42, 0x62, 0x01, 0x60, 0x13, 0x20, - 0x06, 0x21, 0x02, 0xf0, 0x5c, 0xfa, 0x13, 0x20, 0x02, 0xf0, 0x3e, 0xfa, - 0xbd, 0xe8, 0x10, 0x40, 0x13, 0x20, 0x02, 0xf0, 0x3f, 0xba, 0x00, 0x00, - 0x2d, 0xe9, 0xf8, 0x43, 0x14, 0x46, 0x05, 0x46, 0x27, 0x12, 0x01, 0x20, - 0x03, 0x29, 0x00, 0xfa, 0x05, 0xf6, 0x40, 0xf6, 0x1c, 0x28, 0x3b, 0xd8, - 0xdf, 0xe8, 0x01, 0xf0, 0x02, 0x1a, 0x21, 0x27, 0x0f, 0xf2, 0xcc, 0x56, - 0xa0, 0x05, 0x01, 0x0e, 0x36, 0xf8, 0x25, 0x00, 0xfd, 0xf7, 0xc2, 0xfa, - 0x06, 0xeb, 0x85, 0x00, 0x04, 0xf0, 0x03, 0x04, 0x45, 0x88, 0x44, 0xf0, - 0x80, 0x01, 0x28, 0x46, 0xfd, 0xf7, 0xb8, 0xfa, 0x00, 0xbf, 0x00, 0xbf, - 0x00, 0xbf, 0x21, 0x46, 0x28, 0x46, 0x1b, 0xe0, 0x0f, 0xf2, 0xa4, 0x59, - 0x00, 0xf0, 0x1e, 0xf8, 0x07, 0xf0, 0x3f, 0x01, 0x0a, 0xe0, 0x0f, 0xf2, - 0xa8, 0x50, 0x30, 0xf8, 0x15, 0x00, 0xe1, 0xb2, 0x0e, 0xe0, 0x0f, 0xf2, - 0xa0, 0x59, 0x00, 0xf0, 0x11, 0xf8, 0xf9, 0xb2, 0x09, 0xeb, 0x85, 0x00, - 0x40, 0x88, 0xfd, 0xf7, 0x9b, 0xfa, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, - 0xf1, 0xb2, 0x40, 0x46, 0xbd, 0xe8, 0xf4, 0x43, 0xfd, 0xf7, 0x92, 0xba, - 0xbd, 0xe8, 0xf1, 0x83, 0x39, 0xf8, 0x25, 0x00, 0xe1, 0xb2, 0xfd, 0xf7, - 0x8b, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0xdf, 0xf8, 0xe0, 0x44, 0xfe, 0xf7, - 0xa7, 0xfb, 0x20, 0x60, 0x01, 0x21, 0x2e, 0x20, 0x02, 0xf0, 0x6d, 0xfa, - 0x20, 0x68, 0x6b, 0x46, 0x00, 0x22, 0x04, 0x21, 0xfc, 0xf7, 0x30, 0xfc, - 0x4f, 0xf0, 0x8a, 0x40, 0x01, 0x68, 0x61, 0x60, 0x41, 0x68, 0x01, 0xf4, - 0xa0, 0x71, 0x41, 0xf0, 0x11, 0x01, 0x41, 0x60, 0x13, 0xbd, 0x30, 0xb5, - 0x83, 0xb0, 0xfe, 0xf7, 0x8d, 0xfb, 0xdf, 0xf8, 0xa4, 0x14, 0x08, 0x60, - 0x01, 0xa9, 0x00, 0x91, 0x41, 0xf2, 0x88, 0x33, 0x03, 0x22, 0x05, 0x21, - 0xfc, 0xf7, 0x8a, 0xfb, 0xc0, 0x07, 0x4f, 0xf0, 0x8a, 0x44, 0x04, 0xd5, - 0x2f, 0x20, 0x02, 0xf0, 0x36, 0xfa, 0x01, 0x25, 0x0b, 0xe0, 0xa0, 0x68, - 0xc0, 0x07, 0x04, 0xd5, 0x30, 0x20, 0x02, 0xf0, 0x2e, 0xfa, 0x00, 0x25, - 0x03, 0xe0, 0x31, 0x20, 0x02, 0xf0, 0x29, 0xfa, 0x02, 0x25, 0xa0, 0x68, - 0xc0, 0x07, 0x07, 0xd4, 0x20, 0x68, 0x20, 0xf0, 0x7e, 0x50, 0x20, 0x60, - 0x60, 0x68, 0x40, 0xf0, 0x01, 0x00, 0x60, 0x60, 0x00, 0x21, 0x2e, 0x20, - 0x02, 0xf0, 0x29, 0xfa, 0x28, 0x46, 0x3e, 0xbd, 0xdf, 0xf8, 0x44, 0x04, - 0x01, 0x68, 0x41, 0xf0, 0x02, 0x01, 0x01, 0x60, 0x70, 0x47, 0x4f, 0xf0, - 0x8a, 0x41, 0x08, 0x60, 0x70, 0x47, 0x02, 0x68, 0x22, 0xf0, 0x7e, 0x52, - 0x42, 0xea, 0xc1, 0x51, 0x01, 0x60, 0x70, 0x47, 0x01, 0x21, 0x00, 0xf0, - 0x1f, 0x02, 0x91, 0x40, 0xc0, 0xf3, 0x41, 0x10, 0x48, 0x43, 0x01, 0xeb, - 0x90, 0x00, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, 0x02, 0xf0, 0x6f, 0xf9, - 0x01, 0x21, 0x81, 0x40, 0x62, 0x1a, 0x89, 0x08, 0xb2, 0xfb, 0xf1, 0xf1, - 0x40, 0xea, 0x41, 0x10, 0xc0, 0xb2, 0x10, 0xbd, 0xdf, 0xf8, 0xf4, 0x13, - 0x0a, 0x68, 0x22, 0xf0, 0xf2, 0x02, 0x00, 0xf0, 0x0f, 0x00, 0x42, 0xea, - 0x00, 0x10, 0x40, 0xf0, 0x04, 0x00, 0x08, 0x60, 0x70, 0x47, 0xdf, 0xf8, - 0xdc, 0x03, 0x01, 0x68, 0x21, 0xf0, 0x04, 0x01, 0xc5, 0xe7, 0x10, 0xb5, - 0xd3, 0x07, 0x12, 0xd5, 0x0f, 0xf2, 0x2c, 0x43, 0x33, 0xf8, 0x20, 0x40, - 0x04, 0xf1, 0x8c, 0x44, 0x03, 0xeb, 0x80, 0x03, 0x24, 0x78, 0xa4, 0x00, - 0x0c, 0x80, 0x5b, 0x88, 0x03, 0xf1, 0x8c, 0x43, 0x1b, 0x78, 0x03, 0xf0, - 0x03, 0x03, 0x23, 0x43, 0x0b, 0x80, 0x92, 0x07, 0x17, 0xd5, 0x0f, 0xf2, - 0x0c, 0x42, 0x32, 0xf8, 0x20, 0x30, 0x03, 0xf1, 0x8c, 0x43, 0x02, 0xeb, - 0x80, 0x00, 0x1b, 0x78, 0x4b, 0x80, 0x40, 0x88, 0x00, 0xf1, 0x8c, 0x40, - 0x00, 0x78, 0x00, 0xf0, 0x3f, 0x00, 0x43, 0xea, 0x00, 0x20, 0x82, 0x04, - 0x48, 0x80, 0x02, 0xd5, 0xde, 0x4a, 0x10, 0x43, 0x48, 0x80, 0x10, 0xbd, - 0x00, 0x21, 0xdd, 0x4a, 0x52, 0xf8, 0x21, 0x20, 0x40, 0xf8, 0x21, 0x20, - 0x49, 0x1c, 0x38, 0x29, 0xf7, 0xd3, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x47, - 0x0d, 0x46, 0xd8, 0x49, 0x49, 0x69, 0x92, 0x46, 0xd7, 0x4a, 0x12, 0x78, - 0x04, 0x46, 0x01, 0x20, 0x13, 0x07, 0x48, 0xbf, 0x04, 0x20, 0x02, 0xd4, - 0x52, 0x07, 0x48, 0xbf, 0x02, 0x20, 0x48, 0x43, 0xd2, 0x49, 0x88, 0x42, - 0x2c, 0xbf, 0x0f, 0xf2, 0xc4, 0x38, 0x0f, 0xf2, 0xb4, 0x38, 0x00, 0x27, - 0x05, 0xeb, 0xc7, 0x00, 0x00, 0xf1, 0x60, 0x06, 0xd6, 0xe9, 0x00, 0x01, - 0x00, 0xf0, 0x84, 0xfe, 0x00, 0xf0, 0xdf, 0xf8, 0xe1, 0x68, 0x00, 0xf0, - 0xbd, 0xff, 0xe0, 0x60, 0xd6, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x7a, 0xfe, - 0x00, 0xf0, 0xd5, 0xf8, 0x21, 0x69, 0x00, 0xf0, 0xb3, 0xff, 0x20, 0x61, - 0xd6, 0xe9, 0x0c, 0x01, 0x00, 0xf0, 0x70, 0xfe, 0x00, 0xf0, 0xcb, 0xf8, - 0x61, 0x69, 0x00, 0xf0, 0xa9, 0xff, 0x60, 0x61, 0xd6, 0xe9, 0x12, 0x01, - 0x00, 0xf0, 0x66, 0xfe, 0x00, 0xf0, 0xc1, 0xf8, 0xa1, 0x69, 0x00, 0xf0, - 0x9f, 0xff, 0x7f, 0x1c, 0x03, 0x2f, 0xa0, 0x61, 0xd0, 0xd3, 0x00, 0x27, - 0x00, 0xf0, 0xbb, 0xf8, 0x00, 0xf0, 0xb2, 0xf8, 0x21, 0x68, 0x00, 0xf0, - 0x93, 0xff, 0x00, 0xf0, 0xbd, 0xf8, 0x00, 0xf0, 0xab, 0xf8, 0x61, 0x68, - 0x00, 0xf0, 0x8c, 0xff, 0x60, 0x60, 0xd9, 0xe9, 0x06, 0x01, 0x00, 0xf0, - 0x49, 0xfe, 0x00, 0xf0, 0xa1, 0xf8, 0xa1, 0x68, 0x00, 0xf0, 0x82, 0xff, - 0x02, 0x2f, 0xa0, 0x60, 0xe4, 0xd3, 0x01, 0x27, 0x00, 0xf0, 0x9f, 0xf8, - 0x00, 0xf0, 0x96, 0xf8, 0x21, 0x68, 0x00, 0xf0, 0x77, 0xff, 0x00, 0xf0, - 0xa1, 0xf8, 0x00, 0xf0, 0x8f, 0xf8, 0x61, 0x68, 0x00, 0xf0, 0x70, 0xff, - 0x60, 0x60, 0xd9, 0xe9, 0x0c, 0x01, 0x00, 0xf0, 0x2d, 0xfe, 0x00, 0xf0, - 0x85, 0xf8, 0xa1, 0x68, 0x00, 0xf0, 0x66, 0xff, 0x02, 0x2f, 0xa0, 0x60, - 0xe4, 0xd3, 0xc0, 0x35, 0xd5, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x20, 0xfe, - 0xe1, 0x69, 0x00, 0xf0, 0x5b, 0xff, 0xe0, 0x61, 0xd5, 0xe9, 0x02, 0x01, - 0x00, 0xf0, 0x18, 0xfe, 0x21, 0x6a, 0x00, 0xf0, 0x53, 0xff, 0x20, 0x62, - 0xd5, 0xe9, 0x04, 0x01, 0x00, 0xf0, 0x10, 0xfe, 0x61, 0x6a, 0x00, 0xf0, - 0x4b, 0xff, 0x60, 0x62, 0xd5, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x08, 0xfe, - 0xa1, 0x6a, 0x00, 0xf0, 0x43, 0xff, 0xa0, 0x62, 0x50, 0x46, 0x00, 0xf0, - 0x3d, 0xfe, 0xe1, 0x6a, 0x00, 0xf0, 0x3c, 0xff, 0xe1, 0x69, 0x05, 0x46, - 0xe5, 0x62, 0x08, 0x46, 0x00, 0xf0, 0xd2, 0xff, 0x29, 0x46, 0x00, 0xf0, - 0x41, 0xfe, 0x01, 0x46, 0x20, 0x68, 0x00, 0xf0, 0xbb, 0xfe, 0x60, 0x63, - 0x25, 0x6a, 0x28, 0x46, 0x29, 0x46, 0x00, 0xf0, 0xc5, 0xff, 0x00, 0xf0, - 0x3c, 0xf8, 0x01, 0x46, 0x60, 0x68, 0x00, 0xf0, 0xaf, 0xfe, 0xa0, 0x63, - 0x29, 0x46, 0xe0, 0x69, 0x00, 0xf0, 0xba, 0xff, 0x00, 0xf0, 0x31, 0xf8, - 0x01, 0x46, 0xa0, 0x68, 0x00, 0xf0, 0xa4, 0xfe, 0xe0, 0x63, 0x66, 0x6a, - 0x00, 0xf0, 0x2c, 0xf8, 0x00, 0xf0, 0x27, 0xf8, 0x01, 0x46, 0xe0, 0x68, - 0x00, 0xf0, 0x9a, 0xfe, 0x20, 0x64, 0x29, 0x46, 0x30, 0x46, 0x00, 0xf0, - 0xa5, 0xff, 0x00, 0xf0, 0x1c, 0xf8, 0x01, 0x46, 0x60, 0x69, 0x00, 0xf0, - 0x8f, 0xfe, 0xa0, 0x64, 0xa6, 0x6a, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, - 0x12, 0xf8, 0x01, 0x46, 0x20, 0x69, 0x00, 0xf0, 0x85, 0xfe, 0x60, 0x64, - 0x29, 0x46, 0x30, 0x46, 0x00, 0xf0, 0x90, 0xff, 0x00, 0xf0, 0x07, 0xf8, - 0x01, 0x46, 0xa0, 0x69, 0x00, 0xf0, 0x7a, 0xfe, 0xe0, 0x64, 0xbd, 0xe8, - 0xf0, 0x87, 0xe1, 0x6a, 0x00, 0xf0, 0xf6, 0xbd, 0xe0, 0x69, 0x31, 0x46, - 0x00, 0xf0, 0x80, 0xbf, 0x71, 0x68, 0x00, 0xf0, 0x7d, 0xbf, 0x58, 0xf8, - 0x27, 0x10, 0x00, 0xf0, 0x79, 0xbf, 0x78, 0x42, 0x05, 0xeb, 0xc7, 0x09, - 0x08, 0xeb, 0x80, 0x06, 0xd9, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x96, 0xbd, - 0x20, 0x60, 0x7f, 0x1c, 0xd9, 0xe9, 0x12, 0x01, 0x00, 0xf0, 0x90, 0xbd, - 0x30, 0xb5, 0xb9, 0xb0, 0x04, 0x46, 0x0d, 0x46, 0x68, 0x46, 0xff, 0xf7, - 0xd9, 0xfe, 0x2a, 0x46, 0x69, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xde, 0xfe, - 0x39, 0xb0, 0x30, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, 0x04, 0x46, 0x04, 0xf1, - 0xc0, 0x07, 0x0d, 0x46, 0xd7, 0xe9, 0x02, 0x01, 0x90, 0x46, 0x00, 0xf0, - 0x77, 0xfd, 0x06, 0x46, 0xd7, 0xe9, 0x00, 0x01, 0x00, 0xf0, 0x72, 0xfd, - 0x07, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xaa, 0xfd, 0x80, 0x46, 0xd4, 0xe9, - 0x00, 0x01, 0x00, 0xf0, 0x69, 0xfd, 0x81, 0x46, 0x38, 0x46, 0x39, 0x46, - 0x00, 0xf0, 0x3e, 0xff, 0x41, 0x46, 0x00, 0xf0, 0xad, 0xfd, 0x01, 0x46, - 0x48, 0x46, 0x00, 0xf0, 0x27, 0xfe, 0x07, 0x46, 0xd4, 0xe9, 0x12, 0x01, - 0x00, 0xf0, 0x58, 0xfd, 0x04, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xab, 0xff, - 0x41, 0x46, 0x00, 0xf0, 0x9d, 0xfd, 0x01, 0x46, 0x20, 0x46, 0x00, 0xf0, - 0x17, 0xfe, 0x39, 0x46, 0x00, 0xf0, 0x88, 0xfe, 0x41, 0x46, 0x00, 0xf0, - 0x93, 0xfd, 0x29, 0x46, 0x01, 0xf0, 0x26, 0xf8, 0x94, 0xbf, 0x01, 0x20, - 0x00, 0x20, 0xbd, 0xe8, 0xf2, 0x83, 0x10, 0xb5, 0x28, 0x49, 0x20, 0x4c, - 0x82, 0xb0, 0x4f, 0xf4, 0x80, 0x70, 0x08, 0x60, 0x6b, 0x46, 0x20, 0x68, - 0x01, 0x22, 0x04, 0x21, 0xfc, 0xf7, 0x04, 0xfa, 0x60, 0x68, 0x4f, 0xf0, - 0x8a, 0x41, 0x08, 0x60, 0x13, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x28, 0x46, 0xff, 0xf7, 0xf0, 0xfc, 0x05, 0xf1, 0x08, 0x00, 0xff, 0xf7, - 0x42, 0xf9, 0x01, 0x21, 0xe0, 0xb2, 0xff, 0xf7, 0xe9, 0xfb, 0x1a, 0x4a, - 0xd2, 0xe9, 0x08, 0x01, 0xff, 0xf7, 0x94, 0xfc, 0x01, 0x46, 0xe0, 0xb2, - 0xff, 0xf7, 0xae, 0xfc, 0x00, 0x20, 0xff, 0xf7, 0xb3, 0xfc, 0x03, 0x21, - 0xe0, 0xb2, 0xff, 0xf7, 0xc2, 0xfc, 0x3f, 0x21, 0xe0, 0xb2, 0xff, 0xf7, - 0xc9, 0xfc, 0xff, 0xf7, 0x2c, 0xfc, 0xff, 0xf7, 0x0e, 0xfc, 0x00, 0x2c, - 0x0c, 0xbf, 0x02, 0x20, 0x03, 0x20, 0xbd, 0xe8, 0x34, 0x40, 0x28, 0x21, - 0xff, 0xf7, 0x30, 0xb9, 0x28, 0x00, 0x00, 0x50, 0x58, 0xf3, 0x00, 0x20, - 0x04, 0x00, 0x00, 0x45, 0x04, 0x00, 0x00, 0x51, 0x00, 0xc0, 0xff, 0xff, - 0x00, 0x01, 0x00, 0x45, 0x78, 0x29, 0x00, 0x20, 0x10, 0x09, 0x00, 0x46, - 0x01, 0x1c, 0x4e, 0x0e, 0x40, 0x00, 0x00, 0x50, 0x00, 0xf2, 0x00, 0x20, - 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x07, 0xf0, 0x53, 0xfe, 0x28, 0x60, - 0x29, 0x1d, 0x20, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0xaf, 0xe7, 0x10, 0xb5, - 0x04, 0x46, 0x04, 0xf1, 0x08, 0x00, 0xff, 0xf7, 0xfd, 0xf8, 0x20, 0x46, - 0xbd, 0xe8, 0x10, 0x40, 0xff, 0xf7, 0xa8, 0xbc, 0x38, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x28, 0x1d, 0xff, 0xf7, 0xef, 0xff, 0x29, 0x68, 0x20, 0x46, - 0xbd, 0xe8, 0x34, 0x40, 0x07, 0xf0, 0x3e, 0xbe, 0x00, 0x07, 0x01, 0x07, - 0x02, 0x07, 0x03, 0x07, 0x12, 0x0a, 0x13, 0x0a, 0x1f, 0x0a, 0x20, 0x0a, - 0xee, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xaa, 0x09, 0xab, 0x09, - 0x10, 0x0a, 0x11, 0x0a, 0x1d, 0x0a, 0x1e, 0x0a, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xb3, 0x7b, 0x72, 0x3e, - 0x99, 0xbb, 0x06, 0x3f, 0xb3, 0x7b, 0x72, 0x3e, 0x0f, 0x4a, 0x80, 0x04, - 0x80, 0x0c, 0x10, 0x60, 0x88, 0x04, 0x80, 0x0c, 0x50, 0x60, 0x70, 0x47, - 0x0c, 0x4a, 0x10, 0x60, 0x51, 0x60, 0x70, 0x47, 0x4f, 0xf0, 0xa2, 0x41, - 0x0a, 0x68, 0x22, 0xf0, 0x80, 0x42, 0x42, 0xea, 0x80, 0x70, 0x08, 0x60, - 0x48, 0x68, 0x40, 0xf0, 0x08, 0x00, 0x48, 0x60, 0x70, 0x47, 0x05, 0x48, - 0x01, 0x68, 0x21, 0xf0, 0x08, 0x01, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, - 0x0c, 0x00, 0x00, 0x51, 0x20, 0x00, 0x00, 0x51, 0x04, 0x00, 0x00, 0x51, - 0x38, 0xb5, 0xdf, 0xf8, 0x90, 0x46, 0xa8, 0x21, 0x20, 0x46, 0x01, 0xf0, - 0x05, 0xfd, 0x00, 0x25, 0xfc, 0xf7, 0x1c, 0xfd, 0x54, 0x21, 0x01, 0xfb, - 0x05, 0x41, 0x6d, 0x1c, 0x02, 0x2d, 0x08, 0x64, 0xf6, 0xd3, 0x0f, 0xf2, - 0xd8, 0x61, 0xdf, 0xf8, 0x70, 0x06, 0x1c, 0xc9, 0x1c, 0xc0, 0x31, 0xbd, - 0x2d, 0xe9, 0xf0, 0x47, 0xdf, 0xf8, 0x64, 0x06, 0x84, 0xb0, 0x80, 0x7a, - 0x0c, 0x46, 0x00, 0xf0, 0x03, 0x09, 0xff, 0xf7, 0xdd, 0xff, 0x00, 0x27, - 0x00, 0x26, 0x0d, 0xf1, 0x04, 0x0a, 0x29, 0xfa, 0x06, 0xf0, 0xc0, 0x07, - 0x4f, 0xd5, 0xdf, 0xf8, 0x40, 0x06, 0x26, 0x60, 0x00, 0xf1, 0x40, 0x01, - 0x61, 0x60, 0x54, 0x22, 0x00, 0xf1, 0x0c, 0x01, 0xa1, 0x60, 0x01, 0x25, - 0xdf, 0xf8, 0x24, 0x16, 0x02, 0xfb, 0x06, 0x18, 0x06, 0x21, 0x01, 0xfb, - 0x06, 0x00, 0x6c, 0x30, 0xe0, 0x61, 0xc4, 0xf8, 0x0c, 0x80, 0x20, 0x46, - 0x00, 0xf0, 0x18, 0xfb, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x8c, 0xfa, - 0x07, 0x00, 0x19, 0xd1, 0xe1, 0x69, 0x60, 0x68, 0x01, 0xeb, 0x45, 0x01, - 0x00, 0x91, 0x14, 0x21, 0x01, 0xfb, 0x05, 0x01, 0x0b, 0x1d, 0xb0, 0xf9, - 0x02, 0x20, 0x01, 0x88, 0x20, 0x68, 0x01, 0xf0, 0x5a, 0xfb, 0x00, 0xb1, - 0x05, 0x20, 0x4a, 0xf8, 0x25, 0x00, 0x20, 0xb9, 0xe0, 0x69, 0x10, 0xf8, - 0x15, 0x00, 0x5a, 0x28, 0x00, 0xda, 0x05, 0x27, 0x29, 0x46, 0x20, 0x46, - 0x00, 0xf0, 0xa6, 0xfa, 0xc7, 0xb9, 0xe1, 0x69, 0x11, 0xf8, 0x15, 0x20, - 0x08, 0xeb, 0x85, 0x00, 0x48, 0x30, 0x01, 0xeb, 0x45, 0x01, 0x42, 0x80, - 0x6d, 0x1e, 0x49, 0x78, 0x01, 0x80, 0xcd, 0xd5, 0xe0, 0x68, 0x50, 0x30, - 0x01, 0x21, 0x41, 0x80, 0x01, 0x80, 0x76, 0x1c, 0x02, 0x2e, 0xa8, 0xd3, - 0x38, 0x46, 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x87, 0xe0, 0x68, 0x50, 0x30, - 0x00, 0x21, 0x41, 0x80, 0x01, 0x80, 0xf5, 0xe7, 0x70, 0x47, 0x2d, 0xe9, - 0xf0, 0x4f, 0x0c, 0x46, 0x8b, 0xb0, 0xdf, 0xf8, 0x7c, 0x15, 0x20, 0x60, - 0x01, 0xf1, 0x40, 0x02, 0x62, 0x60, 0x54, 0x23, 0x01, 0xf1, 0x0c, 0x02, - 0xa2, 0x60, 0x4f, 0xf4, 0x84, 0x5a, 0xdf, 0xf8, 0x60, 0x25, 0x03, 0xfb, - 0x00, 0x22, 0xe2, 0x60, 0x06, 0x22, 0x02, 0xfb, 0x00, 0x10, 0x6c, 0x30, - 0xe0, 0x61, 0xfb, 0xf7, 0x99, 0xfd, 0xe0, 0x68, 0x01, 0x6c, 0x41, 0x64, - 0xfc, 0xf7, 0x7c, 0xfc, 0x01, 0x46, 0xe0, 0x68, 0x01, 0x64, 0x52, 0x46, - 0xc1, 0x6b, 0x49, 0x1c, 0xc1, 0x63, 0x08, 0x21, 0x07, 0xf0, 0x72, 0xfe, - 0xe0, 0x68, 0xe1, 0x69, 0xb0, 0xf8, 0x4a, 0x00, 0x08, 0x70, 0xe0, 0x68, - 0xe1, 0x69, 0xb0, 0xf8, 0x48, 0x00, 0x48, 0x70, 0xe0, 0x68, 0xe1, 0x69, - 0xb0, 0xf8, 0x4e, 0x00, 0x88, 0x70, 0xe0, 0x68, 0xe1, 0x69, 0xb0, 0xf8, - 0x4c, 0x00, 0xc8, 0x70, 0xfb, 0xf7, 0x89, 0xfd, 0x20, 0x46, 0x00, 0xf0, - 0x8f, 0xfa, 0xe0, 0x68, 0xb0, 0xf8, 0x50, 0x00, 0x10, 0xb9, 0x4f, 0xf0, - 0x05, 0x09, 0x65, 0xe0, 0x01, 0x26, 0x49, 0xf2, 0xb2, 0x27, 0x32, 0x46, - 0x69, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x67, 0xf8, 0x5f, 0xea, 0x00, 0x09, - 0x5a, 0xd1, 0x01, 0x2e, 0x05, 0xd1, 0xe0, 0x68, 0x3a, 0x46, 0x00, 0x21, - 0x07, 0xf0, 0x40, 0xfe, 0xba, 0x46, 0x76, 0x1e, 0xed, 0xd5, 0xfb, 0xf7, - 0x53, 0xfd, 0x00, 0x26, 0xdf, 0xf8, 0xc4, 0xa4, 0xdf, 0xf8, 0xc4, 0x84, - 0x68, 0x46, 0x14, 0x21, 0x01, 0xfb, 0x06, 0x05, 0x01, 0x21, 0x28, 0x68, - 0x07, 0xf0, 0x6e, 0xfe, 0xe7, 0x68, 0x0c, 0x21, 0x01, 0xfb, 0x06, 0x7b, - 0x41, 0x46, 0x00, 0xf0, 0x5d, 0xfd, 0x51, 0x46, 0x00, 0xf0, 0x5a, 0xfd, - 0x00, 0xf0, 0xc4, 0xfd, 0xcb, 0xf8, 0x14, 0x00, 0x51, 0x46, 0x68, 0x68, - 0x00, 0xf0, 0x52, 0xfd, 0x00, 0xf0, 0xbc, 0xfd, 0xcb, 0xf8, 0x18, 0x00, - 0x51, 0x46, 0xa8, 0x68, 0x00, 0xf0, 0x4a, 0xfd, 0x00, 0xf0, 0xb4, 0xfd, - 0xcb, 0xf8, 0x1c, 0x00, 0x01, 0x21, 0xe8, 0x68, 0x07, 0xf0, 0x4c, 0xfe, - 0x01, 0x46, 0x40, 0x46, 0x00, 0xf0, 0x3e, 0xfd, 0x51, 0x46, 0x00, 0xf0, - 0x3b, 0xfd, 0x07, 0xeb, 0xc6, 0x07, 0x00, 0xf0, 0xa3, 0xfd, 0xf8, 0x62, - 0x01, 0x21, 0x28, 0x69, 0x07, 0xf0, 0x3c, 0xfe, 0x41, 0x46, 0x00, 0xf0, - 0x2f, 0xfd, 0x51, 0x46, 0x00, 0xf0, 0x2c, 0xfd, 0x00, 0xf0, 0x96, 0xfd, - 0x76, 0x1c, 0x02, 0x2e, 0x38, 0x63, 0xb9, 0xdb, 0xfb, 0xf7, 0x1b, 0xfd, - 0x49, 0xf6, 0xe4, 0x2a, 0xe0, 0x68, 0x52, 0x46, 0x49, 0x46, 0x07, 0xf0, - 0xe7, 0xfd, 0x48, 0x46, 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, - 0xf7, 0x4f, 0x92, 0xb0, 0x00, 0x24, 0x12, 0x98, 0x03, 0x94, 0x02, 0x94, - 0xa0, 0x46, 0x00, 0x68, 0x14, 0x99, 0x01, 0x90, 0x12, 0x98, 0x00, 0xf0, - 0x83, 0xf9, 0x00, 0x90, 0x10, 0xb1, 0x00, 0xf0, 0xe7, 0xf8, 0xd7, 0xe0, - 0x12, 0x98, 0xc0, 0x69, 0x14, 0x99, 0x10, 0xf8, 0x11, 0x10, 0x01, 0x98, - 0x03, 0xf0, 0x91, 0xfe, 0xa3, 0x46, 0x77, 0xe0, 0x00, 0x26, 0x04, 0xaa, - 0x04, 0xa8, 0x32, 0xf9, 0x26, 0x20, 0x00, 0xeb, 0x86, 0x0a, 0xd3, 0x17, - 0xa2, 0xfb, 0x02, 0x57, 0xba, 0xf9, 0x02, 0x00, 0x02, 0xfb, 0x03, 0x77, - 0x03, 0xfb, 0x02, 0x77, 0xc1, 0x17, 0xa0, 0xfb, 0x00, 0x23, 0x00, 0xfb, - 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0x39, 0x46, 0xa8, 0x18, 0x59, 0x41, - 0x00, 0xf0, 0x06, 0xfb, 0x03, 0x99, 0x00, 0xf0, 0x41, 0xfc, 0x03, 0x90, - 0x0b, 0xa8, 0x00, 0xeb, 0x86, 0x09, 0x30, 0xf9, 0x26, 0x00, 0xc1, 0x17, - 0xa0, 0xfb, 0x00, 0x23, 0xb9, 0xf9, 0x02, 0x50, 0x00, 0xfb, 0x01, 0x33, - 0x01, 0xfb, 0x00, 0x33, 0xef, 0x17, 0xa5, 0xfb, 0x05, 0x01, 0x05, 0xfb, - 0x07, 0x11, 0x07, 0xfb, 0x05, 0x11, 0x10, 0x18, 0x59, 0x41, 0x00, 0xf0, - 0xe9, 0xfa, 0x21, 0x46, 0x00, 0xf0, 0x24, 0xfc, 0x04, 0x46, 0x0b, 0xa8, - 0xb9, 0xf9, 0x02, 0x50, 0x30, 0xf9, 0x26, 0x90, 0xba, 0xf9, 0x02, 0x20, - 0x04, 0xa8, 0xef, 0x17, 0x30, 0xf9, 0x26, 0xc0, 0xa2, 0xfb, 0x05, 0x01, - 0xd3, 0x17, 0x02, 0xfb, 0x07, 0x11, 0x03, 0xfb, 0x05, 0x11, 0xcc, 0xfb, - 0x09, 0x01, 0x00, 0xf0, 0xcf, 0xfa, 0x02, 0x99, 0x00, 0xf0, 0x0a, 0xfc, - 0x02, 0x90, 0x2a, 0x46, 0x04, 0xa8, 0x3b, 0x46, 0x30, 0xf9, 0x26, 0x00, - 0xa0, 0xfb, 0x02, 0x57, 0xc1, 0x17, 0x00, 0xfb, 0x03, 0x77, 0x0b, 0xa8, - 0x01, 0xfb, 0x02, 0x77, 0x30, 0xf9, 0x26, 0x00, 0xba, 0xf9, 0x02, 0x10, - 0x81, 0xfb, 0x00, 0x01, 0x28, 0x1a, 0x67, 0xeb, 0x01, 0x01, 0x00, 0xf0, - 0xb3, 0xfa, 0x41, 0x46, 0x00, 0xf0, 0xee, 0xfb, 0x76, 0x1c, 0x07, 0x2e, - 0x80, 0x46, 0x8a, 0xd3, 0x0b, 0xf1, 0x01, 0x0b, 0x00, 0xf0, 0x5b, 0xf8, - 0x83, 0x45, 0x19, 0xd2, 0x01, 0x98, 0x07, 0x23, 0x04, 0xaa, 0x0b, 0xa9, - 0x03, 0xf0, 0x4e, 0xfe, 0xfe, 0xf7, 0x8f, 0xf8, 0x00, 0x28, 0x3f, 0xf4, - 0x79, 0xaf, 0x12, 0x99, 0xc9, 0x68, 0x06, 0x20, 0x08, 0x60, 0xab, 0xf1, - 0x01, 0x0b, 0x00, 0xf0, 0x4d, 0xf8, 0x14, 0x99, 0x12, 0x98, 0x00, 0xf0, - 0xe1, 0xf8, 0x00, 0x28, 0x00, 0x90, 0xdf, 0xd0, 0x00, 0xf0, 0x44, 0xf8, - 0x00, 0x98, 0x00, 0x28, 0x32, 0xd1, 0x13, 0x98, 0x14, 0x99, 0x14, 0x22, - 0x02, 0xfb, 0x01, 0x06, 0x00, 0xf0, 0x33, 0xf8, 0xc0, 0xeb, 0xc0, 0x00, - 0x00, 0xf0, 0xae, 0xfa, 0x05, 0x46, 0x20, 0x46, 0x29, 0x46, 0x00, 0xf0, - 0xc3, 0xfa, 0x00, 0xf0, 0xf5, 0xfb, 0x00, 0xf0, 0x23, 0xf8, 0xf0, 0x60, - 0x29, 0x46, 0x03, 0x98, 0x00, 0xf0, 0xba, 0xfa, 0x00, 0xf0, 0xec, 0xfb, - 0x00, 0xf0, 0x1a, 0xf8, 0x30, 0x61, 0xf1, 0x68, 0x00, 0xf0, 0xb2, 0xfa, - 0x30, 0x60, 0x21, 0x46, 0x9a, 0x48, 0x00, 0xf0, 0x3b, 0xfc, 0x00, 0xf0, - 0x0f, 0xf8, 0x04, 0x46, 0x02, 0x98, 0x21, 0x46, 0x00, 0xf0, 0xa6, 0xfa, - 0x70, 0x60, 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xa1, 0xfa, 0xb0, 0x60, - 0x00, 0x98, 0x15, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x90, 0x49, 0x00, 0xf0, - 0x99, 0xba, 0x12, 0x98, 0x01, 0x99, 0x80, 0x68, 0x00, 0xeb, 0x41, 0x00, - 0x80, 0x8a, 0x70, 0x47, 0x14, 0x99, 0x12, 0x98, 0xce, 0xe0, 0x10, 0xb5, - 0x04, 0x46, 0x21, 0x46, 0x08, 0x29, 0xb1, 0xbf, 0x4f, 0xf4, 0x30, 0x60, - 0x40, 0xf6, 0x01, 0x30, 0x08, 0x39, 0x89, 0xb2, 0x00, 0xf1, 0x8c, 0x42, - 0x01, 0x23, 0x12, 0x78, 0x03, 0xfa, 0x01, 0xf1, 0x8a, 0x43, 0x11, 0x43, - 0xc9, 0xb2, 0xfc, 0xf7, 0x49, 0xfd, 0x04, 0x2c, 0x40, 0xf6, 0x06, 0x30, - 0x7e, 0x49, 0x05, 0xda, 0x09, 0x78, 0x01, 0xf0, 0xf0, 0x01, 0x41, 0xf0, - 0x03, 0x01, 0x0e, 0xe0, 0x08, 0x2c, 0x05, 0xda, 0x09, 0x78, 0x01, 0xf0, - 0x0f, 0x01, 0x41, 0xf0, 0x30, 0x01, 0x06, 0xe0, 0x48, 0x78, 0x00, 0xf0, - 0xf0, 0x00, 0x40, 0xf0, 0x03, 0x01, 0x40, 0xf6, 0x07, 0x30, 0xbd, 0xe8, - 0x10, 0x40, 0xfc, 0xf7, 0x2b, 0xbd, 0x10, 0xb5, 0x08, 0x28, 0xb2, 0xbf, - 0x40, 0xf6, 0x02, 0x32, 0x40, 0xf6, 0x03, 0x32, 0x08, 0x38, 0x02, 0xf1, - 0x8c, 0x43, 0x01, 0x24, 0x1b, 0x78, 0x84, 0x40, 0x23, 0xea, 0x04, 0x00, - 0x01, 0xb1, 0x20, 0x43, 0xbd, 0xe8, 0x10, 0x40, 0xc1, 0xb2, 0x10, 0x46, - 0xfc, 0xf7, 0x14, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0xa0, 0x68, 0x22, 0x68, - 0x00, 0xeb, 0x42, 0x00, 0x01, 0x29, 0x02, 0x89, 0x80, 0x88, 0x02, 0xd1, - 0x52, 0x1e, 0x92, 0x41, 0xd2, 0x0f, 0x11, 0x46, 0xff, 0xf7, 0xd9, 0xff, - 0x5e, 0x48, 0x58, 0x4d, 0x00, 0x68, 0x21, 0x68, 0x05, 0xeb, 0x81, 0x01, - 0x08, 0x63, 0xfc, 0xf7, 0x83, 0xfa, 0x21, 0x68, 0x05, 0xeb, 0x81, 0x01, - 0x88, 0x63, 0x00, 0x21, 0x20, 0x68, 0x05, 0xeb, 0x80, 0x00, 0xbd, 0xe8, - 0x34, 0x40, 0x00, 0x1d, 0xfe, 0xf7, 0x20, 0xbf, 0xf8, 0xb5, 0x04, 0x46, - 0x53, 0x4d, 0x4c, 0x4e, 0x51, 0x48, 0x07, 0x68, 0xfc, 0xf7, 0x6e, 0xfa, - 0x06, 0xf1, 0x38, 0x02, 0x06, 0xf1, 0x30, 0x01, 0x52, 0xf8, 0x24, 0x20, - 0x51, 0xf8, 0x24, 0x10, 0x80, 0x1a, 0x2a, 0x6c, 0xc9, 0x1b, 0x02, 0xfb, - 0x00, 0x10, 0x06, 0xeb, 0x84, 0x01, 0x49, 0x68, 0x49, 0xb9, 0x06, 0xf1, - 0x28, 0x01, 0x51, 0xf8, 0x24, 0x10, 0x88, 0x42, 0x03, 0xd2, 0xfd, 0xf7, - 0xa2, 0xff, 0x00, 0x28, 0xe0, 0xd0, 0xf1, 0xbd, 0x70, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x00, 0x21, 0x00, 0x20, 0xfc, 0xf7, 0x18, 0xff, 0x01, 0x2d, - 0x03, 0xd1, 0x01, 0x21, 0x20, 0x46, 0xff, 0xf7, 0xa9, 0xff, 0x20, 0x68, - 0x04, 0xf1, 0x10, 0x01, 0x03, 0xf0, 0xf5, 0xfd, 0x06, 0x00, 0x09, 0xd1, - 0xe0, 0x69, 0x00, 0xeb, 0x45, 0x01, 0x20, 0x68, 0x03, 0xf0, 0x48, 0xfe, - 0x20, 0x68, 0x03, 0xf0, 0x2a, 0xfe, 0x06, 0x46, 0x01, 0x2e, 0x0b, 0xd0, - 0x02, 0x2e, 0x0b, 0xd0, 0x0c, 0x2e, 0x0b, 0xd0, 0x11, 0x2e, 0x0b, 0xd0, - 0x13, 0x2e, 0x0b, 0xd0, 0x14, 0x2e, 0x08, 0xbf, 0x0a, 0x26, 0x08, 0xe0, - 0x02, 0x26, 0x06, 0xe0, 0x01, 0x26, 0x04, 0xe0, 0x0b, 0x26, 0x02, 0xe0, - 0x03, 0x26, 0x00, 0xe0, 0x09, 0x26, 0x20, 0x68, 0xff, 0xf7, 0xa4, 0xff, - 0x30, 0x46, 0x70, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xfd, 0xf7, - 0xcf, 0xf9, 0x03, 0x28, 0x06, 0xd1, 0x07, 0xf0, 0xd5, 0xfe, 0x00, 0x21, - 0x04, 0xf1, 0x10, 0x00, 0xfe, 0xf7, 0xcf, 0xfe, 0x01, 0x2d, 0x03, 0xd1, - 0x00, 0x21, 0x20, 0x46, 0xff, 0xf7, 0x68, 0xff, 0xbd, 0xe8, 0x32, 0x40, - 0x00, 0x20, 0xfc, 0xf7, 0x29, 0xbf, 0x70, 0xb5, 0x11, 0x4b, 0x03, 0xeb, - 0x40, 0x01, 0x00, 0x22, 0x0d, 0x7c, 0x8c, 0x8a, 0x08, 0x2d, 0x02, 0xdb, - 0x08, 0x3d, 0xed, 0xb2, 0x01, 0x22, 0x01, 0x26, 0x06, 0xfa, 0x05, 0xf5, - 0xd6, 0x5c, 0xae, 0x43, 0xd6, 0x54, 0x04, 0xb9, 0x00, 0x25, 0xd2, 0x18, - 0x03, 0xeb, 0x80, 0x00, 0x94, 0x78, 0x2c, 0x43, 0x94, 0x70, 0x01, 0x22, - 0x42, 0x60, 0x0b, 0x4a, 0x09, 0x8b, 0xd2, 0x6b, 0x51, 0x43, 0x81, 0x62, - 0x70, 0xbd, 0x00, 0x00, 0x94, 0xed, 0x00, 0x20, 0xec, 0x2b, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0xa0, 0x41, - 0xf4, 0xfd, 0xb4, 0x47, 0x06, 0x0b, 0x00, 0x46, 0x18, 0xe0, 0x00, 0xe0, - 0x00, 0xf2, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, 0xe0, 0x69, 0x80, 0x88, - 0xd0, 0xb9, 0xa0, 0x68, 0x21, 0x68, 0x00, 0xeb, 0x41, 0x00, 0x00, 0x8a, - 0x20, 0x28, 0x09, 0xda, 0xff, 0xf7, 0xd5, 0xfe, 0xa0, 0x68, 0x22, 0x68, - 0x00, 0xeb, 0x42, 0x00, 0x01, 0x21, 0x00, 0x8a, 0xff, 0xf7, 0x01, 0xff, - 0xa0, 0x68, 0x21, 0x68, 0x00, 0xeb, 0x41, 0x00, 0x80, 0x88, 0xff, 0xf7, - 0xc6, 0xfe, 0xe1, 0x69, 0x01, 0x20, 0x88, 0x80, 0x10, 0xbd, 0x00, 0x00, - 0xff, 0xff, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x38, 0xb5, 0x75, 0x4d, 0x04, 0x46, 0x15, 0xf8, 0x34, 0x10, 0x48, 0x1e, - 0x80, 0x41, 0xc0, 0x0f, 0x01, 0xf0, 0x29, 0xfb, 0x01, 0x20, 0x3f, 0xe0, - 0xf8, 0xb5, 0x06, 0x46, 0x6e, 0x4d, 0x34, 0x46, 0x15, 0xf8, 0x34, 0x00, - 0x01, 0x28, 0x0f, 0x46, 0x18, 0xbf, 0x00, 0x20, 0x01, 0xf0, 0x1b, 0xfb, - 0x6a, 0x48, 0x87, 0x42, 0x28, 0xbf, 0x6a, 0x4f, 0x28, 0x6b, 0x47, 0x43, - 0x30, 0x46, 0x00, 0xf0, 0x4f, 0xf8, 0x30, 0x46, 0x00, 0xf0, 0x53, 0xf8, - 0x05, 0xeb, 0xc4, 0x00, 0x02, 0x21, 0x40, 0x68, 0x07, 0x60, 0xc1, 0x60, - 0x00, 0x21, 0x81, 0x60, 0xf0, 0x21, 0x81, 0x60, 0x02, 0x20, 0x05, 0xf8, - 0x34, 0x00, 0xf1, 0xbd, 0x10, 0xb5, 0x5c, 0x4a, 0x02, 0xeb, 0xc0, 0x01, - 0x4b, 0x68, 0x59, 0x68, 0x14, 0x6b, 0xb1, 0xfb, 0xf4, 0xf1, 0x00, 0x24, - 0x9c, 0x60, 0x01, 0x23, 0x02, 0xf8, 0x30, 0x30, 0x08, 0x46, 0x10, 0xbd, - 0x38, 0xb5, 0x54, 0x4d, 0x04, 0x46, 0x15, 0xf8, 0x34, 0x10, 0x01, 0x29, - 0x18, 0xbf, 0xff, 0xf7, 0xe7, 0xff, 0x00, 0x20, 0x05, 0xf8, 0x34, 0x00, - 0x31, 0xbd, 0x51, 0x49, 0x0a, 0x68, 0x90, 0x42, 0x09, 0xd3, 0x49, 0x68, - 0x80, 0x1a, 0xb0, 0xfb, 0xf1, 0xf0, 0x00, 0x21, 0x01, 0xe0, 0x00, 0xbf, - 0x49, 0x1c, 0x81, 0x42, 0xfb, 0xd3, 0x70, 0x47, 0x10, 0xb4, 0x46, 0x4b, - 0x1b, 0x6b, 0x03, 0xfb, 0x00, 0xf3, 0x06, 0x24, 0xb3, 0xfb, 0xf4, 0xf3, - 0x19, 0x00, 0x00, 0x23, 0x1a, 0x00, 0x8a, 0x42, 0x02, 0xd2, 0x00, 0xbf, - 0x52, 0x1c, 0xfa, 0xe7, 0x10, 0xbc, 0x70, 0x47, 0x3d, 0x49, 0x01, 0xeb, - 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x00, 0x01, 0xf0, 0x01, 0xbb, 0x10, 0xb5, - 0x39, 0x49, 0x01, 0xeb, 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x40, 0x20, 0x46, - 0x01, 0xf0, 0xf8, 0xfa, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x01, 0xf0, - 0xf9, 0xba, 0x33, 0x49, 0x01, 0xeb, 0xc0, 0x00, 0x90, 0xf9, 0x01, 0x00, - 0x01, 0xf0, 0xfb, 0xba, 0x80, 0xb5, 0x06, 0x21, 0x05, 0x20, 0x01, 0xf0, - 0x02, 0xfb, 0x06, 0x21, 0x06, 0x20, 0x01, 0xf0, 0xfe, 0xfa, 0x06, 0x21, - 0x07, 0x20, 0x01, 0xf0, 0xfa, 0xfa, 0x06, 0x21, 0x08, 0x20, 0x01, 0xf0, - 0xf6, 0xfa, 0x06, 0x21, 0x2f, 0x20, 0x01, 0xf0, 0xf2, 0xfa, 0x06, 0x21, - 0x30, 0x20, 0x01, 0xf0, 0xee, 0xfa, 0x06, 0x21, 0x31, 0x20, 0x01, 0xf0, - 0xea, 0xfa, 0x06, 0x21, 0x32, 0x20, 0x01, 0xf0, 0xe6, 0xfa, 0x23, 0x48, - 0x1e, 0x49, 0xc0, 0x6b, 0x08, 0x63, 0x01, 0xbd, 0x38, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0xff, 0xf7, 0x49, 0xff, 0x1b, 0x48, 0x85, 0x42, 0x19, 0x48, - 0x28, 0xbf, 0x1a, 0x4d, 0x01, 0x6b, 0x00, 0xeb, 0xc4, 0x00, 0x69, 0x43, - 0x40, 0x68, 0x01, 0x60, 0x02, 0x21, 0xc1, 0x60, 0x00, 0x21, 0xc1, 0x60, - 0x81, 0x60, 0xf0, 0x21, 0x81, 0x60, 0x31, 0xbd, 0x10, 0x49, 0x01, 0xeb, - 0xc0, 0x00, 0x40, 0x68, 0x40, 0x69, 0x70, 0x47, 0x80, 0xb5, 0x00, 0x20, - 0xff, 0xf7, 0xb1, 0xff, 0x00, 0xf0, 0x12, 0xf8, 0x08, 0x70, 0x01, 0xbd, - 0x80, 0xb5, 0x01, 0x20, 0xff, 0xf7, 0xa9, 0xff, 0x00, 0xf0, 0x0a, 0xf8, - 0x08, 0x72, 0x01, 0xbd, 0x80, 0xb5, 0x02, 0x20, 0xff, 0xf7, 0xa1, 0xff, - 0x00, 0xf0, 0x02, 0xf8, 0x08, 0x74, 0x01, 0xbd, 0x01, 0x49, 0x01, 0x20, - 0x70, 0x47, 0x00, 0x00, 0x78, 0x2a, 0x00, 0x20, 0xc1, 0xe1, 0xe4, 0x00, - 0xc0, 0xe1, 0xe4, 0x00, 0xac, 0x2a, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, - 0x80, 0xb5, 0x03, 0x20, 0xff, 0xf7, 0x8b, 0xff, 0xff, 0xf7, 0xec, 0xff, - 0x08, 0x76, 0x01, 0xbd, 0x00, 0x29, 0x40, 0xf1, 0x0b, 0x80, 0xf4, 0x46, - 0x49, 0x42, 0x40, 0x42, 0x71, 0xf1, 0x00, 0x01, 0x00, 0xf0, 0x0a, 0xf8, - 0x50, 0xf0, 0x00, 0x40, 0x60, 0x47, 0x00, 0x00, 0x50, 0xea, 0x01, 0x02, - 0x00, 0xf0, 0x0e, 0x80, 0x09, 0x42, 0x00, 0xbf, 0x0b, 0xd1, 0xb0, 0xfa, - 0x80, 0xf1, 0x88, 0x40, 0xc1, 0xf1, 0x9d, 0x01, 0xc9, 0x05, 0x02, 0x06, - 0x72, 0xf1, 0x00, 0x42, 0x41, 0xeb, 0x10, 0x20, 0x70, 0x47, 0xb1, 0xfa, - 0x81, 0xf2, 0x41, 0x40, 0x90, 0x40, 0xc2, 0xf1, 0x20, 0x02, 0x61, 0xfa, - 0x02, 0xf1, 0x81, 0xea, 0x00, 0x00, 0x18, 0xbf, 0x40, 0xf0, 0x01, 0x00, - 0x02, 0xf1, 0x9d, 0x01, 0xe8, 0xe7, 0x00, 0x00, 0x00, 0x28, 0x40, 0xf1, - 0x09, 0x80, 0xf4, 0x46, 0x40, 0x42, 0x00, 0xf0, 0x05, 0xf8, 0x50, 0xf0, - 0x00, 0x40, 0x60, 0x47, 0x00, 0x28, 0x00, 0xbf, 0x0a, 0xd0, 0xb0, 0xfa, - 0x80, 0xf1, 0x88, 0x40, 0xd1, 0xf1, 0x9d, 0x01, 0xc9, 0x05, 0x02, 0x06, - 0x72, 0xf1, 0x00, 0x42, 0x41, 0xeb, 0x10, 0x20, 0x70, 0x47, 0x00, 0x00, - 0x10, 0xb5, 0xff, 0x23, 0x13, 0xea, 0xd0, 0x54, 0x1d, 0xbf, 0x13, 0xea, - 0xd1, 0x52, 0x9c, 0x42, 0x9a, 0x42, 0x39, 0xe0, 0xa4, 0x1a, 0xda, 0x07, - 0x80, 0xea, 0x01, 0x03, 0x13, 0x40, 0x42, 0xea, 0x01, 0x21, 0x42, 0xea, - 0x00, 0x20, 0x42, 0x1a, 0x3c, 0xbf, 0x64, 0x1e, 0x01, 0xeb, 0x42, 0x02, - 0x09, 0x0a, 0xb2, 0xfb, 0xf1, 0xfe, 0x01, 0xfb, 0x1e, 0x22, 0x12, 0x02, - 0xb2, 0xfb, 0xf1, 0xf0, 0x01, 0xfb, 0x10, 0x22, 0x6e, 0xf3, 0x0f, 0x20, - 0x12, 0x02, 0xb2, 0xfb, 0xf1, 0xfe, 0x4e, 0xea, 0x00, 0x20, 0x7f, 0x34, - 0x06, 0xdd, 0xfe, 0x2c, 0x24, 0xda, 0x53, 0xea, 0x50, 0x00, 0x50, 0xeb, - 0xc4, 0x50, 0x10, 0xbd, 0xd4, 0xf1, 0x02, 0x04, 0x01, 0xfb, 0x1e, 0x22, - 0x40, 0xf0, 0x80, 0x71, 0x19, 0x2c, 0x1d, 0xdc, 0x21, 0xfa, 0x04, 0xf0, - 0xc4, 0xf1, 0x20, 0x04, 0xa1, 0x40, 0x11, 0x43, 0x71, 0xf1, 0x00, 0x42, - 0x58, 0x41, 0x10, 0xbd, 0x9c, 0x42, 0x1a, 0xbf, 0x03, 0xea, 0xd1, 0x52, - 0x9a, 0x42, 0x0f, 0xe0, 0x80, 0xea, 0x01, 0x0e, 0x0e, 0xf0, 0x00, 0x43, - 0x40, 0x00, 0x04, 0xd0, 0x49, 0x00, 0x16, 0xd1, 0x43, 0xf0, 0xff, 0x40, - 0x10, 0xbd, 0x49, 0x00, 0x08, 0xbf, 0xd3, 0x43, 0x18, 0x00, 0x10, 0xbd, - 0x9c, 0x42, 0x05, 0xd1, 0xd2, 0x1a, 0xf7, 0xd0, 0x01, 0xf0, 0x00, 0x41, - 0x48, 0x40, 0x10, 0xbd, 0x4a, 0x02, 0x12, 0xbf, 0x08, 0x46, 0x48, 0x40, - 0x00, 0xf0, 0x00, 0x40, 0x10, 0xbd, 0x4a, 0xb9, 0x09, 0x02, 0xb1, 0xfa, - 0x81, 0xf2, 0x91, 0x40, 0x44, 0xb1, 0xa4, 0x18, 0xc0, 0x01, 0x40, 0xf0, - 0x00, 0x40, 0x9e, 0xe7, 0xc9, 0x01, 0x41, 0xf0, 0x00, 0x41, 0x52, 0x42, - 0x00, 0x02, 0xb0, 0xfa, 0x80, 0xf4, 0xa0, 0x40, 0x14, 0x1b, 0x94, 0xe7, - 0x90, 0xea, 0x01, 0x0f, 0x44, 0xbf, 0x81, 0xf0, 0x00, 0x41, 0x00, 0xf0, - 0x75, 0xb8, 0x00, 0xbf, 0x43, 0x1a, 0x4f, 0xf0, 0x00, 0x42, 0x3e, 0xbf, - 0x53, 0x40, 0xc0, 0x1a, 0xc9, 0x18, 0x00, 0xbf, 0xd3, 0x09, 0x5f, 0xea, - 0xd0, 0x5c, 0x13, 0xeb, 0x40, 0x0f, 0x34, 0xbf, 0xb3, 0xeb, 0x41, 0x0f, - 0x40, 0xe0, 0x7c, 0xeb, 0xd1, 0x53, 0x0c, 0xd3, 0x42, 0xea, 0x01, 0x21, - 0x22, 0xd8, 0xd1, 0xeb, 0x40, 0x20, 0x09, 0xd3, 0x40, 0x0a, 0x28, 0xbf, - 0x5f, 0xea, 0x50, 0x01, 0x40, 0xeb, 0xcc, 0x50, 0x70, 0x47, 0x40, 0x1a, - 0x15, 0xd0, 0x40, 0x02, 0xb0, 0xfa, 0x80, 0xf2, 0x52, 0x1c, 0x90, 0x40, - 0x40, 0x0a, 0x4f, 0xea, 0x3c, 0x23, 0xb3, 0xeb, 0x02, 0x63, 0x84, 0xbf, - 0x00, 0xeb, 0x73, 0x00, 0x07, 0xe0, 0x40, 0xf4, 0x00, 0x00, 0x1a, 0x16, - 0xdb, 0x07, 0xc2, 0xf1, 0x01, 0x02, 0xd0, 0x40, 0x18, 0x43, 0x70, 0x47, - 0x18, 0x2b, 0xfc, 0xdc, 0x31, 0xfa, 0x03, 0xf2, 0x02, 0xfa, 0x03, 0xf3, - 0x59, 0x1a, 0x38, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0xd2, 0xeb, 0x40, 0x20, - 0x3c, 0xbf, 0x40, 0x00, 0xac, 0xf1, 0x01, 0x0c, 0x5f, 0xea, 0xcc, 0x5c, - 0xc2, 0x05, 0x72, 0xf1, 0x00, 0x41, 0x4c, 0xeb, 0x50, 0x20, 0x70, 0x47, - 0x13, 0xeb, 0x40, 0x0f, 0x0f, 0xd2, 0x4b, 0x00, 0x09, 0xd0, 0xac, 0xeb, - 0xd1, 0x53, 0x02, 0x2b, 0x03, 0xdb, 0x49, 0x02, 0x17, 0x2b, 0xdd, 0xdd, - 0x70, 0x47, 0x91, 0x43, 0x40, 0x1a, 0x43, 0x00, 0xd5, 0xd1, 0x00, 0x20, - 0x70, 0x47, 0x13, 0xeb, 0x41, 0x0f, 0xd0, 0xd3, 0x6f, 0xf0, 0x00, 0x00, - 0x70, 0x47, 0x00, 0x00, 0x90, 0xea, 0x01, 0x0f, 0x44, 0xbf, 0x81, 0xf0, - 0x00, 0x41, 0xff, 0xf7, 0x8d, 0xbf, 0x00, 0xbf, 0x42, 0x1a, 0x3c, 0xbf, - 0x80, 0x1a, 0x89, 0x18, 0x4f, 0xf0, 0x00, 0x4c, 0xc0, 0xf3, 0xc7, 0x52, - 0xff, 0x2a, 0x24, 0xd0, 0xc1, 0xf3, 0xc7, 0x53, 0x13, 0xb3, 0xd2, 0x1a, - 0xd2, 0xf1, 0x19, 0x03, 0x27, 0xdd, 0x4c, 0xea, 0x01, 0x21, 0x4c, 0xfa, - 0x03, 0xf3, 0x21, 0xea, 0x03, 0x03, 0xd1, 0x40, 0xc2, 0x0d, 0x4c, 0xea, - 0x00, 0x20, 0x40, 0x18, 0x34, 0xbf, 0x20, 0xea, 0x0c, 0x00, 0x4c, 0xea, - 0x50, 0x00, 0xd2, 0x05, 0x53, 0xea, 0x00, 0x63, 0x73, 0xeb, 0x0c, 0x0c, - 0x52, 0xeb, 0x10, 0x20, 0x42, 0x00, 0x12, 0xf1, 0x80, 0x7f, 0x38, 0xbf, - 0x70, 0x47, 0xc0, 0x0d, 0xc0, 0x05, 0x70, 0x47, 0x49, 0x02, 0x12, 0xbf, - 0x9a, 0x42, 0x00, 0xeb, 0x51, 0x20, 0xf8, 0xe7, 0xd2, 0xf1, 0x17, 0x03, - 0xd9, 0xd5, 0x70, 0x47, 0x4f, 0xf4, 0x00, 0x02, 0xc1, 0x0d, 0x23, 0xd0, - 0xff, 0x29, 0x29, 0xd2, 0x30, 0xea, 0xc1, 0x50, 0x10, 0x43, 0x7d, 0x31, - 0x49, 0x08, 0x28, 0xbf, 0x00, 0x18, 0x80, 0x00, 0x4f, 0xf0, 0xc0, 0x73, - 0xb0, 0xf1, 0x90, 0x60, 0x06, 0xd4, 0x52, 0x08, 0x0e, 0xd2, 0xc0, 0x1a, - 0x9b, 0x18, 0xd2, 0xeb, 0x40, 0x00, 0xf8, 0xd5, 0x52, 0x08, 0x06, 0xd2, - 0xc0, 0x18, 0x9b, 0x1a, 0xd2, 0xeb, 0x40, 0x00, 0xf1, 0xd5, 0x52, 0x08, - 0xf8, 0xd3, 0x5b, 0x1e, 0x58, 0x08, 0x50, 0xeb, 0xc1, 0x50, 0x70, 0x47, - 0xb0, 0xfa, 0x80, 0xf1, 0x08, 0x39, 0x88, 0x40, 0xf9, 0xd0, 0xd1, 0xf1, - 0x01, 0x01, 0xd8, 0xe7, 0xff, 0x29, 0xf4, 0xd0, 0xd0, 0x42, 0xf2, 0xd8, - 0x40, 0x00, 0xf0, 0xd0, 0xc8, 0x43, 0x07, 0xf0, 0xd1, 0xbf, 0x00, 0x00, - 0x40, 0xea, 0x01, 0x0c, 0x5f, 0xea, 0x4c, 0x0c, 0x07, 0xd0, 0x88, 0x42, - 0x05, 0xd1, 0x4f, 0xea, 0x40, 0x0c, 0x1c, 0xf1, 0x80, 0x7f, 0x98, 0xbf, - 0x80, 0x42, 0x70, 0x47, 0x4f, 0xf0, 0x80, 0x7c, 0x1c, 0xeb, 0x40, 0x0f, - 0x94, 0xbf, 0x1c, 0xeb, 0x41, 0x0f, 0x05, 0xe0, 0x40, 0xea, 0x01, 0x0c, - 0x5f, 0xea, 0x4c, 0x0c, 0x01, 0xd2, 0x88, 0x42, 0x70, 0x47, 0x18, 0xbf, - 0x81, 0x42, 0x70, 0x47, 0xff, 0x22, 0x12, 0xea, 0xd0, 0x5c, 0x1d, 0xbf, - 0x12, 0xea, 0xd1, 0x53, 0x94, 0x45, 0x93, 0x42, 0x2b, 0xe0, 0x9c, 0x44, - 0xd3, 0x07, 0x80, 0xea, 0x01, 0x02, 0x1a, 0x40, 0x43, 0xea, 0x00, 0x20, - 0x43, 0xea, 0x01, 0x21, 0xa1, 0xfb, 0x00, 0x30, 0x41, 0x00, 0x38, 0xbf, - 0x40, 0x00, 0x7c, 0xf1, 0x7f, 0x01, 0x0b, 0xdb, 0xfe, 0x29, 0x4a, 0xda, - 0x5b, 0x08, 0x42, 0xea, 0xc1, 0x51, 0x53, 0xea, 0x00, 0x63, 0x73, 0xf1, - 0x00, 0x4c, 0x51, 0xeb, 0x10, 0x20, 0x70, 0x47, 0xd1, 0xf1, 0x08, 0x0c, - 0xdc, 0xf1, 0x20, 0x01, 0x2f, 0xdb, 0x5b, 0x08, 0x10, 0xfa, 0x01, 0xf1, - 0x0b, 0x43, 0x73, 0xf1, 0x00, 0x41, 0x20, 0xfa, 0x0c, 0xf0, 0x50, 0x41, - 0x70, 0x47, 0x94, 0x45, 0x1c, 0xbf, 0x02, 0xea, 0xd1, 0x53, 0x93, 0x42, - 0x80, 0xea, 0x01, 0x02, 0x02, 0xf0, 0x00, 0x42, 0x1d, 0xd0, 0x40, 0x00, - 0x19, 0xd0, 0x49, 0x00, 0x17, 0xd0, 0x5b, 0xb9, 0x63, 0x45, 0x14, 0xd0, - 0x09, 0x02, 0xb1, 0xfa, 0x81, 0xf3, 0x99, 0x40, 0xbc, 0xeb, 0x03, 0x0c, - 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc1, 0xe7, 0x00, 0x02, 0xb0, 0xfa, - 0x80, 0xfc, 0x10, 0xfa, 0x0c, 0xf0, 0xb3, 0xeb, 0x0c, 0x0c, 0xc9, 0x01, - 0x41, 0xf0, 0x00, 0x41, 0xb6, 0xe7, 0x10, 0x00, 0x70, 0x47, 0x40, 0x00, - 0x0a, 0xd0, 0x49, 0x00, 0x08, 0xd0, 0x10, 0xf1, 0x80, 0x7f, 0x94, 0xbf, - 0x11, 0xf1, 0x80, 0x7f, 0x02, 0xe0, 0x42, 0xf0, 0xff, 0x40, 0x70, 0x47, - 0xd0, 0x43, 0x70, 0x47, 0x41, 0x00, 0x09, 0x0e, 0x7f, 0x39, 0x15, 0xd4, - 0xd1, 0xf1, 0x1f, 0x01, 0x14, 0xd4, 0x40, 0x00, 0x07, 0xd2, 0xc0, 0x01, - 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, 0x48, 0xbf, 0x6f, 0xf0, 0x00, 0x40, - 0x70, 0x47, 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, 0x4c, 0xbf, - 0x4f, 0xf0, 0x00, 0x40, 0x40, 0x42, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, - 0x00, 0x42, 0x4f, 0xf0, 0x00, 0x40, 0x58, 0xbf, 0xc0, 0x43, 0x70, 0x47, - 0xc0, 0xf3, 0xc7, 0x52, 0x7e, 0x3a, 0x09, 0xdd, 0x18, 0x2a, 0x0c, 0xda, - 0x6f, 0xf0, 0x7f, 0x41, 0xd1, 0x40, 0x20, 0xea, 0x51, 0x00, 0x40, 0x18, - 0x88, 0x43, 0x70, 0x47, 0x00, 0xf0, 0x00, 0x40, 0x08, 0xbf, 0x40, 0xf0, - 0x7e, 0x50, 0x70, 0x47, 0x38, 0xb5, 0x0b, 0x46, 0xc3, 0xf3, 0xc7, 0x51, - 0xff, 0x29, 0x02, 0x46, 0x09, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x34, - 0x09, 0xe0, 0x58, 0x02, 0x0c, 0xbf, 0x00, 0x24, 0x6f, 0xf0, 0x01, 0x04, - 0x03, 0xe0, 0x58, 0x02, 0x14, 0xbf, 0x02, 0x24, 0x01, 0x24, 0xc2, 0xf3, - 0xc7, 0x51, 0xff, 0x29, 0x08, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x31, - 0x08, 0xe0, 0x50, 0x02, 0x06, 0xd0, 0x6f, 0xf0, 0x01, 0x01, 0x03, 0xe0, - 0x50, 0x02, 0x14, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x01, 0x2c, 0xb8, 0xbf, - 0x01, 0x29, 0x1c, 0xda, 0x00, 0x2a, 0x46, 0xbf, 0x82, 0xf0, 0x00, 0x42, - 0x08, 0x25, 0x00, 0x25, 0x00, 0x2b, 0x44, 0xbf, 0x83, 0xf0, 0x00, 0x43, - 0x85, 0xf0, 0x06, 0x05, 0x18, 0x46, 0x11, 0x46, 0xff, 0xf7, 0x12, 0xff, - 0x02, 0xd2, 0xff, 0xf7, 0x93, 0xfd, 0x1f, 0xe0, 0x00, 0x2c, 0x04, 0xd5, - 0x10, 0x46, 0x19, 0x46, 0xff, 0xf7, 0x8c, 0xfd, 0x1a, 0xe0, 0x00, 0x20, - 0x18, 0xe0, 0x02, 0x29, 0x01, 0xd1, 0x10, 0x46, 0x32, 0xbd, 0x02, 0x2c, - 0x01, 0xd1, 0x18, 0x46, 0x32, 0xbd, 0x8c, 0x42, 0x0c, 0xbf, 0x4f, 0xf0, - 0x7e, 0x50, 0x00, 0x20, 0x00, 0x2a, 0x4c, 0xbf, 0x08, 0x25, 0x00, 0x25, - 0x00, 0x2b, 0x48, 0xbf, 0x85, 0xf0, 0x06, 0x05, 0x01, 0x29, 0x01, 0xd1, - 0x85, 0xf0, 0x02, 0x05, 0x29, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0x07, 0xf0, - 0xaf, 0xbe, 0x00, 0x00, 0x4f, 0xf0, 0x80, 0x7c, 0x1c, 0xeb, 0x40, 0x0f, - 0x94, 0xbf, 0x1c, 0xeb, 0x41, 0x0f, 0x05, 0xe0, 0x40, 0xea, 0x01, 0x0c, - 0x5f, 0xea, 0x4c, 0x0c, 0x01, 0xd2, 0x81, 0x42, 0x70, 0x47, 0x18, 0xbf, - 0x88, 0x42, 0x70, 0x47, 0x2d, 0xe9, 0xf1, 0x4d, 0x83, 0xb0, 0x0c, 0x46, - 0x03, 0x98, 0x01, 0x94, 0xc0, 0xf3, 0xc7, 0x50, 0xff, 0x28, 0x15, 0x46, - 0x08, 0xd1, 0x03, 0x98, 0x00, 0x27, 0x40, 0x02, 0x0c, 0xbf, 0x4f, 0xf0, - 0x01, 0x08, 0x4f, 0xf0, 0x02, 0x08, 0x13, 0xe0, 0x01, 0x28, 0x07, 0xda, - 0x03, 0xa8, 0x07, 0xf0, 0xfd, 0xfe, 0x01, 0x28, 0x02, 0xdb, 0x00, 0x27, - 0xb8, 0x46, 0x09, 0xe0, 0x03, 0x99, 0x21, 0xf0, 0xff, 0x41, 0x41, 0xf0, - 0x7c, 0x51, 0x03, 0x91, 0xa0, 0xf1, 0x7e, 0x07, 0x4f, 0xf0, 0xff, 0x38, - 0x00, 0x21, 0x01, 0xa8, 0x07, 0xf0, 0xfd, 0xfe, 0x06, 0x46, 0x0d, 0xb1, - 0x00, 0x20, 0x28, 0x80, 0x26, 0xb9, 0x20, 0x46, 0x00, 0x21, 0xff, 0xf7, - 0x91, 0xfe, 0x12, 0xd0, 0xb8, 0xf1, 0x00, 0x0f, 0x12, 0xd5, 0x3f, 0xb2, - 0x01, 0x2f, 0x14, 0xd1, 0x03, 0x98, 0x4f, 0xf0, 0x7c, 0x51, 0xff, 0xf7, - 0x85, 0xfe, 0x06, 0xd0, 0x01, 0x2e, 0x0c, 0xd1, 0x4f, 0xf0, 0x3f, 0x41, - 0xff, 0xf7, 0x7e, 0xfe, 0x2e, 0xd1, 0x4f, 0xf0, 0x7e, 0x50, 0x0d, 0xe1, - 0xb8, 0xf1, 0x02, 0x0f, 0x03, 0xd1, 0x03, 0x98, 0x08, 0xe1, 0x01, 0x2e, - 0x53, 0xdb, 0x02, 0x2e, 0x08, 0xbf, 0x20, 0x46, 0x00, 0xf0, 0x02, 0x81, - 0xb8, 0xf1, 0x01, 0x0f, 0x1a, 0xd1, 0x03, 0x98, 0x00, 0x28, 0x02, 0xd4, - 0x00, 0x2c, 0x43, 0xd5, 0x2f, 0xe0, 0x00, 0x2c, 0x09, 0xd4, 0x00, 0x2e, - 0x3e, 0xd1, 0x4f, 0xf0, 0xff, 0x31, 0x01, 0xa8, 0x07, 0xf0, 0xbf, 0xfe, - 0x00, 0x28, 0x37, 0xd5, 0x34, 0xe0, 0x16, 0xbb, 0x4f, 0xf0, 0xff, 0x31, - 0x01, 0xa8, 0x07, 0xf0, 0xb6, 0xfe, 0x00, 0x28, 0x1b, 0xd5, 0x17, 0xe0, - 0x01, 0x2e, 0x08, 0xd1, 0x00, 0x2c, 0x3f, 0xb2, 0x02, 0xd4, 0x01, 0x2f, - 0x26, 0xda, 0x12, 0xe0, 0x01, 0x2f, 0x10, 0xda, 0x22, 0xe0, 0x00, 0x2c, - 0x0f, 0xd4, 0x66, 0xb9, 0x4f, 0xf0, 0xff, 0x31, 0x01, 0xa8, 0x07, 0xf0, - 0xa0, 0xfe, 0x00, 0x28, 0x44, 0xbf, 0x03, 0x98, 0x00, 0x28, 0x02, 0xd5, - 0x4f, 0xf0, 0x00, 0x40, 0xc8, 0xe0, 0x00, 0x20, 0xc6, 0xe0, 0x07, 0xf0, - 0xbb, 0xfe, 0x22, 0x21, 0x01, 0x60, 0x5e, 0xb9, 0x4f, 0xf0, 0xff, 0x31, - 0x01, 0xa8, 0x07, 0xf0, 0x8c, 0xfe, 0x00, 0x28, 0x44, 0xbf, 0x03, 0x98, - 0x00, 0x28, 0x01, 0xd5, 0x4f, 0x48, 0xb5, 0xe0, 0x4f, 0xf0, 0xff, 0x40, - 0xb2, 0xe0, 0x03, 0x98, 0x00, 0x28, 0x48, 0xbf, 0x00, 0x2e, 0x06, 0xd5, - 0x07, 0xf0, 0xa2, 0xfe, 0x21, 0x21, 0x01, 0x60, 0x6f, 0xf0, 0x00, 0x40, - 0xa6, 0xe0, 0x00, 0x21, 0xff, 0xf7, 0x38, 0xff, 0x38, 0xbf, 0x00, 0x26, - 0x08, 0xd3, 0x80, 0xf0, 0x00, 0x40, 0x03, 0x90, 0x4f, 0xf0, 0xff, 0x31, - 0x01, 0xa8, 0x07, 0xf0, 0x68, 0xfe, 0x06, 0x46, 0x03, 0x98, 0x40, 0x49, - 0xff, 0xf7, 0x0e, 0xfe, 0x06, 0xd2, 0x01, 0x46, 0x4f, 0xf0, 0x80, 0x40, - 0xff, 0xf7, 0x1a, 0xfe, 0x03, 0x90, 0x7f, 0x1e, 0x03, 0x99, 0x3b, 0x48, - 0xff, 0xf7, 0x78, 0xfd, 0x83, 0x46, 0x03, 0x99, 0x4f, 0xf0, 0x7e, 0x50, - 0xff, 0xf7, 0x72, 0xfd, 0x01, 0x46, 0x58, 0x46, 0xff, 0xf7, 0x7c, 0xfc, - 0x80, 0x46, 0x41, 0x46, 0xff, 0xf7, 0x06, 0xfe, 0x82, 0x46, 0xcd, 0xf8, - 0x0c, 0xb0, 0x06, 0xf0, 0xcb, 0xff, 0x51, 0x46, 0xff, 0xf7, 0xfe, 0xfd, - 0x03, 0x99, 0xff, 0xf7, 0xeb, 0xfc, 0x41, 0x46, 0xff, 0xf7, 0xf8, 0xfd, - 0x01, 0x46, 0x03, 0x98, 0xff, 0xf7, 0x58, 0xfd, 0x80, 0x46, 0x38, 0xb2, - 0xff, 0xf7, 0x48, 0xfc, 0x07, 0x46, 0x40, 0x46, 0x27, 0x49, 0xff, 0xf7, - 0x5d, 0xfc, 0x39, 0x46, 0xff, 0xf7, 0x4c, 0xfd, 0x01, 0x90, 0x21, 0x46, - 0xff, 0xf7, 0xe4, 0xfd, 0x00, 0x90, 0x4f, 0xf0, 0x47, 0x41, 0xff, 0xf7, - 0xcd, 0xfd, 0x43, 0xd3, 0x20, 0x49, 0xff, 0xf7, 0xe3, 0xfe, 0x41, 0xd9, - 0x00, 0x21, 0xff, 0xf7, 0xc5, 0xfd, 0x01, 0x46, 0x34, 0xbf, 0x4f, 0xf0, - 0x3f, 0x40, 0x4f, 0xf0, 0x7c, 0x50, 0xff, 0xf7, 0x33, 0xfd, 0xff, 0xf7, - 0x39, 0xfe, 0x82, 0x46, 0x38, 0x46, 0x21, 0x46, 0xff, 0xf7, 0xc8, 0xfd, - 0x07, 0x46, 0x50, 0x46, 0xff, 0xf7, 0x1c, 0xfc, 0x01, 0x46, 0x38, 0x46, - 0xff, 0xf7, 0xb0, 0xfc, 0x10, 0x49, 0xff, 0xf7, 0xbd, 0xfd, 0x07, 0x46, - 0x40, 0x46, 0x21, 0x46, 0xff, 0xf7, 0xb8, 0xfd, 0x39, 0x46, 0xff, 0xf7, - 0x19, 0xfd, 0x00, 0x90, 0x1d, 0xb1, 0xa5, 0xf8, 0x00, 0xa0, 0x4f, 0xf0, - 0x00, 0x0a, 0x52, 0x46, 0x4f, 0xf0, 0x7e, 0x51, 0x68, 0x46, 0x07, 0xf0, - 0x19, 0xfe, 0x68, 0xb1, 0x01, 0x28, 0x0d, 0xd0, 0x13, 0xe0, 0x00, 0xbf, - 0x00, 0x00, 0x80, 0xff, 0xf3, 0x04, 0x35, 0x3f, 0x00, 0x00, 0x80, 0xbf, - 0x18, 0x72, 0x31, 0x3f, 0x01, 0x00, 0x00, 0x47, 0x00, 0x20, 0x01, 0xe0, - 0x4f, 0xf0, 0xff, 0x40, 0x00, 0x90, 0x07, 0xf0, 0xfd, 0xfd, 0x22, 0x21, - 0x01, 0x60, 0x00, 0x2e, 0x00, 0x98, 0x18, 0xbf, 0x80, 0xf0, 0x00, 0x40, - 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x8d, 0x00, 0x22, 0xa0, 0xe6, 0x00, 0x00, - 0xd2, 0xb2, 0x20, 0x3a, 0x22, 0xbf, 0x00, 0xfa, 0x02, 0xf1, 0x00, 0x20, - 0x70, 0x47, 0x52, 0x42, 0xd0, 0x41, 0xd2, 0xf1, 0x20, 0x02, 0x91, 0x40, - 0x41, 0x40, 0xd0, 0x40, 0x90, 0x40, 0x41, 0x40, 0x70, 0x47, 0x00, 0x00, - 0x38, 0xb5, 0x05, 0x46, 0x0d, 0x48, 0x0c, 0x46, 0x41, 0x78, 0x21, 0x70, - 0x6a, 0x46, 0x00, 0x78, 0x60, 0x70, 0xa1, 0x1d, 0x28, 0x46, 0x00, 0xf0, - 0x89, 0xf8, 0x0f, 0xf2, 0x50, 0x10, 0x30, 0xf8, 0x25, 0x10, 0x01, 0xf1, - 0x8c, 0x41, 0x00, 0xeb, 0x85, 0x00, 0x09, 0x78, 0xe1, 0x70, 0x40, 0x88, - 0x00, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x20, 0x71, 0x31, 0xbd, 0x00, 0x00, - 0x6d, 0x09, 0x00, 0x46, 0x38, 0xb5, 0x0d, 0x46, 0x2a, 0x79, 0xe9, 0x78, - 0x04, 0x46, 0x00, 0xf0, 0x47, 0xf8, 0xe9, 0x88, 0x20, 0x46, 0x00, 0xf0, - 0x59, 0xf8, 0x29, 0x78, 0x40, 0xf6, 0x6e, 0x10, 0xfb, 0xf7, 0x86, 0xfe, - 0x69, 0x78, 0xbd, 0xe8, 0x34, 0x40, 0x40, 0xf6, 0x6d, 0x10, 0xfb, 0xf7, - 0x7f, 0xbe, 0x70, 0xb5, 0x55, 0x1c, 0x0e, 0x46, 0x03, 0x2e, 0x04, 0x46, - 0x1d, 0xd0, 0x10, 0x78, 0x00, 0xf0, 0x9f, 0x00, 0x10, 0x70, 0x02, 0x2e, - 0x28, 0x78, 0x00, 0xf0, 0xe0, 0x00, 0x28, 0x70, 0x08, 0xd1, 0x90, 0x78, - 0x13, 0x78, 0x43, 0xea, 0x40, 0x13, 0x13, 0x70, 0x2b, 0x78, 0x43, 0xea, - 0x40, 0x10, 0x28, 0x70, 0x00, 0x2c, 0x10, 0x78, 0x07, 0xbf, 0x00, 0xf0, - 0xfc, 0x00, 0x08, 0x43, 0x00, 0xf0, 0xf3, 0x00, 0x40, 0xea, 0x81, 0x00, - 0x10, 0x70, 0x40, 0xf6, 0x6e, 0x10, 0x11, 0x78, 0xfb, 0xf7, 0x56, 0xfe, - 0x29, 0x78, 0x40, 0xf6, 0x6d, 0x10, 0xfb, 0xf7, 0x51, 0xfe, 0x02, 0x2e, - 0x05, 0xd1, 0x20, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x22, 0x00, 0x21, - 0x00, 0xe0, 0x70, 0xbd, 0x70, 0xb5, 0x39, 0x2a, 0x0f, 0xf2, 0x88, 0x06, - 0x04, 0x46, 0xac, 0xbf, 0x42, 0xf0, 0x40, 0x05, 0x02, 0xf0, 0xbf, 0x05, - 0x36, 0xf8, 0x24, 0x00, 0xfb, 0xf7, 0x3a, 0xfe, 0x29, 0x46, 0x06, 0xeb, - 0x84, 0x00, 0xbd, 0xe8, 0x70, 0x40, 0x40, 0x88, 0xfb, 0xf7, 0x32, 0xbe, - 0x70, 0xb5, 0x04, 0x46, 0x0f, 0xf2, 0x64, 0x06, 0x06, 0xeb, 0x84, 0x00, - 0x0d, 0x46, 0x40, 0x88, 0x29, 0x0a, 0xfb, 0xf7, 0x27, 0xfe, 0x36, 0xf8, - 0x24, 0x00, 0xe9, 0xb2, 0xbd, 0xe8, 0x70, 0x40, 0xfb, 0xf7, 0x20, 0xbe, - 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0x0f, 0xf2, 0x48, 0x08, 0x08, 0xeb, - 0x86, 0x00, 0x0c, 0x46, 0x47, 0x88, 0x15, 0x46, 0x00, 0x21, 0x38, 0x46, - 0xfb, 0xf7, 0x12, 0xfe, 0x07, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x38, 0xf8, - 0x26, 0x10, 0x01, 0xf1, 0x8c, 0x41, 0x09, 0x78, 0x41, 0xea, 0x00, 0x20, - 0x81, 0x0a, 0x80, 0x05, 0x29, 0x70, 0x80, 0x0d, 0x20, 0x80, 0xbd, 0xe8, - 0xf0, 0x81, 0x00, 0x00, 0x67, 0x09, 0x68, 0x09, 0x6a, 0x09, 0x6b, 0x09, - 0x60, 0x09, 0x61, 0x09, 0x62, 0x09, 0x63, 0x09, 0x40, 0x09, 0x41, 0x09, - 0x42, 0x09, 0x43, 0x09, 0x13, 0xf0, 0x00, 0x4c, 0x03, 0xd5, 0x5b, 0x42, - 0x52, 0x42, 0x63, 0xf1, 0x00, 0x03, 0x9c, 0xea, 0x21, 0x0c, 0x00, 0xf0, - 0x17, 0x80, 0x10, 0xb5, 0x64, 0x46, 0x03, 0xd3, 0x49, 0x42, 0x40, 0x42, - 0x61, 0xf1, 0x00, 0x01, 0x00, 0xf0, 0x0e, 0xf8, 0x64, 0x00, 0x04, 0xd3, - 0x49, 0x42, 0x40, 0x42, 0x61, 0xf1, 0x00, 0x01, 0x24, 0x42, 0x03, 0xd5, - 0x5b, 0x42, 0x52, 0x42, 0x63, 0xf1, 0x00, 0x03, 0x10, 0xbd, 0x00, 0x00, - 0x1b, 0x42, 0x13, 0xd1, 0x09, 0x42, 0x36, 0xd1, 0x2a, 0xb1, 0x84, 0x46, - 0xb0, 0xfb, 0xf2, 0xf0, 0x02, 0xfb, 0x10, 0xc2, 0x70, 0x47, 0x07, 0xf0, - 0xff, 0xbd, 0xfc, 0xd3, 0x00, 0x22, 0x00, 0x23, 0x70, 0x47, 0x0b, 0x00, - 0x02, 0x00, 0x00, 0x21, 0x00, 0x20, 0x70, 0x47, 0x90, 0x42, 0x71, 0xeb, - 0x03, 0x0c, 0xf6, 0xd3, 0x70, 0xb5, 0xb1, 0xfa, 0x81, 0xf4, 0xb3, 0xfa, - 0x83, 0xf5, 0x2c, 0x1b, 0xa3, 0x40, 0xc4, 0xf1, 0x20, 0x05, 0x32, 0xfa, - 0x05, 0xf6, 0x33, 0x43, 0xa2, 0x40, 0x5f, 0xf0, 0x00, 0x46, 0xe6, 0x40, - 0x02, 0xe0, 0x5b, 0x08, 0x5f, 0xea, 0x32, 0x02, 0x84, 0x1a, 0x71, 0xeb, - 0x03, 0x05, 0x24, 0xbf, 0x20, 0x46, 0x29, 0x46, 0x76, 0x41, 0xf4, 0xd3, - 0x02, 0x00, 0x0b, 0x00, 0x30, 0x00, 0x00, 0x21, 0x70, 0xbd, 0x01, 0x2a, - 0xcf, 0xd9, 0x70, 0xb5, 0x14, 0x0c, 0x20, 0xd0, 0xb1, 0xfa, 0x81, 0xf4, - 0xb2, 0xfa, 0x82, 0xf5, 0xc4, 0xf1, 0x20, 0x04, 0x64, 0x19, 0xb4, 0xf1, - 0x20, 0x06, 0xd6, 0xd3, 0xb2, 0x40, 0x5f, 0xf0, 0x00, 0x44, 0xf4, 0x40, - 0x00, 0x25, 0x02, 0xe0, 0x52, 0x08, 0x5f, 0xea, 0x33, 0x03, 0xc6, 0x1a, - 0x71, 0xeb, 0x02, 0x0e, 0x24, 0xbf, 0x30, 0x46, 0x71, 0x46, 0x64, 0x41, - 0x6d, 0x41, 0xf3, 0xd3, 0x02, 0x00, 0x0b, 0x00, 0x20, 0x00, 0x29, 0x00, - 0x70, 0xbd, 0x0c, 0x46, 0xb1, 0xfb, 0xf2, 0xf1, 0x02, 0xfb, 0x11, 0x45, - 0x2d, 0x04, 0x45, 0xea, 0x10, 0x45, 0xb5, 0xfb, 0xf2, 0xf4, 0x02, 0xfb, - 0x14, 0x55, 0x80, 0xb2, 0x40, 0xea, 0x05, 0x45, 0xb5, 0xfb, 0xf2, 0xf0, - 0x02, 0xfb, 0x10, 0x52, 0x40, 0xea, 0x04, 0x40, 0x70, 0xbd, 0x00, 0x00, - 0x10, 0xb5, 0xda, 0x48, 0x01, 0x1d, 0x00, 0x22, 0x00, 0x23, 0x0c, 0xc1, - 0x00, 0x21, 0x00, 0x24, 0x1e, 0xc0, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x43, - 0xd5, 0x48, 0x87, 0xb0, 0x80, 0x7a, 0x00, 0xf0, 0x03, 0x08, 0x40, 0x46, - 0xfb, 0xf7, 0xb0, 0xfd, 0x00, 0x24, 0x08, 0xb9, 0x02, 0x20, 0x55, 0xe0, - 0x00, 0x26, 0xdf, 0xf8, 0x38, 0x93, 0xcf, 0x4d, 0x28, 0xfa, 0x06, 0xf0, - 0xc0, 0x07, 0x49, 0xd5, 0x00, 0x27, 0x28, 0x78, 0x01, 0x21, 0xb9, 0x40, - 0x08, 0x42, 0x3f, 0xd0, 0x00, 0x21, 0x00, 0x20, 0xfb, 0xf7, 0x85, 0xff, - 0x01, 0x2f, 0x06, 0xd1, 0x03, 0xa9, 0x30, 0x46, 0xfe, 0xf7, 0x26, 0xfd, - 0x05, 0xf1, 0x18, 0x01, 0x11, 0xe0, 0x68, 0x46, 0xfd, 0xf7, 0x27, 0xfe, - 0x01, 0xa8, 0xfe, 0xf7, 0xce, 0xf9, 0x01, 0x21, 0xf0, 0xb2, 0xfe, 0xf7, - 0xcb, 0xf8, 0xfe, 0xf7, 0x06, 0xf9, 0xb0, 0x1c, 0x28, 0x21, 0x80, 0xb2, - 0xfd, 0xf7, 0x2c, 0xfe, 0x29, 0x1d, 0x09, 0xf1, 0x04, 0x00, 0x00, 0xeb, - 0x86, 0x00, 0x00, 0xeb, 0x47, 0x02, 0x30, 0x46, 0x00, 0xf0, 0x6e, 0xf8, - 0x04, 0x46, 0x40, 0x1e, 0x80, 0x41, 0x09, 0xeb, 0x46, 0x01, 0xc0, 0x0f, - 0x78, 0x54, 0x01, 0x2f, 0x04, 0xd1, 0x03, 0xa9, 0x30, 0x46, 0xfe, 0xf7, - 0x11, 0xfd, 0x05, 0xe0, 0x68, 0x46, 0xfd, 0xf7, 0x05, 0xfe, 0x01, 0xa8, - 0xfe, 0xf7, 0xb2, 0xf9, 0x00, 0x20, 0xfb, 0xf7, 0xa7, 0xff, 0x14, 0xb9, - 0x7f, 0x1c, 0x02, 0x2f, 0xb7, 0xd3, 0x14, 0xb9, 0x76, 0x1c, 0x02, 0x2e, - 0xae, 0xd3, 0x20, 0x46, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0xa2, 0x4a, - 0x02, 0xeb, 0x41, 0x01, 0x40, 0x5c, 0x70, 0x47, 0x9f, 0x4a, 0x02, 0xeb, - 0x81, 0x01, 0x01, 0xeb, 0x40, 0x00, 0x00, 0x1d, 0x70, 0x47, 0x80, 0xb5, - 0xfe, 0xf7, 0x4f, 0xfa, 0xfe, 0xf7, 0x69, 0xfa, 0x02, 0x28, 0x01, 0xd1, - 0x03, 0x20, 0x02, 0xbd, 0x01, 0x28, 0x0c, 0xbf, 0x04, 0x20, 0x00, 0x20, - 0x02, 0xbd, 0xf0, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x96, 0x48, 0x00, 0xeb, - 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x95, 0x4a, 0x02, 0xeb, 0xc4, 0x06, - 0xd6, 0xe9, 0x00, 0x23, 0x80, 0x18, 0x59, 0x41, 0x2a, 0x46, 0x07, 0xf0, - 0xf9, 0xfc, 0xa0, 0xfb, 0x00, 0x67, 0x00, 0xfb, 0x01, 0x77, 0x01, 0xfb, - 0x00, 0x77, 0x8e, 0x48, 0x00, 0xeb, 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, - 0x8c, 0x4a, 0x02, 0xeb, 0xc4, 0x04, 0xd4, 0xe9, 0x00, 0x23, 0x80, 0x1a, - 0x99, 0x41, 0x2a, 0x46, 0x07, 0xf0, 0xe4, 0xfc, 0xa0, 0xfb, 0x00, 0x23, - 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0xb0, 0x18, 0x47, 0xeb, - 0x03, 0x01, 0xf0, 0xbd, 0x2d, 0xe9, 0xf5, 0x4f, 0x0e, 0x46, 0x81, 0xb0, - 0xb6, 0xf9, 0x08, 0x10, 0xb6, 0xf9, 0x06, 0x00, 0xfe, 0xf7, 0xd0, 0xfc, - 0x31, 0x69, 0xf0, 0x68, 0xfe, 0xf7, 0xd4, 0xfc, 0x01, 0x98, 0xfe, 0xf7, - 0xd5, 0xfc, 0x4f, 0xf0, 0x00, 0x0a, 0xd0, 0x46, 0xf0, 0x78, 0x00, 0x27, - 0xc1, 0x46, 0x18, 0xb1, 0xfe, 0xf7, 0x81, 0xfa, 0xc3, 0x46, 0x04, 0xe0, - 0x08, 0x20, 0xfe, 0xf7, 0x6f, 0xfa, 0x4f, 0xf0, 0x08, 0x0b, 0xb6, 0xf9, - 0x06, 0x00, 0x00, 0x28, 0x48, 0xbf, 0x40, 0x42, 0xb6, 0xf9, 0x08, 0x40, - 0x00, 0x2c, 0x48, 0xbf, 0x64, 0x42, 0x84, 0x42, 0x38, 0xbf, 0x04, 0x46, - 0x20, 0x46, 0x00, 0xf0, 0xb7, 0xfb, 0x11, 0x28, 0x04, 0xd2, 0x20, 0x46, - 0x00, 0xf0, 0xb2, 0xfb, 0x11, 0x30, 0x00, 0xe0, 0x22, 0x20, 0xb1, 0x78, - 0x08, 0x18, 0x1d, 0x28, 0x26, 0xbf, 0x1c, 0x38, 0x00, 0x90, 0xcd, 0xf8, - 0x00, 0x80, 0x34, 0x78, 0x10, 0xe0, 0x00, 0x25, 0x00, 0x98, 0x29, 0x46, - 0xff, 0xf7, 0x87, 0xff, 0x89, 0x45, 0x05, 0xdc, 0x01, 0xdb, 0x80, 0x45, - 0x02, 0xd2, 0x2f, 0x19, 0x80, 0x46, 0x89, 0x46, 0x6d, 0x1c, 0x03, 0x2d, - 0xf0, 0xd3, 0xe4, 0x1c, 0x70, 0x78, 0x80, 0x1e, 0xa0, 0x42, 0x08, 0xd3, - 0x01, 0x98, 0x21, 0x04, 0x00, 0xf0, 0x43, 0xf8, 0xff, 0xf7, 0x63, 0xff, - 0x5f, 0xea, 0x00, 0x0a, 0xe1, 0xd0, 0x00, 0xf0, 0x36, 0xf8, 0xf0, 0x78, - 0x00, 0x28, 0x2b, 0xd1, 0x02, 0x99, 0x09, 0x78, 0x01, 0x98, 0x49, 0x1e, - 0x09, 0x04, 0x00, 0xf0, 0x32, 0xf8, 0x00, 0x24, 0x01, 0xe0, 0x08, 0x2c, - 0x1b, 0xd0, 0x20, 0x46, 0xfe, 0xf7, 0x1a, 0xfa, 0xff, 0xf7, 0x4b, 0xff, - 0x5f, 0xea, 0x00, 0x0a, 0x16, 0xd1, 0x00, 0x25, 0x00, 0x98, 0x29, 0x46, - 0xff, 0xf7, 0x51, 0xff, 0x89, 0x45, 0x09, 0xdc, 0x01, 0xdb, 0x80, 0x45, - 0x06, 0xd2, 0x02, 0x9a, 0x12, 0x78, 0xaa, 0x18, 0x57, 0x1e, 0xa3, 0x46, - 0x80, 0x46, 0x89, 0x46, 0x6d, 0x1c, 0x03, 0x2d, 0xec, 0xd3, 0x64, 0x1c, - 0x10, 0x2c, 0xde, 0xd3, 0x00, 0xf0, 0x07, 0xf8, 0xfe, 0xf7, 0x5f, 0xfc, - 0xfe, 0xf7, 0x05, 0xfa, 0x50, 0x46, 0xbd, 0xe8, 0xfe, 0x8f, 0x02, 0x98, - 0x07, 0x70, 0x02, 0x98, 0x80, 0xf8, 0x01, 0xb0, 0x70, 0x47, 0x01, 0xf4, - 0xfe, 0x01, 0x41, 0xea, 0x80, 0x70, 0xb1, 0x78, 0xc9, 0x05, 0x01, 0xf0, - 0x7e, 0x51, 0x08, 0x43, 0x31, 0x79, 0xc9, 0x03, 0x01, 0xf4, 0x00, 0x41, - 0x08, 0x43, 0x40, 0xf0, 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, 0xfe, 0xf7, - 0xb8, 0xb9, 0x70, 0xb5, 0x04, 0x9c, 0x0e, 0x46, 0x15, 0x46, 0x19, 0x46, - 0x22, 0x46, 0xff, 0xf7, 0x45, 0xff, 0xc8, 0xb9, 0x21, 0x78, 0x71, 0x18, - 0x21, 0x70, 0xad, 0xb1, 0xea, 0x10, 0x05, 0xeb, 0x12, 0x72, 0x12, 0x11, - 0xc9, 0xb2, 0x51, 0x18, 0x63, 0x78, 0xa5, 0xeb, 0x02, 0x12, 0xd2, 0x18, - 0x12, 0xb2, 0x00, 0x2a, 0x02, 0xd5, 0x49, 0x1e, 0x10, 0x32, 0x03, 0xe0, - 0x10, 0x2a, 0xa4, 0xbf, 0x49, 0x1c, 0x10, 0x3a, 0x21, 0x70, 0x62, 0x70, - 0x70, 0xbd, 0x10, 0xb5, 0x00, 0x22, 0x17, 0x4b, 0x44, 0x24, 0x00, 0xf0, - 0x31, 0xf8, 0xdc, 0x63, 0x01, 0x24, 0xa3, 0xf8, 0x40, 0x40, 0x94, 0x24, - 0x13, 0x4b, 0x00, 0xf0, 0x29, 0xf8, 0x9c, 0x61, 0x01, 0x24, 0x9c, 0x83, - 0x58, 0xb1, 0x11, 0x4b, 0x54, 0x24, 0x00, 0xf0, 0x21, 0xf8, 0x9c, 0x64, - 0x01, 0xeb, 0x82, 0x04, 0xa4, 0x68, 0xdc, 0x64, 0x01, 0x24, 0xa3, 0xf8, - 0x50, 0x40, 0x52, 0x1c, 0x02, 0x2a, 0xe0, 0xd3, 0x10, 0xbd, 0x00, 0x00, - 0x78, 0xb8, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x20, 0x29, 0x00, 0x20, - 0x60, 0x01, 0x00, 0x45, 0xa8, 0x01, 0x00, 0x45, 0x90, 0x01, 0x00, 0x45, - 0x78, 0x01, 0x00, 0x45, 0xa8, 0xef, 0x00, 0x20, 0x74, 0x27, 0x00, 0x20, - 0x94, 0xed, 0x00, 0x20, 0x04, 0xfb, 0x02, 0x33, 0x51, 0xf8, 0x22, 0x40, - 0x70, 0x47, 0x01, 0xb4, 0xbd, 0xf8, 0x02, 0x00, 0x5a, 0x28, 0x03, 0xdb, - 0xbd, 0xf8, 0x00, 0x00, 0x10, 0x28, 0x01, 0xdb, 0x00, 0x20, 0x00, 0xe0, - 0x01, 0x20, 0x01, 0xb0, 0x70, 0x47, 0xfe, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x00, 0x26, 0x55, 0xf8, 0x26, 0x00, 0x00, 0x90, 0xff, 0xf7, 0xe9, 0xff, - 0x07, 0x46, 0x34, 0xb1, 0x05, 0xeb, 0x86, 0x00, 0x80, 0x68, 0x00, 0x90, - 0xff, 0xf7, 0xe1, 0xff, 0x00, 0xe0, 0x01, 0x20, 0x17, 0xb1, 0x10, 0xb1, - 0x01, 0x20, 0x00, 0xe0, 0x00, 0x20, 0x01, 0xa9, 0xc0, 0xb2, 0x41, 0xf8, - 0x26, 0x00, 0x76, 0x1c, 0x02, 0x2e, 0xe4, 0xd3, 0x01, 0x98, 0x00, 0x28, - 0x1e, 0xbf, 0x02, 0x98, 0x00, 0x28, 0x01, 0x20, 0xc0, 0xb2, 0xfe, 0xbd, - 0x35, 0x49, 0x00, 0x20, 0x08, 0x80, 0x70, 0x47, 0x07, 0xf0, 0x9d, 0xbb, - 0x07, 0xf0, 0x9c, 0xbb, 0x07, 0xf0, 0x9b, 0xbb, 0x07, 0xf0, 0x9b, 0xbb, - 0x4f, 0xf0, 0x80, 0x73, 0x42, 0xf8, 0x04, 0x39, 0x10, 0x60, 0x10, 0x1f, - 0x2d, 0x4a, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, 0x12, 0x32, 0x40, 0xf8, - 0x04, 0x29, 0x4f, 0xf0, 0x03, 0x32, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, - 0x02, 0x32, 0x40, 0xf8, 0x04, 0x29, 0x4f, 0xf0, 0x01, 0x32, 0x40, 0xf8, - 0x04, 0x29, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x11, 0x31, 0x40, 0xf8, - 0x04, 0x19, 0x4f, 0xf0, 0x10, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, - 0x09, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x08, 0x31, 0x40, 0xf8, - 0x04, 0x19, 0x4f, 0xf0, 0x07, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, - 0x06, 0x31, 0x40, 0xf8, 0x04, 0x19, 0x4f, 0xf0, 0x05, 0x31, 0x40, 0xf8, - 0x04, 0x19, 0x4f, 0xf0, 0x04, 0x31, 0x01, 0x60, 0x70, 0x47, 0x07, 0xf0, - 0x5f, 0xbb, 0x07, 0xf0, 0x64, 0xbb, 0x80, 0xb5, 0x07, 0xf0, 0x62, 0xfb, - 0x0e, 0x48, 0x01, 0x88, 0x49, 0x1c, 0x01, 0x80, 0x89, 0xb2, 0x05, 0x29, - 0x05, 0xd3, 0x00, 0x21, 0x01, 0x80, 0xbd, 0xe8, 0x01, 0x40, 0xfb, 0xf7, - 0xbf, 0xb9, 0x01, 0xbd, 0x80, 0xb5, 0x00, 0xf0, 0x13, 0xf8, 0x08, 0x49, - 0x0a, 0x78, 0x52, 0x1c, 0x0a, 0x70, 0x80, 0xf3, 0x11, 0x88, 0xfa, 0xf7, - 0xcd, 0xf9, 0xbd, 0xe8, 0x01, 0x40, 0xfa, 0xf7, 0x67, 0xb9, 0x00, 0x00, - 0x9c, 0xf3, 0x00, 0x20, 0xbd, 0x2a, 0x00, 0x01, 0x20, 0xbd, 0x00, 0x20, - 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, - 0x80, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x1b, 0x48, 0xff, 0x21, 0x01, 0x70, - 0x00, 0x20, 0x80, 0xf3, 0x09, 0x88, 0x19, 0x48, 0x01, 0x21, 0x01, 0x70, - 0x18, 0x48, 0x19, 0x49, 0x01, 0x60, 0x62, 0xb6, 0xfe, 0xe7, 0x16, 0x48, - 0x16, 0x49, 0x01, 0x60, 0x70, 0x47, 0x14, 0x48, 0x14, 0x49, 0x01, 0x60, - 0x70, 0x47, 0x72, 0xb6, 0xef, 0xf3, 0x09, 0x80, 0x28, 0xb1, 0x20, 0x38, - 0x80, 0xe8, 0xf0, 0x0f, 0x10, 0x49, 0x09, 0x68, 0x08, 0x60, 0x00, 0xb5, - 0x0f, 0x48, 0x80, 0x47, 0x5d, 0xf8, 0x04, 0xeb, 0x0e, 0x48, 0x0f, 0x49, - 0x0a, 0x78, 0x02, 0x70, 0x0a, 0x48, 0x0e, 0x49, 0x0a, 0x68, 0x02, 0x60, - 0x10, 0x68, 0x90, 0xe8, 0xf0, 0x0f, 0x20, 0x30, 0x80, 0xf3, 0x09, 0x88, - 0x4e, 0xf0, 0x04, 0x0e, 0x62, 0xb6, 0x70, 0x47, 0x22, 0xed, 0x00, 0xe0, - 0x25, 0xbd, 0x00, 0x20, 0x04, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x10, - 0x40, 0xbd, 0x00, 0x20, 0x03, 0x7a, 0x00, 0x01, 0x22, 0xbd, 0x00, 0x20, - 0x23, 0xbd, 0x00, 0x20, 0x48, 0xbd, 0x00, 0x20, 0x00, 0x22, 0x07, 0xf0, - 0xeb, 0xba, 0x00, 0x00, 0x62, 0xf3, 0x0f, 0x22, 0x62, 0xf3, 0x1f, 0x42, - 0x40, 0x18, 0x10, 0xf0, 0x03, 0x03, 0x08, 0xd0, 0xc9, 0x1a, 0x1f, 0xd3, - 0xdb, 0x07, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2d, 0x28, 0xbf, 0x20, 0xf8, - 0x02, 0x2d, 0x13, 0x00, 0x30, 0xb4, 0x14, 0x46, 0x15, 0x46, 0x10, 0x39, - 0x28, 0xbf, 0x20, 0xe9, 0x3c, 0x00, 0xfa, 0xd8, 0x49, 0x07, 0x28, 0xbf, - 0x20, 0xe9, 0x0c, 0x00, 0x48, 0xbf, 0x40, 0xf8, 0x04, 0x2d, 0x89, 0x00, - 0x28, 0xbf, 0x20, 0xf8, 0x02, 0x2d, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2d, - 0x30, 0xbc, 0x70, 0x47, 0xc9, 0x18, 0x18, 0xbf, 0x00, 0xf8, 0x01, 0x2d, - 0xcb, 0x07, 0x28, 0xbf, 0x00, 0xf8, 0x01, 0x2d, 0x70, 0x47, 0x00, 0x00, - 0x58, 0xb5, 0x04, 0x46, 0x03, 0x2c, 0x16, 0xda, 0x04, 0xf0, 0x00, 0xff, - 0xbb, 0x4a, 0xbc, 0x4e, 0x12, 0x68, 0x09, 0x07, 0x41, 0xea, 0x10, 0x11, - 0x00, 0x07, 0x00, 0x23, 0xff, 0xf7, 0x78, 0xfc, 0x06, 0xeb, 0xc4, 0x02, - 0xc2, 0xe9, 0x00, 0x01, 0x20, 0x46, 0x04, 0xf0, 0xef, 0xfe, 0x06, 0xeb, - 0xc4, 0x02, 0xc2, 0xe9, 0x06, 0x01, 0x51, 0xbd, 0x7c, 0xb5, 0xb2, 0x49, - 0x0f, 0xf2, 0x28, 0x34, 0x09, 0x78, 0x01, 0xf0, 0x03, 0x02, 0x89, 0x08, - 0x01, 0xf0, 0x01, 0x03, 0x60, 0xcc, 0x69, 0x46, 0x01, 0x2a, 0x60, 0xc1, - 0x4f, 0xf4, 0x7a, 0x71, 0xa1, 0xfb, 0x00, 0x01, 0x04, 0xd1, 0x1b, 0xb1, - 0x49, 0x00, 0x41, 0xea, 0xd0, 0x71, 0x40, 0x00, 0x6c, 0x46, 0x04, 0xeb, - 0x83, 0x03, 0xd2, 0x5c, 0x02, 0xb0, 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x23, - 0xff, 0xf7, 0x4a, 0xbc, 0xa2, 0x49, 0x09, 0x78, 0x49, 0x07, 0x46, 0xbf, - 0x05, 0x21, 0xb0, 0xfb, 0xf1, 0xf0, 0x80, 0x08, 0x70, 0x47, 0x9f, 0x49, - 0x09, 0x78, 0xc9, 0x07, 0x9e, 0x49, 0x48, 0xbf, 0x40, 0x08, 0x09, 0x78, - 0xc1, 0xf3, 0x41, 0x01, 0xc8, 0x40, 0x70, 0x47, 0x10, 0xb5, 0x95, 0x48, - 0x95, 0x4c, 0x40, 0x68, 0xff, 0xf7, 0xc4, 0xff, 0x20, 0x63, 0xff, 0xf7, - 0xe3, 0xff, 0x60, 0x63, 0xff, 0xf7, 0xe9, 0xff, 0xa0, 0x63, 0x95, 0x49, - 0xb0, 0xfb, 0xf1, 0xf0, 0x40, 0x1c, 0xe0, 0x63, 0x4f, 0xf4, 0x7a, 0x71, - 0xa0, 0x6b, 0xb0, 0xfb, 0xf1, 0xf0, 0x20, 0x64, 0x10, 0xbd, 0x4b, 0x01, - 0x19, 0x18, 0x8f, 0x48, 0x20, 0x22, 0x18, 0x18, 0x02, 0xf0, 0x10, 0xb8, - 0xf8, 0xb5, 0x8d, 0x4d, 0x8d, 0x4a, 0x29, 0x68, 0x51, 0x18, 0x00, 0x20, - 0x8c, 0x4a, 0x91, 0x42, 0x0c, 0xd2, 0x69, 0x68, 0x8b, 0x4a, 0x51, 0x18, - 0x8b, 0x4a, 0x91, 0x42, 0x06, 0xd2, 0x29, 0x7a, 0x04, 0x29, 0x03, 0xda, - 0x69, 0x89, 0xb1, 0xf5, 0x00, 0x7f, 0x00, 0xd3, 0x01, 0x20, 0xae, 0x7a, - 0x86, 0x49, 0x87, 0x4a, 0x87, 0x4b, 0x88, 0x4c, 0x03, 0x27, 0x3e, 0x42, - 0x0c, 0xd0, 0x2e, 0x7c, 0x03, 0x2e, 0x07, 0xda, 0x6e, 0x69, 0xa6, 0x19, - 0x9e, 0x42, 0x03, 0xd2, 0x6e, 0x6a, 0x00, 0xf0, 0x69, 0xf8, 0x02, 0xe0, - 0x01, 0x26, 0x00, 0xe0, 0x00, 0x26, 0x30, 0x43, 0xae, 0x7a, 0x0c, 0x27, - 0x3e, 0x42, 0x09, 0xd0, 0xee, 0x6a, 0xa6, 0x19, 0x9e, 0x42, 0x03, 0xd2, - 0xae, 0x6b, 0x00, 0xf0, 0x59, 0xf8, 0x02, 0xe0, 0x01, 0x26, 0x00, 0xe0, - 0x00, 0x26, 0x30, 0x43, 0xae, 0x7a, 0x30, 0x27, 0x3e, 0x42, 0x0b, 0xd0, - 0x2e, 0x6c, 0xa6, 0x19, 0x9e, 0x42, 0x05, 0xd2, 0xee, 0x6c, 0x73, 0x4f, - 0xbe, 0x42, 0xb6, 0x41, 0xf6, 0x0f, 0x02, 0xe0, 0x01, 0x26, 0x00, 0xe0, - 0x00, 0x26, 0x30, 0x43, 0x6e, 0x89, 0x4f, 0xf4, 0xe0, 0x77, 0x3e, 0x42, - 0x0c, 0xd0, 0x6e, 0x6d, 0xa4, 0x19, 0x9c, 0x42, 0x06, 0xd2, 0x2b, 0x6e, - 0xd2, 0x18, 0x8a, 0x42, 0x89, 0x41, 0xc9, 0x43, 0xc9, 0x0f, 0x02, 0xe0, - 0x01, 0x21, 0x00, 0xe0, 0x00, 0x21, 0x51, 0xea, 0x00, 0x04, 0x06, 0xd0, - 0x04, 0x22, 0x00, 0x23, 0x00, 0x21, 0x04, 0x20, 0x00, 0xf0, 0xe4, 0xf9, - 0x22, 0xe0, 0x4f, 0x4e, 0x64, 0x22, 0x29, 0x46, 0x30, 0x46, 0x01, 0xf0, - 0x9d, 0xff, 0x70, 0x89, 0xc0, 0xf3, 0x81, 0x00, 0x10, 0xb1, 0x00, 0x21, - 0x00, 0xf0, 0x1e, 0xf8, 0x70, 0x89, 0xc0, 0xf3, 0x01, 0x10, 0x10, 0xb1, - 0x01, 0x21, 0x00, 0xf0, 0x17, 0xf8, 0x70, 0x89, 0xc0, 0xf3, 0x82, 0x10, - 0x10, 0xb1, 0x02, 0x21, 0x00, 0xf0, 0x10, 0xf8, 0xb0, 0x7a, 0x03, 0x21, - 0x08, 0x42, 0x1c, 0xbf, 0x05, 0xf1, 0x64, 0x00, 0xff, 0xf7, 0x69, 0xff, - 0x20, 0x46, 0xf2, 0xbd, 0x96, 0x19, 0x8e, 0x42, 0xb6, 0x41, 0xf6, 0x43, - 0xf6, 0x0f, 0x70, 0x47, 0x05, 0xf1, 0x64, 0x00, 0x5d, 0xe7, 0x80, 0xb5, - 0x00, 0xf0, 0x43, 0xf8, 0x0e, 0xd0, 0x00, 0xf0, 0x35, 0xf8, 0x00, 0x21, - 0x40, 0xf2, 0x09, 0x20, 0xfb, 0xf7, 0x42, 0xf9, 0x00, 0xf0, 0x33, 0xf8, - 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, 0x0a, 0x20, 0xfb, 0xf7, 0x44, 0xf9, - 0xf8, 0x20, 0x00, 0xf0, 0x35, 0xf8, 0xbd, 0xe8, 0x02, 0x40, 0x0e, 0x20, - 0x00, 0xf0, 0xa5, 0xb8, 0x80, 0xb5, 0x05, 0x21, 0x4f, 0xf4, 0xd8, 0x70, - 0xfb, 0xf7, 0x2c, 0xf9, 0x00, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xfb, 0xf7, - 0x27, 0xf9, 0x00, 0xf0, 0x1e, 0xf8, 0x10, 0xd0, 0xff, 0x21, 0x40, 0xf2, - 0x09, 0x20, 0xfb, 0xf7, 0x1f, 0xf9, 0x00, 0xf0, 0x0b, 0xf8, 0x00, 0xf0, - 0x0e, 0xf8, 0xbd, 0xe8, 0x08, 0x40, 0x03, 0x22, 0x03, 0x21, 0x40, 0xf2, - 0x0a, 0x20, 0xfb, 0xf7, 0x1d, 0xb9, 0x01, 0xbd, 0xff, 0x21, 0x40, 0xf6, - 0x89, 0x50, 0xfb, 0xf7, 0x0d, 0xb9, 0x03, 0x22, 0x03, 0x21, 0x40, 0xf6, - 0x8a, 0x50, 0xfb, 0xf7, 0x11, 0xb9, 0x15, 0x48, 0x80, 0x7a, 0x03, 0x21, - 0x08, 0x42, 0x70, 0x47, 0x01, 0x07, 0x0a, 0xd5, 0x11, 0x49, 0x49, 0x89, - 0x01, 0xf0, 0x03, 0x02, 0x89, 0x08, 0x89, 0x01, 0x41, 0xea, 0x02, 0x11, - 0x41, 0xf0, 0x0f, 0x01, 0x08, 0x40, 0x01, 0x46, 0x4f, 0xf4, 0xd8, 0x70, - 0xfb, 0xf7, 0xf0, 0xb8, 0x00, 0x28, 0x14, 0xbf, 0x02, 0x22, 0x00, 0x22, - 0x02, 0x21, 0x4f, 0xf4, 0xd8, 0x70, 0xfb, 0xf7, 0xf1, 0xb8, 0x38, 0xb9, - 0x16, 0x49, 0x4f, 0xf0, 0x00, 0x40, 0x08, 0x60, 0x00, 0xbf, 0x00, 0xbf, - 0x00, 0xbf, 0x00, 0xbf, 0x70, 0x47, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, - 0x00, 0xf2, 0x00, 0x20, 0x19, 0x01, 0x00, 0x46, 0x02, 0x01, 0x00, 0x46, - 0x18, 0x01, 0x00, 0x46, 0x08, 0x0d, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, - 0x00, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0xc0, 0x87, 0x82, 0xfe, - 0xc1, 0x57, 0x95, 0x11, 0x20, 0xf9, 0xa5, 0xff, 0x21, 0x79, 0x61, 0x00, - 0x81, 0x77, 0x8e, 0x06, 0x00, 0xd3, 0xce, 0xfe, 0x01, 0x70, 0x28, 0x12, - 0x00, 0xa0, 0x15, 0xff, 0x00, 0x2d, 0x31, 0x01, 0x04, 0xed, 0x00, 0xe0, - 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, 0x07, 0xf8, 0x01, 0x21, 0x81, 0x40, - 0x49, 0x1e, 0x21, 0x42, 0x18, 0xbf, 0x40, 0x1c, 0x10, 0xbd, 0xb0, 0xfa, - 0x80, 0xf0, 0xc0, 0xf1, 0x1f, 0x00, 0x70, 0x47, 0x04, 0x06, 0x08, 0x0c, - 0x05, 0x0f, 0x0a, 0x0f, 0x01, 0x21, 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, - 0x11, 0x4a, 0x04, 0xe0, 0x01, 0x21, 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, - 0x0f, 0x4a, 0x40, 0x09, 0x42, 0xf8, 0x20, 0x10, 0x70, 0x47, 0x01, 0x21, - 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, 0x0c, 0x4a, 0xf5, 0xe7, 0x01, 0x21, - 0x00, 0xf0, 0x1f, 0x02, 0x91, 0x40, 0x0a, 0x4a, 0xef, 0xe7, 0x09, 0x01, - 0x00, 0x28, 0x06, 0xd5, 0x08, 0x4a, 0x00, 0xf0, 0x0f, 0x00, 0x80, 0x18, - 0x00, 0xf8, 0x04, 0x1c, 0x70, 0x47, 0x06, 0x4a, 0x81, 0x54, 0x70, 0x47, - 0x80, 0xe2, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, - 0x00, 0xe2, 0x00, 0xe0, 0x18, 0xed, 0x00, 0xe0, 0x00, 0xe4, 0x00, 0xe0, - 0x42, 0x48, 0x00, 0xf1, 0x08, 0x01, 0x01, 0x60, 0x00, 0x21, 0xc1, 0x80, - 0x04, 0x21, 0x81, 0x80, 0x00, 0x21, 0x3f, 0x48, 0x81, 0x60, 0x6f, 0xf0, - 0x7f, 0x41, 0x01, 0x60, 0x15, 0x21, 0x81, 0x60, 0x70, 0x47, 0xef, 0xf3, - 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x37, 0x49, - 0x0a, 0x68, 0x10, 0x60, 0x01, 0xf5, 0x80, 0x50, 0x00, 0x1d, 0x82, 0x42, - 0x2c, 0xbf, 0x01, 0xf1, 0x08, 0x00, 0x10, 0x1d, 0x08, 0x60, 0xc8, 0x88, - 0xb0, 0xf5, 0x80, 0x6f, 0xbc, 0xbf, 0x40, 0x1c, 0xc8, 0x80, 0x70, 0x47, - 0x38, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xe3, 0xff, 0x05, 0x46, 0x00, 0xf0, - 0x11, 0xf8, 0x85, 0xf3, 0x11, 0x88, 0x31, 0xbd, 0x70, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x06, 0x46, 0x00, 0xf0, 0x06, 0xf8, - 0x28, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x86, 0xf3, 0x11, 0x88, 0x70, 0xbd, - 0x23, 0x48, 0x01, 0x68, 0x00, 0x22, 0x42, 0x60, 0x15, 0x22, 0x42, 0x60, - 0x44, 0xea, 0xc1, 0x10, 0xcb, 0xe7, 0x10, 0xb5, 0x1f, 0x4a, 0x04, 0x46, - 0xd2, 0xe9, 0x02, 0x01, 0x22, 0x46, 0xfb, 0xf7, 0x21, 0xfa, 0xc0, 0x07, - 0x04, 0xd5, 0x44, 0xf0, 0x00, 0x40, 0xbd, 0xe8, 0x10, 0x40, 0xcf, 0xe7, - 0x10, 0xbd, 0x38, 0xb5, 0x00, 0xf0, 0x1f, 0xf8, 0xc0, 0x07, 0x08, 0xd5, - 0x05, 0xf0, 0x01, 0x00, 0x44, 0xea, 0x80, 0x10, 0xbd, 0xe8, 0x32, 0x40, - 0x40, 0xf0, 0x00, 0x40, 0xc0, 0xe7, 0x31, 0xbd, 0x38, 0xb5, 0x00, 0xf0, - 0x10, 0xf8, 0xc0, 0x07, 0x0c, 0xd5, 0x68, 0x0e, 0x00, 0xf0, 0x40, 0x00, - 0x04, 0xf0, 0x3f, 0x02, 0x69, 0x00, 0x10, 0x43, 0xbd, 0xe8, 0x34, 0x40, - 0x49, 0x08, 0x40, 0xf0, 0x00, 0x40, 0xb7, 0xe7, 0x31, 0xbd, 0x07, 0x4a, - 0x04, 0x46, 0x0d, 0x46, 0xd2, 0xe9, 0x02, 0x01, 0x22, 0x46, 0xfb, 0xf7, - 0xef, 0xb9, 0x00, 0x00, 0xb8, 0x82, 0x00, 0x20, 0x00, 0x00, 0x30, 0x59, - 0x04, 0x00, 0x30, 0x59, 0x88, 0x02, 0x00, 0x20, 0x10, 0xb5, 0x04, 0x46, - 0x00, 0xf0, 0x07, 0xf8, 0x20, 0x46, 0x07, 0xf0, 0x5b, 0xf8, 0xbd, 0xe8, - 0x10, 0x40, 0x07, 0xf0, 0x4b, 0xb8, 0x10, 0xb5, 0x30, 0x48, 0x00, 0x21, - 0x00, 0x22, 0x00, 0x23, 0x00, 0x24, 0x1e, 0xc0, 0x10, 0xbd, 0x10, 0xb5, - 0x00, 0xf0, 0x05, 0xf8, 0x23, 0xea, 0x00, 0x00, 0x42, 0xf8, 0x21, 0x00, - 0x10, 0xbd, 0x29, 0x4a, 0x01, 0x09, 0x52, 0xf8, 0x21, 0x30, 0x01, 0x24, - 0x40, 0x00, 0x04, 0xfa, 0x00, 0xf0, 0x70, 0x47, 0x30, 0xb5, 0x02, 0x09, - 0x23, 0x4b, 0x53, 0xf8, 0x22, 0x40, 0x40, 0x00, 0x40, 0x1c, 0x07, 0x25, - 0x85, 0x40, 0xac, 0x43, 0x43, 0xf8, 0x22, 0x40, 0x01, 0xf0, 0x07, 0x01, - 0x53, 0xf8, 0x22, 0x40, 0x01, 0xfa, 0x00, 0xf0, 0x20, 0x43, 0x43, 0xf8, - 0x22, 0x00, 0x30, 0xbd, 0x19, 0x4a, 0x03, 0x09, 0x52, 0xf8, 0x23, 0x20, - 0x43, 0x00, 0x5b, 0x1c, 0xda, 0x40, 0x02, 0xf0, 0x07, 0x02, 0x8a, 0x42, - 0x38, 0xbf, 0xff, 0xf7, 0xdd, 0xbf, 0x70, 0x47, 0xf0, 0xb5, 0xef, 0xf3, - 0x10, 0x84, 0x72, 0xb6, 0x11, 0x4d, 0xd5, 0xe9, 0x00, 0x67, 0x26, 0xea, - 0x02, 0x02, 0x27, 0xea, 0x03, 0x03, 0x10, 0x43, 0x19, 0x43, 0xc5, 0xe9, - 0x00, 0x01, 0x84, 0xf3, 0x10, 0x88, 0xf0, 0xbd, 0xd0, 0xb5, 0x04, 0x46, - 0xef, 0xf3, 0x10, 0x80, 0x72, 0xb6, 0x08, 0x49, 0xd1, 0xe9, 0x00, 0x67, - 0x80, 0xf3, 0x10, 0x88, 0x26, 0xea, 0x02, 0x00, 0x27, 0xea, 0x03, 0x01, - 0x22, 0x46, 0xbd, 0xe8, 0xd0, 0x40, 0xfb, 0xf7, 0x79, 0xb9, 0x00, 0x00, - 0x08, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x49, 0x3c, 0x48, 0x01, 0x74, - 0xc9, 0xb2, 0x03, 0x29, 0x9c, 0xbf, 0x00, 0x20, 0xff, 0xf7, 0x7f, 0xbe, - 0x70, 0x47, 0x30, 0xb5, 0x37, 0x4d, 0x85, 0xb0, 0x04, 0x46, 0x55, 0xf8, - 0x24, 0x10, 0xa1, 0xb9, 0x03, 0xa9, 0x02, 0x91, 0x00, 0x90, 0x00, 0x21, - 0x33, 0x48, 0x34, 0x4b, 0x01, 0x91, 0x01, 0x22, 0x50, 0xf8, 0x24, 0x00, - 0xfa, 0xf7, 0xe8, 0xfc, 0x45, 0xf8, 0x24, 0x00, 0x9d, 0xf8, 0x0c, 0x10, - 0x48, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0xff, 0xf7, 0x62, 0xfe, 0x05, 0xb0, - 0x30, 0xbd, 0x38, 0xb5, 0x28, 0x4d, 0x04, 0x46, 0x55, 0xf8, 0x24, 0x00, - 0x20, 0xb1, 0x69, 0x46, 0xfa, 0xf7, 0x12, 0xfd, 0x00, 0xf0, 0x1b, 0xf8, - 0x00, 0x20, 0x45, 0xf8, 0x24, 0x00, 0x31, 0xbd, 0x38, 0xb5, 0x00, 0xf0, - 0x3b, 0xf8, 0x11, 0xd1, 0x1f, 0x4d, 0x55, 0xf8, 0x24, 0x00, 0x68, 0xb1, - 0x69, 0x46, 0xfa, 0xf7, 0x5d, 0xfd, 0x01, 0x28, 0x08, 0xd1, 0x00, 0xf0, - 0x08, 0xf8, 0x55, 0xf8, 0x24, 0x00, 0x69, 0x46, 0xfa, 0xf7, 0x74, 0xfd, - 0x00, 0xf0, 0x01, 0xf8, 0x31, 0xbd, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, - 0x80, 0x41, 0xc0, 0x0f, 0xff, 0xf7, 0x33, 0xbe, 0x38, 0xb5, 0x00, 0xf0, - 0x1d, 0xf8, 0x1a, 0xd1, 0x10, 0x4d, 0x55, 0xf8, 0x24, 0x00, 0xb0, 0xb1, - 0x69, 0x46, 0xfa, 0xf7, 0x3f, 0xfd, 0x03, 0x28, 0x11, 0xd1, 0xff, 0xf7, - 0xea, 0xff, 0x55, 0xf8, 0x24, 0x00, 0x69, 0x46, 0xfa, 0xf7, 0x00, 0xfd, - 0xff, 0xf7, 0xe3, 0xff, 0x55, 0xf8, 0x24, 0x00, 0x6b, 0x46, 0x00, 0x22, - 0x00, 0x21, 0xfa, 0xf7, 0x79, 0xfd, 0xff, 0xf7, 0xda, 0xff, 0x31, 0xbd, - 0x04, 0x46, 0x03, 0x48, 0x00, 0x7c, 0x01, 0x28, 0x70, 0x47, 0x00, 0x00, - 0x08, 0x1f, 0x00, 0x20, 0x1c, 0x1f, 0x00, 0x20, 0x45, 0x81, 0x00, 0x01, - 0x00, 0x20, 0x00, 0xe0, 0x01, 0x20, 0x38, 0xb5, 0xff, 0xf7, 0xee, 0xff, - 0x0b, 0xd1, 0x00, 0x25, 0x00, 0x2c, 0xe8, 0xb2, 0x02, 0xd1, 0xff, 0xf7, - 0x7c, 0xff, 0x01, 0xe0, 0xff, 0xf7, 0x97, 0xff, 0x6d, 0x1c, 0x04, 0x2d, - 0xf4, 0xd3, 0x31, 0xbd, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, - 0x11, 0x88, 0x70, 0x47, 0x30, 0xb5, 0x00, 0xf0, 0x11, 0xf8, 0x23, 0x43, - 0x13, 0x60, 0x01, 0xeb, 0x40, 0x00, 0x01, 0x22, 0x42, 0x70, 0x30, 0xbd, - 0x30, 0xb5, 0x00, 0xf0, 0x07, 0xf8, 0xa3, 0x43, 0x13, 0x60, 0x01, 0xeb, - 0x40, 0x00, 0x00, 0x22, 0x42, 0x70, 0x30, 0xbd, 0xdf, 0xf8, 0xb0, 0x2c, - 0xdf, 0xf8, 0xd4, 0x1d, 0x13, 0x68, 0x11, 0xf9, 0x10, 0x50, 0x01, 0x24, - 0xac, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0xa0, 0x0c, 0xc0, 0x6c, 0x70, 0x47, - 0xdf, 0xf8, 0x9c, 0x1c, 0xdf, 0xf8, 0x94, 0x0c, 0x89, 0x6b, 0xc0, 0x6c, - 0xdf, 0xf8, 0x94, 0x2c, 0xb1, 0xfb, 0xf2, 0xf1, 0x48, 0x43, 0xdf, 0xf8, - 0x68, 0x1d, 0x48, 0x60, 0x70, 0x47, 0x80, 0xb5, 0xdf, 0xf8, 0x3c, 0x0d, - 0x00, 0x21, 0x41, 0x71, 0x84, 0x30, 0xfb, 0xf7, 0xb1, 0xf9, 0x06, 0xf0, - 0xea, 0xf9, 0xbd, 0xe8, 0x01, 0x40, 0x06, 0xf0, 0x1a, 0xb9, 0xdf, 0xf8, - 0xc8, 0x1d, 0x02, 0x20, 0x08, 0x60, 0x70, 0x47, 0xdf, 0xf8, 0x18, 0x0d, - 0x41, 0x79, 0xd0, 0xf8, 0x80, 0x00, 0x00, 0x29, 0x18, 0xbf, 0x40, 0xf0, - 0x00, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0x04, 0x0d, 0x01, 0x79, 0x00, 0x29, - 0x0e, 0xbf, 0x00, 0x20, 0xd0, 0xf8, 0x80, 0x00, 0xc0, 0xf3, 0x02, 0x10, - 0x70, 0x47, 0x10, 0xb5, 0xdf, 0xf8, 0x28, 0x4c, 0xa1, 0x7c, 0x4f, 0xf4, - 0x17, 0x60, 0xfa, 0xf7, 0x73, 0xfe, 0xe1, 0x7c, 0xbd, 0xe8, 0x10, 0x40, - 0x40, 0xf6, 0x71, 0x10, 0xfa, 0xf7, 0x6c, 0xbe, 0x2d, 0xe9, 0xf0, 0x47, - 0x06, 0x21, 0x31, 0x20, 0xff, 0xf7, 0xdf, 0xfd, 0x31, 0x20, 0xff, 0xf7, - 0xc1, 0xfd, 0x31, 0x20, 0xff, 0xf7, 0xc4, 0xfd, 0xff, 0xf7, 0xac, 0xff, - 0xdf, 0xf8, 0xb4, 0x4c, 0xdf, 0xf8, 0xd0, 0x5c, 0xdf, 0xf8, 0xd0, 0x1c, - 0xdf, 0xf8, 0xe4, 0x9b, 0x00, 0x20, 0x60, 0x71, 0x68, 0x68, 0x08, 0x60, - 0x06, 0x21, 0x10, 0x20, 0xff, 0xf7, 0xc7, 0xfd, 0x02, 0x21, 0x0c, 0x20, - 0xff, 0xf7, 0xc3, 0xfd, 0x02, 0x21, 0x0a, 0x20, 0xff, 0xf7, 0xbf, 0xfd, - 0x02, 0x21, 0x1d, 0x20, 0xff, 0xf7, 0xbb, 0xfd, 0x02, 0x21, 0x0d, 0x20, - 0xff, 0xf7, 0xb7, 0xfd, 0x02, 0x21, 0x0b, 0x20, 0xff, 0xf7, 0xb3, 0xfd, - 0x02, 0x21, 0x1e, 0x20, 0xff, 0xf7, 0xaf, 0xfd, 0x02, 0x21, 0x1f, 0x20, - 0xff, 0xf7, 0xab, 0xfd, 0xdf, 0xf8, 0xc4, 0x0d, 0x40, 0x89, 0xc0, 0xf3, - 0x81, 0x01, 0x89, 0xf8, 0x04, 0x10, 0x01, 0x23, 0x00, 0xf0, 0x03, 0x01, - 0x89, 0xf8, 0x05, 0x10, 0x00, 0x21, 0x03, 0xfa, 0x01, 0xf8, 0x08, 0xea, - 0x00, 0x06, 0x0f, 0x1d, 0x8a, 0x1c, 0x16, 0xf0, 0x03, 0x0f, 0x03, 0xfa, - 0x07, 0xf7, 0x03, 0xfa, 0x02, 0xf2, 0x03, 0xfa, 0x01, 0xfe, 0x0d, 0xd1, - 0x2e, 0x78, 0x42, 0xea, 0x0e, 0x0a, 0x47, 0xea, 0x0a, 0x0a, 0x4a, 0xea, - 0x06, 0x06, 0x2e, 0x70, 0x4e, 0xf0, 0x04, 0x0a, 0x6e, 0x78, 0x4a, 0xea, - 0x06, 0x06, 0x6e, 0x70, 0x08, 0xea, 0x90, 0x0a, 0x8e, 0x1d, 0x1a, 0xf0, - 0x03, 0x0f, 0x03, 0xfa, 0x06, 0xf6, 0x0b, 0xd1, 0x42, 0xea, 0x0e, 0x02, - 0x94, 0xf8, 0x06, 0xa0, 0x17, 0x43, 0x37, 0x43, 0x47, 0xea, 0x0a, 0x07, - 0xa7, 0x71, 0x4a, 0x19, 0x7f, 0x27, 0x97, 0x70, 0x08, 0xea, 0x10, 0x17, - 0x17, 0xf0, 0x03, 0x0f, 0x02, 0xd1, 0xe7, 0x79, 0x37, 0x43, 0xe7, 0x71, - 0x49, 0x1c, 0x02, 0x29, 0xc3, 0xdb, 0xc0, 0xf3, 0x82, 0x10, 0x20, 0xb9, - 0xe0, 0x79, 0x40, 0xf0, 0x30, 0x00, 0xe0, 0x71, 0x15, 0xe0, 0x80, 0x22, - 0x80, 0x21, 0x4f, 0xf4, 0x02, 0x60, 0xfa, 0xf7, 0xe5, 0xfd, 0xc0, 0x22, - 0xc0, 0x21, 0x40, 0xf6, 0x1f, 0x00, 0xfa, 0xf7, 0xdf, 0xfd, 0x3f, 0x21, - 0x40, 0xf6, 0x8c, 0x50, 0xfa, 0xf7, 0xd0, 0xfd, 0x03, 0x21, 0x4f, 0xf4, - 0x03, 0x70, 0xfa, 0xf7, 0xcb, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, - 0x14, 0x00, 0xfa, 0xf7, 0xcf, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, - 0x12, 0x00, 0xfa, 0xf7, 0xc9, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf6, - 0x13, 0x00, 0xfa, 0xf7, 0xc3, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf2, - 0x42, 0x50, 0xfa, 0xf7, 0xbd, 0xfd, 0xc0, 0x22, 0xc0, 0x21, 0x40, 0xf2, - 0x43, 0x50, 0xfa, 0xf7, 0xb7, 0xfd, 0x00, 0x22, 0xc0, 0x21, 0x40, 0xf2, - 0xe4, 0x60, 0xfa, 0xf7, 0xb1, 0xfd, 0x99, 0xf8, 0x04, 0x00, 0x99, 0xf8, - 0x05, 0x10, 0x40, 0xea, 0x81, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0x06, 0xf0, - 0x2b, 0xf8, 0xbd, 0xe8, 0xf0, 0x47, 0x05, 0xf0, 0x6b, 0xbe, 0x80, 0xb5, - 0x4f, 0xf0, 0x92, 0x41, 0x00, 0x20, 0x08, 0x60, 0x04, 0x21, 0x01, 0x20, - 0xff, 0xf7, 0x09, 0xfd, 0x01, 0x20, 0xff, 0xf7, 0xf1, 0xfc, 0x00, 0x20, - 0x02, 0xbd, 0xf8, 0xb5, 0x0a, 0x20, 0xff, 0xf7, 0xe5, 0xfc, 0x1d, 0x20, - 0xff, 0xf7, 0xe2, 0xfc, 0x0c, 0x20, 0xff, 0xf7, 0xdf, 0xfc, 0xdf, 0xf8, - 0x78, 0x3c, 0xdf, 0xf8, 0x78, 0x5c, 0xdf, 0xf8, 0x30, 0x2a, 0xdf, 0xf8, - 0xf0, 0x4a, 0x00, 0x20, 0x98, 0x60, 0x18, 0x60, 0x28, 0x60, 0x4f, 0xf4, - 0x00, 0x21, 0x90, 0x78, 0x70, 0xb9, 0x00, 0xf0, 0xfd, 0xf9, 0x10, 0x79, - 0xc2, 0x07, 0x4c, 0xbf, 0x80, 0x22, 0x00, 0x22, 0xa2, 0x65, 0x80, 0x07, - 0x58, 0xbf, 0x00, 0x21, 0x21, 0x66, 0x03, 0x20, 0x20, 0x72, 0x45, 0xe0, - 0x03, 0xf1, 0x40, 0x00, 0x60, 0x62, 0x03, 0xf1, 0x3c, 0x00, 0xa0, 0x62, - 0x05, 0xf1, 0x40, 0x00, 0x20, 0x63, 0x05, 0xf1, 0x3c, 0x00, 0x60, 0x63, - 0x80, 0x20, 0xd8, 0x63, 0xe9, 0x63, 0x98, 0x6c, 0x40, 0xf0, 0x80, 0x00, - 0x98, 0x64, 0xd8, 0x6c, 0x40, 0xf0, 0x80, 0x00, 0xd8, 0x64, 0xa8, 0x6c, - 0x40, 0xf4, 0x00, 0x20, 0xa8, 0x64, 0xe8, 0x6c, 0x40, 0xf4, 0x00, 0x20, - 0xe8, 0x64, 0xdf, 0xf8, 0xe8, 0x0b, 0x46, 0x89, 0xc6, 0xf3, 0x81, 0x07, - 0x03, 0x2f, 0x04, 0xbf, 0x12, 0x78, 0x00, 0x2a, 0x40, 0xf2, 0x05, 0x10, - 0x05, 0xd1, 0x80, 0x21, 0x99, 0x60, 0x08, 0x22, 0x04, 0x21, 0x21, 0x72, - 0x11, 0xe0, 0x00, 0x22, 0x22, 0x72, 0xc6, 0xf3, 0x80, 0x02, 0x1a, 0xb1, - 0x80, 0x22, 0x1a, 0x60, 0x01, 0x22, 0x22, 0x72, 0xb2, 0x08, 0x92, 0x07, - 0x04, 0xd5, 0x29, 0x60, 0x21, 0x7a, 0x41, 0xf0, 0x02, 0x01, 0x21, 0x72, - 0x00, 0x22, 0x08, 0x21, 0xfa, 0xf7, 0x26, 0xfd, 0x00, 0xf0, 0xc3, 0xf9, - 0x05, 0xf0, 0xeb, 0xff, 0xd4, 0xf8, 0x80, 0x00, 0x80, 0x08, 0x80, 0x00, - 0xc4, 0xf8, 0x80, 0x00, 0x0a, 0x20, 0xff, 0xf7, 0x82, 0xfc, 0x1d, 0x20, - 0xff, 0xf7, 0x7f, 0xfc, 0xbd, 0xe8, 0xf2, 0x40, 0x0c, 0x20, 0xff, 0xf7, - 0x7a, 0xbc, 0xf8, 0xb5, 0x0d, 0x20, 0xff, 0xf7, 0x61, 0xfc, 0x0b, 0x20, - 0xff, 0xf7, 0x5e, 0xfc, 0x1e, 0x20, 0xff, 0xf7, 0x5b, 0xfc, 0xdf, 0xf8, - 0xf8, 0x5b, 0xdf, 0xf8, 0xf8, 0x6b, 0xdf, 0xf8, 0x28, 0x39, 0xdf, 0xf8, - 0xdc, 0x1c, 0xdf, 0xf8, 0xe4, 0x49, 0x00, 0x20, 0xa8, 0x60, 0x28, 0x60, - 0x30, 0x60, 0x4f, 0xf4, 0x80, 0x12, 0x98, 0x78, 0x70, 0xb9, 0x00, 0xf0, - 0x6a, 0xf9, 0x58, 0x79, 0xc3, 0x07, 0x4c, 0xbf, 0x40, 0x23, 0x00, 0x23, - 0xa3, 0x64, 0x80, 0x07, 0x58, 0xbf, 0x00, 0x22, 0x22, 0x65, 0x03, 0x20, - 0x08, 0x70, 0x43, 0xe0, 0x05, 0xf1, 0x3c, 0x00, 0xe0, 0x60, 0x05, 0xf1, - 0x38, 0x00, 0x20, 0x61, 0x06, 0xf1, 0x3c, 0x00, 0xa0, 0x61, 0x06, 0xf1, - 0x38, 0x00, 0xe0, 0x61, 0x40, 0x20, 0xa8, 0x63, 0xb2, 0x63, 0x68, 0x6c, - 0x40, 0xf0, 0x40, 0x00, 0x68, 0x64, 0xa8, 0x6c, 0x40, 0xf0, 0x40, 0x00, - 0xa8, 0x64, 0x70, 0x6c, 0x40, 0xf4, 0x80, 0x10, 0x70, 0x64, 0xb0, 0x6c, - 0x40, 0xf4, 0x80, 0x10, 0xb0, 0x64, 0xdf, 0xf8, 0xdc, 0x0a, 0x47, 0x89, - 0x07, 0xf0, 0x03, 0x0c, 0xbc, 0xf1, 0x03, 0x0f, 0x04, 0xbf, 0x5b, 0x78, - 0x00, 0x2b, 0x40, 0xf2, 0x05, 0x10, 0x04, 0xd1, 0x40, 0x22, 0xaa, 0x60, - 0x04, 0x22, 0x0a, 0x70, 0x0f, 0xe0, 0x00, 0x23, 0x0b, 0x70, 0xfb, 0x07, - 0x03, 0xd5, 0x40, 0x23, 0x2b, 0x60, 0x01, 0x23, 0x0b, 0x70, 0xbb, 0x07, - 0x04, 0xd5, 0x32, 0x60, 0x0a, 0x78, 0x42, 0xf0, 0x02, 0x02, 0x0a, 0x70, - 0x00, 0x22, 0x04, 0x21, 0xfa, 0xf7, 0xa2, 0xfc, 0x00, 0xf0, 0x6f, 0xf9, - 0xff, 0xf7, 0x19, 0xfe, 0xd4, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x0c, 0x00, - 0xc4, 0xf8, 0x80, 0x00, 0x0b, 0x20, 0xff, 0xf7, 0xfe, 0xfb, 0x1e, 0x20, - 0xff, 0xf7, 0xfb, 0xfb, 0xbd, 0xe8, 0xf2, 0x40, 0x0d, 0x20, 0xff, 0xf7, - 0xf6, 0xbb, 0x2d, 0xe9, 0xf8, 0x43, 0xdf, 0xf8, 0x38, 0x58, 0xdf, 0xf8, - 0xf0, 0x6b, 0xe8, 0x78, 0xdf, 0xf8, 0xf0, 0x48, 0x98, 0xb9, 0x00, 0xf0, - 0x12, 0xf9, 0x30, 0x60, 0x10, 0x20, 0x60, 0x64, 0xa9, 0x79, 0x48, 0x08, - 0x40, 0x00, 0x01, 0xf0, 0x01, 0x02, 0x89, 0x08, 0x00, 0xf0, 0x02, 0x00, - 0x89, 0x00, 0x10, 0x43, 0x01, 0xf0, 0x04, 0x01, 0x08, 0x43, 0xa0, 0x66, - 0x37, 0xe0, 0x00, 0x20, 0x01, 0xf0, 0x88, 0xfb, 0x80, 0x46, 0x01, 0x20, - 0x01, 0xf0, 0x84, 0xfb, 0x07, 0x46, 0x02, 0x20, 0x01, 0xf0, 0x80, 0xfb, - 0x81, 0x46, 0x03, 0x20, 0x01, 0xf0, 0x7c, 0xfb, 0xa8, 0xf1, 0x04, 0x01, - 0x04, 0x2f, 0x21, 0x67, 0x0a, 0xd2, 0x07, 0xf1, 0x0a, 0x02, 0x62, 0x67, - 0x0a, 0x30, 0xe0, 0x67, 0x09, 0xf1, 0x0a, 0x02, 0xa2, 0x67, 0xdf, 0xf8, - 0x88, 0x0b, 0x0c, 0xe0, 0x10, 0x2f, 0x09, 0xd2, 0x3a, 0x1f, 0x62, 0x67, - 0x00, 0x1f, 0xe0, 0x67, 0xa9, 0xf1, 0x04, 0x02, 0xa2, 0x67, 0x06, 0xf1, - 0x38, 0x00, 0x00, 0xe0, 0x00, 0x20, 0xe0, 0x63, 0x01, 0x20, 0x88, 0x40, - 0x06, 0xf1, 0x34, 0x01, 0x21, 0x64, 0x60, 0x64, 0x70, 0x63, 0x30, 0x60, - 0x31, 0x6c, 0x08, 0x43, 0x30, 0x64, 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, - 0x05, 0x10, 0xfa, 0xf7, 0x31, 0xfc, 0x00, 0x21, 0x4f, 0xf4, 0x82, 0x70, - 0xfa, 0xf7, 0x22, 0xfc, 0xdf, 0xf8, 0xb4, 0x0b, 0x00, 0x78, 0x60, 0x70, - 0x29, 0x7e, 0xc9, 0x07, 0x48, 0xbf, 0x40, 0xf0, 0xc0, 0x00, 0x20, 0x70, - 0x00, 0xf0, 0x10, 0xf9, 0x05, 0xf0, 0x58, 0xfd, 0xd4, 0xf8, 0x80, 0x00, - 0xdf, 0xf8, 0x98, 0x1b, 0x20, 0xf0, 0x70, 0x00, 0xc4, 0xf8, 0x80, 0x00, - 0x00, 0x20, 0x08, 0x70, 0x1f, 0x20, 0xbd, 0xe8, 0xf2, 0x43, 0xff, 0xf7, - 0x78, 0xbb, 0xdf, 0xf8, 0x84, 0x0b, 0x01, 0x79, 0x01, 0x29, 0x0c, 0xbf, - 0x02, 0x21, 0x00, 0x21, 0x01, 0x71, 0x00, 0x20, 0x70, 0x47, 0x10, 0xb5, - 0xdf, 0xf8, 0xec, 0x47, 0x20, 0x79, 0x02, 0x28, 0x6d, 0xd1, 0xdf, 0xf8, - 0x68, 0x0b, 0x01, 0x68, 0x21, 0xf0, 0xc0, 0x01, 0x01, 0x60, 0x41, 0x68, - 0x21, 0xf0, 0xc0, 0x01, 0x41, 0x60, 0xdf, 0xf8, 0x58, 0x0b, 0x01, 0x68, - 0x21, 0xf4, 0xc0, 0x11, 0x01, 0x60, 0x41, 0x68, 0x21, 0xf4, 0xc0, 0x11, - 0x41, 0x60, 0xdf, 0xf8, 0xf8, 0x16, 0xc9, 0x78, 0x01, 0x29, 0x05, 0xd1, - 0x01, 0x68, 0x23, 0x6f, 0x01, 0x22, 0x9a, 0x40, 0x91, 0x43, 0x01, 0x60, - 0x05, 0xf0, 0x07, 0xff, 0x00, 0xf0, 0x60, 0xf8, 0x00, 0x20, 0xa0, 0x65, - 0x20, 0x66, 0x0c, 0x20, 0xff, 0xf7, 0x3f, 0xfb, 0x0a, 0x20, 0xff, 0xf7, - 0x3c, 0xfb, 0x1d, 0x20, 0xff, 0xf7, 0x39, 0xfb, 0x00, 0xf0, 0x45, 0xf8, - 0x00, 0x20, 0xa0, 0x64, 0x20, 0x65, 0x0d, 0x20, 0xff, 0xf7, 0x31, 0xfb, - 0x0b, 0x20, 0xff, 0xf7, 0x2e, 0xfb, 0x1e, 0x20, 0xff, 0xf7, 0x2b, 0xfb, - 0x00, 0xf0, 0x51, 0xf8, 0xa0, 0x66, 0x1f, 0x20, 0xff, 0xf7, 0x25, 0xfb, - 0xdf, 0xf8, 0xd8, 0x1a, 0x01, 0x20, 0x08, 0x70, 0x10, 0x20, 0xff, 0xf7, - 0x18, 0xfb, 0x0a, 0x20, 0xff, 0xf7, 0x15, 0xfb, 0x1d, 0x20, 0xff, 0xf7, - 0x12, 0xfb, 0x0c, 0x20, 0xff, 0xf7, 0x0f, 0xfb, 0x0b, 0x20, 0xff, 0xf7, - 0x0c, 0xfb, 0x1e, 0x20, 0xff, 0xf7, 0x09, 0xfb, 0x0d, 0x20, 0xff, 0xf7, - 0x06, 0xfb, 0x1f, 0x20, 0xff, 0xf7, 0x03, 0xfb, 0x06, 0xf0, 0x7b, 0xfc, - 0x00, 0x20, 0xff, 0xf7, 0xa1, 0xfa, 0xff, 0xf7, 0x5d, 0xfa, 0x07, 0x22, - 0x04, 0xf1, 0x8c, 0x01, 0x0f, 0xf6, 0xfc, 0x20, 0xfa, 0xf7, 0xa6, 0xfb, - 0x04, 0xe0, 0x00, 0x20, 0xff, 0xf7, 0x94, 0xfa, 0xff, 0xf7, 0x50, 0xfa, - 0x00, 0x20, 0x20, 0x71, 0x10, 0xbd, 0x04, 0xf1, 0x48, 0x00, 0xe0, 0x60, - 0x04, 0xf1, 0x4c, 0x00, 0x20, 0x61, 0x04, 0xf1, 0x50, 0x00, 0xa0, 0x61, - 0x04, 0xf1, 0x54, 0x00, 0xe0, 0x61, 0x70, 0x47, 0x04, 0xf1, 0x58, 0x00, - 0x60, 0x62, 0x04, 0xf1, 0x5c, 0x00, 0xa0, 0x62, 0x04, 0xf1, 0x60, 0x00, - 0x20, 0x63, 0x04, 0xf1, 0x64, 0x00, 0x60, 0x63, 0x70, 0x47, 0x04, 0xf1, - 0x68, 0x00, 0xe0, 0x63, 0x04, 0xf1, 0x6c, 0x00, 0x20, 0x64, 0x00, 0x20, - 0x60, 0x67, 0x01, 0x20, 0xa0, 0x67, 0x02, 0x20, 0xe0, 0x67, 0x00, 0x20, - 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0xe0, 0x45, 0xdf, 0xf8, 0xa0, 0x16, - 0x20, 0x7b, 0x89, 0x79, 0xdf, 0xf8, 0xb8, 0x56, 0x20, 0xea, 0x01, 0x01, - 0x40, 0xf6, 0x84, 0x50, 0xfa, 0xf7, 0x48, 0xfb, 0x60, 0x7b, 0xa9, 0x78, - 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x85, 0x50, 0xfa, 0xf7, 0x40, 0xfb, - 0xa0, 0x7b, 0xe9, 0x78, 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x86, 0x50, - 0xfa, 0xf7, 0x38, 0xfb, 0x00, 0x21, 0x4f, 0xf4, 0x01, 0x70, 0xfa, 0xf7, - 0x33, 0xfb, 0x00, 0x21, 0x40, 0xf2, 0x05, 0x20, 0xfa, 0xf7, 0x2e, 0xfb, - 0xbd, 0xe8, 0x34, 0x40, 0x00, 0x21, 0x40, 0xf2, 0x06, 0x20, 0xfa, 0xf7, - 0x27, 0xbb, 0x38, 0xb5, 0xdf, 0xf8, 0x64, 0x46, 0xdf, 0xf8, 0xcc, 0x59, - 0x21, 0x78, 0x28, 0x7c, 0x20, 0xea, 0x01, 0x01, 0x40, 0xf6, 0x89, 0x50, - 0xfa, 0xf7, 0x1a, 0xfb, 0x68, 0x7c, 0x61, 0x78, 0x20, 0xea, 0x01, 0x01, - 0x40, 0xf6, 0x8a, 0x50, 0xfa, 0xf7, 0x12, 0xfb, 0x00, 0x21, 0x40, 0xf2, - 0x09, 0x20, 0xfa, 0xf7, 0x0d, 0xfb, 0xbd, 0xe8, 0x34, 0x40, 0x00, 0x21, - 0x40, 0xf2, 0x0a, 0x20, 0xfa, 0xf7, 0x06, 0xbb, 0x80, 0xb5, 0xdf, 0xf8, - 0x04, 0x16, 0xdf, 0xf8, 0x3c, 0x05, 0xc9, 0x79, 0x40, 0x69, 0xc9, 0x43, - 0x01, 0x40, 0xc9, 0xb2, 0x40, 0xf6, 0x87, 0x50, 0xfa, 0xf7, 0xf8, 0xfa, - 0xbd, 0xe8, 0x04, 0x40, 0x00, 0x21, 0x40, 0xf2, 0x07, 0x20, 0xfa, 0xf7, - 0xf1, 0xba, 0xf8, 0xb5, 0x00, 0x24, 0x0f, 0xf6, 0x18, 0x25, 0x0f, 0xf6, - 0x10, 0x26, 0xa0, 0x5d, 0xfb, 0xf7, 0x36, 0xfe, 0x30, 0xb1, 0x20, 0x46, - 0x01, 0xf0, 0x6d, 0xfd, 0x10, 0xb9, 0x20, 0x46, 0x05, 0xf0, 0xb3, 0xf9, - 0x60, 0x5d, 0xfb, 0xf7, 0x2b, 0xfe, 0x10, 0xb1, 0x20, 0x46, 0xfd, 0xf7, - 0x62, 0xfe, 0x64, 0x1c, 0x02, 0x2c, 0xea, 0xd3, 0x04, 0xf0, 0xa1, 0xfa, - 0x08, 0xb1, 0x04, 0xf0, 0xa2, 0xfa, 0xdf, 0xf8, 0xd8, 0x44, 0xe0, 0x78, - 0x01, 0x28, 0x43, 0xd1, 0x00, 0x20, 0x01, 0xf0, 0xef, 0xf9, 0x00, 0x1f, - 0x0c, 0x28, 0x3b, 0xd2, 0x01, 0x20, 0x01, 0xf0, 0xe9, 0xf9, 0x05, 0x46, - 0x02, 0x20, 0x01, 0xf0, 0xe5, 0xf9, 0x06, 0x46, 0x03, 0x20, 0x01, 0xf0, - 0xe1, 0xf9, 0x04, 0x2d, 0xb8, 0xbf, 0x00, 0x21, 0x07, 0xdb, 0x10, 0x2d, - 0xb8, 0xbf, 0x01, 0x21, 0x03, 0xdb, 0x13, 0x2d, 0xb4, 0xbf, 0x02, 0x21, - 0x03, 0x21, 0x04, 0x2e, 0xb8, 0xbf, 0x00, 0x22, 0x07, 0xdb, 0x10, 0x2e, - 0xb8, 0xbf, 0x01, 0x22, 0x03, 0xdb, 0x13, 0x2e, 0xb4, 0xbf, 0x02, 0x22, - 0x03, 0x22, 0x04, 0x28, 0xb8, 0xbf, 0x00, 0x23, 0x07, 0xdb, 0x10, 0x28, - 0xb8, 0xbf, 0x01, 0x23, 0x03, 0xdb, 0x13, 0x28, 0xb4, 0xbf, 0x02, 0x23, - 0x03, 0x23, 0x03, 0x29, 0x0a, 0xd2, 0x91, 0x42, 0x08, 0xbf, 0x99, 0x42, - 0x06, 0xd1, 0x02, 0x29, 0x06, 0xd1, 0x10, 0x2d, 0x04, 0xbf, 0x11, 0x2e, - 0x12, 0x28, 0x01, 0xd0, 0x04, 0x20, 0xf2, 0xbd, 0xef, 0xf3, 0x10, 0x86, - 0x72, 0xb6, 0xdf, 0xf8, 0x04, 0x55, 0x0f, 0xf6, 0xec, 0x00, 0x07, 0x22, - 0x05, 0xf1, 0x8c, 0x01, 0xfa, 0xf7, 0xad, 0xfa, 0xff, 0xf7, 0xef, 0xfc, - 0xff, 0xf7, 0x71, 0xfd, 0xff, 0xf7, 0xf3, 0xfd, 0x21, 0x7a, 0x4f, 0xf4, - 0xdb, 0x70, 0xfa, 0xf7, 0x71, 0xfa, 0x61, 0x7a, 0x40, 0xf2, 0xb7, 0x10, - 0xfa, 0xf7, 0x6c, 0xfa, 0x08, 0x20, 0xff, 0xf7, 0x67, 0xf9, 0x40, 0xf2, - 0x2f, 0x47, 0x80, 0x22, 0x80, 0x21, 0x38, 0x46, 0xfa, 0xf7, 0x6c, 0xfa, - 0x00, 0x22, 0x80, 0x21, 0x38, 0x46, 0xfa, 0xf7, 0x67, 0xfa, 0xa0, 0x78, - 0x01, 0x28, 0x18, 0xbf, 0x00, 0x20, 0xff, 0xf7, 0x67, 0xf9, 0xff, 0xf7, - 0xa3, 0xfb, 0x01, 0x20, 0x28, 0x71, 0x86, 0xf3, 0x10, 0x88, 0x10, 0x20, - 0xff, 0xf7, 0xb2, 0xf9, 0x28, 0x7a, 0x41, 0x07, 0x48, 0xbf, 0x0c, 0x20, - 0x08, 0xd4, 0xc0, 0x07, 0x44, 0xbf, 0x0a, 0x20, 0xff, 0xf7, 0xa8, 0xf9, - 0x28, 0x7a, 0x80, 0x07, 0x02, 0xd5, 0x1d, 0x20, 0xff, 0xf7, 0xa2, 0xf9, - 0xdf, 0xf8, 0x68, 0x47, 0x20, 0x78, 0x41, 0x07, 0x48, 0xbf, 0x0d, 0x20, - 0x08, 0xd4, 0xc0, 0x07, 0x44, 0xbf, 0x0b, 0x20, 0xff, 0xf7, 0x96, 0xf9, - 0x20, 0x78, 0x80, 0x07, 0x02, 0xd5, 0x1e, 0x20, 0xff, 0xf7, 0x90, 0xf9, - 0x1f, 0x20, 0xff, 0xf7, 0x8d, 0xf9, 0x06, 0xf0, 0xc5, 0xfa, 0x00, 0x20, - 0xf2, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x4f, 0xf0, 0x92, 0x45, 0xdf, 0xf8, - 0x3c, 0x64, 0x28, 0x68, 0x69, 0x68, 0x6f, 0x68, 0x4f, 0xea, 0x11, 0x28, - 0x31, 0x79, 0x00, 0x24, 0x01, 0x29, 0x04, 0xbf, 0x00, 0xf0, 0x3f, 0x00, - 0x0a, 0x28, 0x63, 0xd1, 0x00, 0x21, 0xff, 0xf7, 0x53, 0xfa, 0xff, 0xb2, - 0x61, 0x2f, 0xdf, 0xf8, 0xa0, 0x07, 0x40, 0xd0, 0x64, 0x2f, 0x04, 0xbf, - 0x80, 0x78, 0x00, 0x28, 0x56, 0xd1, 0xd6, 0xf8, 0x80, 0x00, 0x08, 0xf0, - 0x0f, 0x08, 0x88, 0xea, 0x00, 0x07, 0xf8, 0x07, 0x0b, 0xd5, 0x71, 0x6a, - 0x08, 0xf0, 0x01, 0x00, 0xc0, 0x01, 0x08, 0x60, 0x01, 0x24, 0xb1, 0x6a, - 0xf0, 0x6a, 0x08, 0x60, 0x0a, 0x20, 0xff, 0xf7, 0x64, 0xf9, 0xb8, 0x07, - 0x0b, 0xd5, 0x31, 0x6b, 0x08, 0xf0, 0x02, 0x00, 0x80, 0x04, 0x08, 0x60, - 0x01, 0x24, 0x71, 0x6b, 0xb0, 0x6b, 0x08, 0x60, 0x1d, 0x20, 0xff, 0xf7, - 0x56, 0xf9, 0x78, 0x07, 0x0b, 0xd5, 0xf1, 0x68, 0x08, 0xf0, 0x04, 0x00, - 0x00, 0x01, 0x08, 0x60, 0x01, 0x24, 0x31, 0x69, 0x70, 0x69, 0x08, 0x60, - 0x0b, 0x20, 0xff, 0xf7, 0x48, 0xf9, 0x38, 0x07, 0x1c, 0xd5, 0xb1, 0x69, - 0x08, 0xf0, 0x08, 0x00, 0x40, 0x04, 0x08, 0x60, 0xf1, 0x69, 0x30, 0x6a, - 0x08, 0x60, 0x1e, 0x20, 0x0f, 0xe0, 0xc0, 0x78, 0xc0, 0xb9, 0xf1, 0x6b, - 0x08, 0xf0, 0x07, 0x00, 0x08, 0x60, 0x04, 0x28, 0x32, 0x6c, 0x71, 0x6c, - 0x11, 0x60, 0x04, 0xbf, 0xc8, 0xf3, 0x01, 0x10, 0x00, 0xf0, 0xf3, 0xfa, - 0x1f, 0x20, 0xff, 0xf7, 0x2a, 0xf9, 0x00, 0xe0, 0x5c, 0xb1, 0x00, 0x20, - 0x28, 0x60, 0x0a, 0x20, 0xbd, 0xe8, 0xf0, 0x41, 0xfb, 0xf7, 0x1b, 0xbc, - 0xbd, 0xe8, 0xf0, 0x41, 0x0f, 0x20, 0xff, 0xf7, 0x1c, 0xb9, 0xbd, 0xe8, - 0xf0, 0x81, 0x10, 0xb5, 0x05, 0xf0, 0xe8, 0xfc, 0x05, 0xf0, 0x1c, 0xfc, - 0xd8, 0x4c, 0x00, 0x20, 0xa0, 0x60, 0x02, 0x20, 0xe0, 0x60, 0x31, 0x20, - 0xff, 0xf7, 0xf8, 0xf8, 0xcb, 0x48, 0x01, 0x21, 0x41, 0x71, 0x84, 0x30, - 0xd1, 0x49, 0x49, 0x68, 0x21, 0x60, 0x70, 0x21, 0xa1, 0x60, 0xbd, 0xe8, - 0x10, 0x40, 0xfa, 0xf7, 0xa3, 0xbc, 0x70, 0xb5, 0x00, 0xf0, 0x8c, 0xf8, - 0x10, 0xd5, 0x30, 0x78, 0x40, 0xf0, 0x40, 0x00, 0x30, 0x70, 0x04, 0x20, - 0xff, 0xf7, 0xae, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, 0x01, 0x00, - 0xc5, 0xf8, 0x80, 0x00, 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x0f, 0xe0, - 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x30, 0x78, 0x00, 0xf0, 0xbf, 0x00, - 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0xa4, 0xfa, 0xd5, 0xf8, 0x80, 0x00, - 0x40, 0x08, 0x40, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x62, 0xe0, 0x70, 0xb5, - 0xb1, 0x4c, 0xdf, 0xf8, 0x54, 0x56, 0x61, 0x6b, 0xdf, 0xf8, 0x50, 0x66, - 0x4f, 0xf4, 0x00, 0x20, 0x08, 0x60, 0x4f, 0xf6, 0xfe, 0x60, 0x28, 0x60, - 0x20, 0x6b, 0x00, 0x68, 0x00, 0x03, 0x10, 0xd5, 0x30, 0x78, 0x40, 0xf0, - 0x80, 0x00, 0x30, 0x70, 0x05, 0x20, 0xff, 0xf7, 0x7b, 0xfa, 0xd4, 0xf8, - 0x80, 0x00, 0x40, 0xf0, 0x02, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0x01, 0x20, - 0xc0, 0x46, 0xc0, 0x46, 0x0f, 0xe0, 0x01, 0x20, 0xc0, 0x46, 0xc0, 0x46, - 0x30, 0x78, 0x00, 0xf0, 0x7f, 0x00, 0x30, 0x70, 0x05, 0x20, 0xff, 0xf7, - 0x71, 0xfa, 0xd4, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x02, 0x00, 0xc4, 0xf8, - 0x80, 0x00, 0x10, 0x20, 0xff, 0xf7, 0xa5, 0xf8, 0x00, 0x20, 0x28, 0x60, - 0x70, 0xbd, 0x70, 0xb5, 0x00, 0xf0, 0x2e, 0xf8, 0x13, 0xd5, 0x30, 0x78, - 0x40, 0xf0, 0xc0, 0x00, 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0x50, 0xfa, - 0x05, 0x20, 0xff, 0xf7, 0x4d, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, - 0x03, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x02, 0x20, 0xc0, 0x46, 0xc0, 0x46, - 0x12, 0xe0, 0x02, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x30, 0x78, 0x00, 0xf0, - 0x3f, 0x00, 0x30, 0x70, 0x04, 0x20, 0xff, 0xf7, 0x43, 0xfa, 0x05, 0x20, - 0xff, 0xf7, 0x40, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x80, 0x08, 0x80, 0x00, - 0xc5, 0xf8, 0x80, 0x00, 0x10, 0x20, 0xff, 0xf7, 0x74, 0xf8, 0x00, 0x20, - 0x20, 0x60, 0x70, 0xbd, 0xdf, 0xf8, 0x84, 0x45, 0x7c, 0x4d, 0xdf, 0xf8, - 0x84, 0x65, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, 0x80, 0x20, 0xa9, 0x6a, - 0x08, 0x60, 0x68, 0x6a, 0x00, 0x68, 0x00, 0x06, 0x70, 0x47, 0x38, 0xb5, - 0x00, 0xf0, 0x75, 0xf8, 0x0c, 0xd5, 0x41, 0xf0, 0x10, 0x01, 0x01, 0x70, - 0x06, 0x20, 0xff, 0xf7, 0x11, 0xfa, 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, - 0x04, 0x00, 0x00, 0xf0, 0x3f, 0xf8, 0x0b, 0xe0, 0x01, 0xf0, 0xef, 0x01, - 0x01, 0x70, 0x06, 0x20, 0xff, 0xf7, 0x0e, 0xfa, 0xd5, 0xf8, 0x80, 0x00, - 0x20, 0xf0, 0x04, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0x2a, 0xe0, 0x38, 0xb5, - 0xdf, 0xf8, 0x28, 0x45, 0x65, 0x4d, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, - 0x4f, 0xf4, 0x80, 0x10, 0xe9, 0x69, 0x08, 0x60, 0xa9, 0x69, 0xdf, 0xf8, - 0x18, 0x05, 0x09, 0x68, 0xc9, 0x02, 0x01, 0x78, 0x0c, 0xd5, 0x41, 0xf0, - 0x20, 0x01, 0x01, 0x70, 0x07, 0x20, 0xff, 0xf7, 0xe5, 0xf9, 0xd5, 0xf8, - 0x80, 0x00, 0x40, 0xf0, 0x08, 0x00, 0x00, 0xf0, 0x13, 0xf8, 0x0b, 0xe0, - 0x01, 0xf0, 0xdf, 0x01, 0x01, 0x70, 0x07, 0x20, 0xff, 0xf7, 0xe2, 0xf9, - 0xd5, 0xf8, 0x80, 0x00, 0x20, 0xf0, 0x08, 0x00, 0xc5, 0xf8, 0x80, 0x00, - 0x10, 0x20, 0xff, 0xf7, 0x16, 0xf8, 0x00, 0x20, 0x20, 0x60, 0x31, 0xbd, - 0xc5, 0xf8, 0x80, 0x00, 0x0e, 0x20, 0xff, 0xf7, 0x0e, 0xb8, 0x38, 0xb5, - 0x00, 0xf0, 0x21, 0xf8, 0x0f, 0xd5, 0x41, 0xf0, 0x30, 0x01, 0x01, 0x70, - 0x06, 0x20, 0xff, 0xf7, 0xbd, 0xf9, 0x07, 0x20, 0xff, 0xf7, 0xba, 0xf9, - 0xd5, 0xf8, 0x80, 0x00, 0x40, 0xf0, 0x0c, 0x00, 0xff, 0xf7, 0xe8, 0xff, - 0x0e, 0xe0, 0x01, 0xf0, 0xcf, 0x01, 0x01, 0x70, 0x06, 0x20, 0xff, 0xf7, - 0xb7, 0xf9, 0x07, 0x20, 0xff, 0xf7, 0xb4, 0xf9, 0xd5, 0xf8, 0x80, 0x00, - 0x20, 0xf0, 0x0c, 0x00, 0xc5, 0xf8, 0x80, 0x00, 0xd0, 0xe7, 0xdf, 0xf8, - 0x78, 0x44, 0x39, 0x4d, 0x4f, 0xf6, 0xfe, 0x60, 0x20, 0x60, 0x40, 0x20, - 0x29, 0x69, 0x08, 0x60, 0xe9, 0x68, 0xdf, 0xf8, 0x68, 0x04, 0x09, 0x68, - 0x49, 0x06, 0x01, 0x78, 0x70, 0x47, 0x00, 0x00, 0x18, 0x00, 0x00, 0x49, - 0x4c, 0x1f, 0x00, 0x20, 0x00, 0xf2, 0x00, 0x20, 0x40, 0x42, 0x0f, 0x00, - 0xf8, 0xb5, 0x2d, 0x48, 0x02, 0x6c, 0x41, 0x6c, 0x11, 0x60, 0xd0, 0xf8, - 0x80, 0x10, 0xc1, 0xf3, 0x02, 0x14, 0xc1, 0x6b, 0x91, 0xb1, 0x09, 0x68, - 0x42, 0x6f, 0x21, 0xfa, 0x02, 0xf3, 0x82, 0x6f, 0x21, 0xfa, 0x02, 0xf5, - 0x05, 0xf0, 0x01, 0x02, 0x5b, 0x08, 0xc3, 0x6f, 0x52, 0x41, 0xd9, 0x40, - 0x01, 0xf0, 0x01, 0x01, 0x42, 0xea, 0x81, 0x05, 0xed, 0xb2, 0x04, 0xe0, - 0xdf, 0xf8, 0x10, 0x14, 0x09, 0x78, 0x01, 0xf0, 0x07, 0x05, 0xac, 0x42, - 0x35, 0xd0, 0xd0, 0xf8, 0x80, 0x10, 0xdf, 0xf8, 0xf8, 0x63, 0x21, 0xf0, - 0x70, 0x01, 0x41, 0xea, 0x05, 0x11, 0xc0, 0xf8, 0x80, 0x10, 0x10, 0x20, - 0xfe, 0xf7, 0x9f, 0xff, 0x4f, 0xf6, 0xfe, 0x60, 0x30, 0x60, 0xdf, 0xf8, - 0xd8, 0x03, 0x00, 0x7e, 0xc0, 0x07, 0x03, 0xd5, 0xdf, 0xf8, 0xb8, 0x03, - 0x00, 0xf0, 0x83, 0xf8, 0xdf, 0xf8, 0xd4, 0x73, 0x0f, 0xf2, 0x50, 0x41, - 0x38, 0x78, 0x00, 0xf0, 0xef, 0x00, 0x38, 0x70, 0x20, 0x46, 0x51, 0xf8, - 0x24, 0x10, 0x88, 0x47, 0x0f, 0xf2, 0x1c, 0x41, 0x51, 0xf8, 0x25, 0x10, - 0x28, 0x46, 0x88, 0x47, 0x38, 0x78, 0x40, 0xf0, 0x10, 0x00, 0x38, 0x70, - 0x00, 0x20, 0x30, 0x60, 0x1c, 0x20, 0xbd, 0xe8, 0xf2, 0x40, 0xfe, 0xf7, - 0x76, 0xbf, 0xf1, 0xbd, 0xd0, 0x1f, 0x00, 0x20, 0xdf, 0xf8, 0x98, 0x03, - 0xdf, 0xf8, 0x98, 0x23, 0x01, 0x78, 0x92, 0xf8, 0x6b, 0x20, 0x01, 0xf0, - 0xe0, 0x01, 0x11, 0x43, 0x41, 0xf0, 0x20, 0x01, 0x01, 0x70, 0x70, 0x47, - 0x30, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x20, 0x59, 0xdf, 0xf8, 0x7c, 0x13, - 0x00, 0x20, 0x08, 0x70, 0xdf, 0xf8, 0x78, 0x13, 0x08, 0x80, 0x70, 0x47, - 0x70, 0x47, 0x10, 0xb5, 0x00, 0xf0, 0x2b, 0xf8, 0x00, 0xf0, 0x65, 0xf8, - 0xa4, 0x7c, 0x00, 0xf0, 0x69, 0xf8, 0x49, 0x7d, 0x81, 0x70, 0x01, 0x21, - 0x11, 0x70, 0xd4, 0x4a, 0x41, 0x79, 0x00, 0xf0, 0x54, 0xf8, 0x41, 0x71, - 0x01, 0x20, 0x11, 0xe0, 0xb4, 0x28, 0x00, 0x20, 0x10, 0xb5, 0x00, 0xf0, - 0x16, 0xf8, 0x00, 0xf0, 0x75, 0xf8, 0xa4, 0x7c, 0x23, 0x43, 0x03, 0x70, - 0x09, 0x78, 0x89, 0x18, 0x49, 0x7d, 0x81, 0x70, 0x01, 0x20, 0x00, 0xf0, - 0x68, 0xf8, 0x05, 0x20, 0x05, 0xf0, 0x67, 0xf9, 0x00, 0xf0, 0x1d, 0xf9, - 0x08, 0x20, 0xbd, 0xe8, 0x10, 0x40, 0xff, 0xf7, 0xe3, 0xb8, 0xc6, 0x48, - 0xc6, 0x4a, 0x01, 0x79, 0x01, 0xf0, 0x7f, 0x01, 0x01, 0x71, 0x70, 0x47, - 0x0c, 0x00, 0x00, 0x59, 0x80, 0xb5, 0x00, 0xe0, 0x80, 0xb5, 0x05, 0xf0, - 0x85, 0xf9, 0xc1, 0x48, 0x81, 0x78, 0x41, 0xf0, 0x80, 0x01, 0x81, 0x70, - 0x00, 0xf0, 0x05, 0xf8, 0x08, 0x20, 0xbd, 0xe8, 0x02, 0x40, 0xff, 0xf7, - 0xd3, 0xb8, 0x01, 0x78, 0x41, 0xf0, 0xc0, 0x01, 0x01, 0x70, 0x70, 0x47, - 0x10, 0xb5, 0x00, 0xf0, 0x49, 0xf8, 0x00, 0xf0, 0x18, 0xf8, 0x24, 0x7e, - 0x00, 0xf0, 0x1c, 0xf8, 0xc9, 0x7e, 0x81, 0x70, 0x02, 0x21, 0x11, 0x70, - 0xad, 0x4a, 0x01, 0x79, 0x00, 0xf0, 0x07, 0xf8, 0x01, 0x71, 0x02, 0x20, - 0x05, 0xf0, 0x2d, 0xf9, 0x00, 0xf0, 0x42, 0xf8, 0xc5, 0xe7, 0x92, 0xf8, - 0x43, 0x20, 0x01, 0xf0, 0xc0, 0x01, 0x11, 0x43, 0x70, 0x47, 0xab, 0x49, - 0x03, 0x78, 0x0c, 0x78, 0xa4, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0x70, 0x47, - 0x23, 0x43, 0x03, 0x70, 0x09, 0x78, 0x89, 0x18, 0xa0, 0x4a, 0x70, 0x47, - 0x10, 0xb5, 0x00, 0xf0, 0x1f, 0xf8, 0x00, 0xf0, 0x13, 0xf8, 0x24, 0x7e, - 0x23, 0x43, 0x03, 0x70, 0x09, 0x78, 0x89, 0x18, 0xc9, 0x7e, 0x81, 0x70, - 0x02, 0x20, 0x00, 0xf0, 0x06, 0xf8, 0x06, 0x20, 0x05, 0xf0, 0x05, 0xf9, - 0x00, 0xf0, 0x1a, 0xf8, 0x9d, 0xe7, 0x95, 0x49, 0x08, 0x70, 0x55, 0xe7, - 0x99, 0x49, 0x03, 0x78, 0x0c, 0x78, 0xa4, 0x18, 0x03, 0xf0, 0xc0, 0x03, - 0x70, 0x47, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0x95, 0x48, 0x91, 0x4a, - 0xc1, 0x78, 0x01, 0xf0, 0xbf, 0x01, 0xc1, 0x70, 0x70, 0x47, 0x00, 0x00, - 0x04, 0x00, 0x00, 0x50, 0x04, 0x00, 0x00, 0x58, 0x7c, 0x48, 0x01, 0x78, - 0x01, 0xf0, 0x3f, 0x01, 0x01, 0x70, 0x09, 0x20, 0x70, 0x47, 0x80, 0xb5, - 0x05, 0xf0, 0x12, 0xf9, 0x00, 0xf0, 0x07, 0xf8, 0x91, 0xe7, 0x80, 0xb5, - 0x05, 0xf0, 0x0c, 0xf9, 0x00, 0xf0, 0x01, 0xf8, 0x8b, 0xe7, 0x87, 0x48, - 0x41, 0x78, 0x41, 0xf0, 0x40, 0x01, 0x41, 0x70, 0x01, 0x78, 0x41, 0xf0, - 0xc0, 0x01, 0x01, 0x70, 0x09, 0x20, 0x70, 0x47, 0x10, 0xb5, 0x79, 0x49, - 0x7a, 0x4a, 0x00, 0x20, 0x08, 0x70, 0x7a, 0x49, 0x7b, 0x48, 0x13, 0x78, - 0x00, 0xf0, 0x1c, 0xf8, 0xa4, 0x7c, 0x23, 0x43, 0x13, 0x70, 0x93, 0x78, - 0x00, 0xf0, 0x16, 0xf8, 0x64, 0x7d, 0x23, 0x43, 0x93, 0x70, 0x53, 0x78, - 0x00, 0xf0, 0x10, 0xf8, 0x24, 0x7e, 0x23, 0x43, 0x53, 0x70, 0xd3, 0x78, - 0x00, 0x78, 0x40, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0xc0, 0x7e, 0x18, 0x43, - 0xd0, 0x70, 0x10, 0xbd, 0x08, 0x00, 0x00, 0x50, 0x08, 0x00, 0x00, 0x58, - 0x04, 0x78, 0x64, 0x18, 0x03, 0xf0, 0xc0, 0x03, 0x70, 0x47, 0x80, 0xb5, - 0x05, 0xf0, 0xd0, 0xf8, 0x6b, 0x48, 0xff, 0xf7, 0x54, 0xff, 0x41, 0x78, - 0x41, 0xf0, 0xc0, 0x01, 0x41, 0x70, 0x63, 0x49, 0x8a, 0x78, 0x42, 0xf0, - 0xc0, 0x02, 0x8a, 0x70, 0x0a, 0x78, 0x42, 0xf0, 0xc0, 0x02, 0x0a, 0x70, - 0x4a, 0x78, 0x42, 0xf0, 0xc0, 0x02, 0x4a, 0x70, 0x81, 0x79, 0x01, 0xf0, - 0xcc, 0x01, 0x81, 0x71, 0x60, 0x48, 0x61, 0x49, 0x0a, 0x78, 0x03, 0x78, - 0x1a, 0x40, 0x83, 0x78, 0x1a, 0x43, 0x0a, 0x70, 0x4a, 0x78, 0x43, 0x78, - 0x1a, 0x40, 0xc3, 0x78, 0x1a, 0x43, 0x4a, 0x70, 0x01, 0x21, 0x41, 0x60, - 0x81, 0x60, 0x00, 0x20, 0x42, 0x49, 0x08, 0x70, 0x01, 0xbd, 0x08, 0xb1, - 0x57, 0x49, 0x08, 0x70, 0x70, 0x47, 0x56, 0x48, 0x00, 0x78, 0x70, 0x47, - 0x80, 0xb5, 0x55, 0x48, 0x53, 0x4a, 0x81, 0x79, 0x46, 0x4b, 0x01, 0xf0, - 0x7f, 0x01, 0x81, 0x71, 0x41, 0x79, 0x01, 0xf0, 0x3f, 0x01, 0x41, 0x71, - 0x12, 0x78, 0x0f, 0xf2, 0xa4, 0x11, 0x51, 0x5c, 0x4e, 0x4a, 0x11, 0x70, - 0x04, 0x22, 0x1a, 0x70, 0x01, 0x70, 0xff, 0xf7, 0xa9, 0xfe, 0x04, 0x20, - 0x05, 0xf0, 0x4f, 0xf8, 0x00, 0xf0, 0x05, 0xf8, 0x0a, 0x20, 0xbd, 0xe8, - 0x02, 0x40, 0xfe, 0xf7, 0xcb, 0xbf, 0x2c, 0x48, 0x01, 0x78, 0x01, 0xf0, - 0x3f, 0x01, 0x01, 0x70, 0x70, 0x47, 0x80, 0xb5, 0x05, 0xf0, 0x72, 0xf8, - 0x40, 0x48, 0x00, 0x21, 0x01, 0x70, 0x81, 0x79, 0x41, 0xf0, 0x80, 0x01, - 0x81, 0x71, 0x41, 0x79, 0x41, 0xf0, 0xc0, 0x01, 0x41, 0x71, 0x0a, 0x20, - 0xe7, 0xe6, 0x00, 0x00, 0x64, 0xf3, 0x00, 0x20, 0x0c, 0x00, 0x00, 0x58, - 0x44, 0x00, 0x00, 0x50, 0x2d, 0xe9, 0xf0, 0x47, 0x04, 0x46, 0x91, 0x46, - 0x9a, 0x46, 0xfe, 0xf7, 0xa1, 0xff, 0x1c, 0x4f, 0x80, 0x46, 0x38, 0x79, - 0x01, 0x28, 0x25, 0xd1, 0x02, 0x2c, 0x21, 0xd1, 0xfe, 0xf7, 0x98, 0xff, - 0x30, 0x4e, 0x31, 0x49, 0x35, 0x68, 0x04, 0x46, 0x4f, 0xf0, 0x00, 0x40, - 0x08, 0x60, 0xd7, 0xf8, 0x80, 0x00, 0xc0, 0xf3, 0x02, 0x10, 0x03, 0x28, - 0x18, 0xbf, 0x04, 0x28, 0x09, 0xd0, 0x05, 0x28, 0x18, 0xbf, 0x06, 0x28, - 0x05, 0xd0, 0x02, 0x22, 0x48, 0x46, 0x51, 0x46, 0x03, 0xf0, 0xc4, 0xfc, - 0x00, 0xe0, 0x05, 0x20, 0x05, 0xf0, 0x00, 0x41, 0x31, 0x60, 0x84, 0xf3, - 0x11, 0x88, 0x06, 0xe0, 0x05, 0x20, 0x04, 0xe0, 0x22, 0x46, 0x48, 0x46, - 0x51, 0x46, 0x03, 0xf0, 0xb5, 0xfc, 0x88, 0xf3, 0x11, 0x88, 0xc0, 0xb2, - 0xbd, 0xe8, 0xf0, 0x87, 0x41, 0x0c, 0x00, 0x46, 0x65, 0x2c, 0x00, 0x20, - 0xd0, 0x1f, 0x00, 0x20, 0x4c, 0x00, 0x00, 0x50, 0x4c, 0x00, 0x00, 0x58, - 0x4c, 0x1f, 0x00, 0x20, 0x48, 0x00, 0x00, 0x50, 0xb0, 0x01, 0x00, 0x46, - 0x28, 0x0b, 0x00, 0x46, 0x42, 0x06, 0x00, 0x46, 0x15, 0x08, 0x00, 0x46, - 0x68, 0xee, 0x00, 0x20, 0x04, 0x01, 0x00, 0x46, 0xfe, 0x01, 0x00, 0x41, - 0x10, 0x08, 0x00, 0x46, 0x4c, 0x29, 0x00, 0x20, 0x12, 0x08, 0x00, 0x46, - 0x6c, 0x29, 0x00, 0x20, 0x6d, 0x29, 0x00, 0x20, 0x11, 0x08, 0x00, 0x46, - 0x13, 0x08, 0x00, 0x46, 0x42, 0x05, 0x00, 0x46, 0xec, 0x2b, 0x00, 0x20, - 0x02, 0x0b, 0x00, 0x46, 0x64, 0x2c, 0x00, 0x20, 0x1a, 0x08, 0x00, 0x46, - 0x0c, 0x02, 0x00, 0x46, 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, - 0x04, 0x02, 0x84, 0x0d, 0x05, 0x02, 0x85, 0x0d, 0x06, 0x02, 0x86, 0x0d, - 0x41, 0x0c, 0x00, 0x00, 0x45, 0x90, 0x00, 0x01, 0x57, 0x90, 0x00, 0x01, - 0xf1, 0x90, 0x00, 0x01, 0xdd, 0x91, 0x00, 0x01, 0xa1, 0x92, 0x00, 0x01, - 0x81, 0x90, 0x00, 0x01, 0x45, 0x91, 0x00, 0x01, 0x45, 0x90, 0x00, 0x01, - 0x55, 0x90, 0x00, 0x01, 0xc5, 0x90, 0x00, 0x01, 0xaf, 0x91, 0x00, 0x01, - 0x33, 0x92, 0x00, 0x01, 0xef, 0x92, 0x00, 0x01, 0xc9, 0x90, 0x00, 0x01, - 0xbb, 0x91, 0x00, 0x01, 0x55, 0x90, 0x00, 0x01, 0x08, 0x09, 0x00, 0x00, - 0x0c, 0x0d, 0x00, 0x00, 0x00, 0x03, 0x0c, 0x30, 0x0f, 0xf2, 0x2c, 0x02, - 0x00, 0xf0, 0x1f, 0x00, 0x80, 0x5c, 0x08, 0xb9, 0x03, 0x20, 0x70, 0x47, - 0x01, 0x22, 0x02, 0xfa, 0x01, 0xf1, 0x08, 0x42, 0x14, 0xbf, 0x00, 0x20, - 0x02, 0x20, 0x70, 0x47, 0x0f, 0xf2, 0x1c, 0x02, 0x06, 0x23, 0x03, 0xfb, - 0x00, 0x20, 0x08, 0x5c, 0x70, 0x47, 0x00, 0x00, 0x0c, 0x18, 0x1c, 0x1c, - 0x18, 0x3e, 0x3e, 0x18, 0x00, 0x3e, 0x1c, 0x3e, 0x3e, 0x0c, 0x00, 0x00, - 0x02, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x80, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x02, 0x02, 0x00, 0x80, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x02, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0xb5, 0x08, 0x46, - 0x6b, 0x46, 0x40, 0x68, 0x01, 0x22, 0x08, 0x21, 0xf8, 0xf7, 0x44, 0xff, - 0x00, 0xf0, 0x01, 0xf8, 0x01, 0xbd, 0x9d, 0xf8, 0x00, 0x10, 0x48, 0x1e, - 0x80, 0x41, 0xc0, 0x0f, 0xfe, 0xf7, 0x9d, 0xbc, 0x70, 0xb5, 0x82, 0xb0, - 0x0d, 0xf1, 0x01, 0x00, 0xfa, 0xf7, 0x47, 0xfa, 0x01, 0x24, 0x67, 0x4d, - 0x58, 0x20, 0x00, 0xfb, 0x04, 0x56, 0x33, 0x69, 0x18, 0x00, 0x03, 0xd0, - 0x70, 0x6a, 0x00, 0x22, 0x00, 0x21, 0x98, 0x47, 0x69, 0x46, 0x00, 0x20, - 0xf8, 0xf7, 0x73, 0xfe, 0x70, 0x60, 0xff, 0xf7, 0xe0, 0xff, 0x64, 0x1c, - 0x11, 0x2c, 0xeb, 0xd3, 0x05, 0xf0, 0x46, 0xff, 0x0d, 0xf1, 0x01, 0x00, - 0x00, 0xf0, 0xe0, 0xfa, 0x73, 0xbd, 0xf8, 0xb5, 0xfe, 0xf7, 0x70, 0xfe, - 0x00, 0x24, 0x57, 0x4d, 0x57, 0x4e, 0xe0, 0xb2, 0xfb, 0xf7, 0xae, 0xf8, - 0x60, 0xb1, 0xa0, 0x5d, 0x58, 0x21, 0x01, 0xfb, 0x00, 0x57, 0x00, 0xf0, - 0x25, 0xf8, 0x3b, 0x69, 0x18, 0x00, 0x03, 0xd0, 0x78, 0x6a, 0x00, 0x22, - 0x02, 0x21, 0x98, 0x47, 0x64, 0x1c, 0x10, 0x2c, 0xeb, 0xd3, 0xf1, 0xbd, - 0x10, 0xb5, 0x4b, 0x4c, 0x82, 0xb0, 0x60, 0x62, 0x60, 0x68, 0x20, 0xb9, - 0x69, 0x46, 0xf8, 0xf7, 0x42, 0xfe, 0x60, 0x60, 0x03, 0xe0, 0x00, 0xf0, - 0x98, 0xf8, 0xff, 0xf7, 0xac, 0xff, 0x00, 0x20, 0x00, 0xf0, 0x08, 0xf8, - 0x23, 0x69, 0x18, 0x00, 0x03, 0xd0, 0x60, 0x6a, 0x00, 0x22, 0x02, 0x21, - 0x98, 0x47, 0x13, 0xbd, 0x30, 0xb5, 0x04, 0x46, 0x3d, 0x48, 0x58, 0x21, - 0x87, 0xb0, 0x01, 0xfb, 0x04, 0x05, 0xfb, 0xf7, 0x37, 0xf8, 0xc4, 0xb1, - 0x3b, 0x48, 0x20, 0x5c, 0xfb, 0xf7, 0x74, 0xf8, 0x00, 0x28, 0x36, 0xd0, - 0x20, 0x46, 0xfa, 0xf7, 0xfd, 0xfd, 0x05, 0xa9, 0x02, 0x91, 0x00, 0x95, - 0x00, 0x21, 0x01, 0x91, 0x01, 0x46, 0x35, 0x4b, 0x01, 0x22, 0x00, 0x20, - 0xf9, 0xf7, 0xa4, 0xfa, 0xa8, 0x62, 0x9d, 0xf8, 0x14, 0x10, 0xff, 0xf7, - 0x80, 0xff, 0xeb, 0x6b, 0xa8, 0x6c, 0xe9, 0x6c, 0x01, 0x90, 0x03, 0x22, - 0x04, 0x92, 0x02, 0x91, 0x9a, 0xb2, 0x00, 0x92, 0x00, 0xeb, 0x81, 0x00, - 0x03, 0x94, 0x02, 0x1f, 0x69, 0x6a, 0x68, 0x6c, 0xdb, 0xb2, 0xf9, 0xf7, - 0x6c, 0xf9, 0x8d, 0xf8, 0x14, 0x00, 0x00, 0xf0, 0x4d, 0xf8, 0xe8, 0x6b, - 0x29, 0x6c, 0x05, 0xaa, 0xc0, 0xb2, 0xf9, 0xf7, 0x19, 0xfa, 0x9d, 0xf8, - 0x14, 0x10, 0xff, 0xf7, 0x60, 0xff, 0x29, 0x46, 0x20, 0x46, 0xf9, 0xf7, - 0x23, 0xff, 0x00, 0x20, 0x07, 0xb0, 0x30, 0xbd, 0x38, 0xb5, 0x05, 0x46, - 0x18, 0x48, 0x58, 0x21, 0x01, 0xfb, 0x05, 0x04, 0xfa, 0xf7, 0xee, 0xff, - 0x25, 0xb1, 0x17, 0x48, 0x28, 0x5c, 0xfb, 0xf7, 0x2b, 0xf8, 0xf8, 0xb1, - 0x28, 0x46, 0xfa, 0xf7, 0x99, 0xf8, 0xa0, 0x6a, 0x68, 0xb1, 0x6b, 0x46, - 0x00, 0x22, 0x00, 0x21, 0xf9, 0xf7, 0x46, 0xfb, 0xa0, 0x6a, 0x0d, 0xf1, - 0x01, 0x01, 0xf9, 0xf7, 0x99, 0xfa, 0x9d, 0xf8, 0x01, 0x10, 0xff, 0xf7, - 0x38, 0xff, 0x60, 0x68, 0x00, 0xf0, 0x1d, 0xf8, 0xff, 0xf7, 0x31, 0xff, - 0xe0, 0x6b, 0xc0, 0xb2, 0xf9, 0xf7, 0x74, 0xf9, 0x8d, 0xf8, 0x00, 0x00, - 0x00, 0xf0, 0x0e, 0xf8, 0x9d, 0xf8, 0x00, 0x00, 0x00, 0xb1, 0x02, 0x20, - 0x32, 0xbd, 0x00, 0x00, 0xd8, 0x20, 0x00, 0x20, 0xc8, 0x20, 0x00, 0x20, - 0xf4, 0x1e, 0x00, 0x20, 0xf5, 0x94, 0x00, 0x01, 0x40, 0x1e, 0x80, 0x41, - 0xc0, 0x0f, 0xfe, 0xf7, 0xba, 0xbb, 0x6b, 0x46, 0x00, 0x22, 0x4f, 0xf6, - 0xff, 0x71, 0xf8, 0xf7, 0x51, 0xbe, 0x00, 0x00, 0x2c, 0x21, 0xfe, 0xf7, - 0x05, 0xba, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x88, 0x46, 0x04, 0x46, - 0x00, 0x25, 0xc9, 0xb2, 0x48, 0x09, 0x05, 0x28, 0x01, 0xf0, 0x1f, 0x01, - 0x49, 0xda, 0x0f, 0xf2, 0xac, 0x03, 0x03, 0xeb, 0xc0, 0x02, 0x57, 0x68, - 0x00, 0x2f, 0x42, 0xd0, 0x13, 0xf8, 0x30, 0x30, 0x99, 0x42, 0x3e, 0xda, - 0x23, 0x4b, 0x53, 0xf8, 0x20, 0x60, 0x01, 0x27, 0x07, 0xfa, 0x01, 0xfe, - 0x0e, 0xea, 0x06, 0x06, 0xd3, 0xf8, 0x14, 0xe0, 0x9b, 0x69, 0x07, 0xfa, - 0x00, 0xf0, 0x00, 0xea, 0x0e, 0x00, 0x30, 0x43, 0x43, 0xea, 0x00, 0x07, - 0x50, 0x68, 0x00, 0xeb, 0xc1, 0x06, 0xfb, 0xf7, 0xc2, 0xf9, 0x04, 0x28, - 0x03, 0xd1, 0xf0, 0x88, 0x80, 0xf0, 0x01, 0x00, 0x07, 0x43, 0x00, 0x2c, - 0x1c, 0xbf, 0x00, 0x2f, 0x06, 0x25, 0x1d, 0xd1, 0x30, 0x68, 0xb1, 0x88, - 0x00, 0x28, 0x18, 0xbf, 0x00, 0x29, 0x14, 0xd0, 0x4f, 0xea, 0x08, 0x23, - 0x4f, 0xea, 0x18, 0x62, 0x02, 0xeb, 0x13, 0x46, 0xb1, 0x42, 0x0a, 0xdb, - 0x00, 0xeb, 0x13, 0x40, 0x0b, 0x4b, 0x00, 0x2c, 0x12, 0xbf, 0x19, 0x46, - 0x01, 0x46, 0x18, 0x46, 0x00, 0xf0, 0x6e, 0xfa, 0x04, 0xe0, 0x07, 0x25, - 0x02, 0xe0, 0x05, 0x25, 0x00, 0xe0, 0x04, 0x25, 0x28, 0x46, 0xbd, 0xe8, - 0xf0, 0x81, 0x02, 0x49, 0x00, 0xf0, 0x01, 0x00, 0x88, 0x61, 0x70, 0x47, - 0x14, 0x27, 0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x13, 0x00, 0x00, 0x00, - 0x00, 0x68, 0x01, 0x01, 0x08, 0x00, 0x00, 0x00, 0x68, 0x6f, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x38, 0x76, 0x01, 0x01, - 0x10, 0xb5, 0x01, 0x21, 0x15, 0x20, 0xfe, 0xf7, 0x08, 0xfc, 0x00, 0xf0, - 0x4d, 0xf8, 0x84, 0x4c, 0xf9, 0xf7, 0x47, 0xfc, 0x21, 0x7a, 0x4f, 0xf4, - 0xdb, 0x70, 0xf9, 0xf7, 0x11, 0xfc, 0x61, 0x7a, 0x80, 0x4c, 0x40, 0xf2, - 0xb7, 0x10, 0xf9, 0xf7, 0x0b, 0xfc, 0xfe, 0xf7, 0xbc, 0xfa, 0x00, 0x22, - 0x03, 0x21, 0x40, 0xf2, 0x33, 0x40, 0xf9, 0xf7, 0x0d, 0xfc, 0x00, 0x22, - 0x01, 0x21, 0x40, 0xf2, 0x4c, 0x40, 0xf9, 0xf7, 0x07, 0xfc, 0x00, 0x22, - 0x0f, 0x21, 0x40, 0xf2, 0x2e, 0x40, 0xf9, 0xf7, 0x01, 0xfc, 0x00, 0x22, - 0x03, 0x21, 0x4f, 0xf4, 0x89, 0x60, 0xf9, 0xf7, 0xfb, 0xfb, 0x21, 0x78, - 0x40, 0xf2, 0x35, 0x40, 0xf9, 0xf7, 0xec, 0xfb, 0x61, 0x7d, 0x40, 0xf2, - 0x36, 0x40, 0xf9, 0xf7, 0xe7, 0xfb, 0xff, 0xf7, 0x8e, 0xf8, 0xff, 0xf7, - 0xbc, 0xf8, 0xff, 0xf7, 0xdb, 0xf8, 0xbd, 0xe8, 0x10, 0x40, 0x04, 0x20, - 0xfc, 0xf7, 0xc2, 0xbf, 0x80, 0xb5, 0x04, 0x20, 0xfd, 0xf7, 0x00, 0xf8, - 0x00, 0xf0, 0x0a, 0xf8, 0xf9, 0xf7, 0xf2, 0xfb, 0xfe, 0xf7, 0xa0, 0xfa, - 0xbd, 0xe8, 0x04, 0x40, 0x00, 0x21, 0x15, 0x20, 0xfe, 0xf7, 0xb9, 0xbb, - 0x09, 0x22, 0x5f, 0x49, 0x0f, 0xf2, 0x78, 0x20, 0x70, 0x47, 0x2d, 0xe9, - 0xf1, 0x4f, 0xdf, 0xf8, 0x74, 0xa1, 0x5d, 0x4e, 0x5d, 0x4f, 0x82, 0xb0, - 0x9a, 0xf8, 0x00, 0x00, 0x00, 0x90, 0x00, 0x24, 0x74, 0x60, 0xb4, 0x81, - 0x03, 0x21, 0xb8, 0x7a, 0x08, 0x42, 0x06, 0xd0, 0x01, 0x20, 0x03, 0xf0, - 0x5f, 0xf8, 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x15, 0xd0, 0x78, 0x89, - 0xc0, 0xf3, 0x81, 0x00, 0x30, 0xb1, 0x00, 0x20, 0x03, 0xf0, 0x54, 0xf8, - 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x0a, 0xd0, 0x78, 0x89, 0xc0, 0xf3, - 0x82, 0x10, 0x40, 0xb1, 0x02, 0x20, 0x03, 0xf0, 0x49, 0xf8, 0x00, 0x29, - 0x08, 0xbf, 0x00, 0x28, 0x01, 0xd1, 0x05, 0x24, 0x53, 0xe0, 0x00, 0x98, - 0x20, 0x28, 0x4f, 0xd2, 0x01, 0x20, 0xff, 0xf7, 0x54, 0xff, 0x34, 0x61, - 0x00, 0x27, 0xdf, 0xf8, 0x14, 0x81, 0xdf, 0xf8, 0x14, 0x91, 0x00, 0xe0, - 0x7f, 0x1c, 0x00, 0x98, 0x87, 0x42, 0x3d, 0xd2, 0x07, 0xeb, 0x0a, 0x00, - 0x0c, 0x21, 0x40, 0x78, 0x00, 0xf0, 0x1f, 0x05, 0x0f, 0xf2, 0x00, 0x10, - 0x01, 0xfb, 0x05, 0x0b, 0xdb, 0xf8, 0x04, 0x00, 0x00, 0x28, 0xed, 0xd0, - 0x02, 0x98, 0xe8, 0x40, 0xc0, 0x07, 0xe9, 0xd5, 0x29, 0x46, 0x16, 0x20, - 0xfe, 0xf7, 0x6c, 0xfb, 0x49, 0x46, 0x04, 0x20, 0xfc, 0xf7, 0x5e, 0xff, - 0x9b, 0xf8, 0x08, 0x00, 0xfe, 0xf7, 0x66, 0xfa, 0xdb, 0xf8, 0x04, 0x20, - 0x41, 0x46, 0x00, 0x20, 0x90, 0x47, 0x04, 0x46, 0x04, 0x20, 0xfc, 0xf7, - 0x77, 0xff, 0xe4, 0xb2, 0x1c, 0xb1, 0x35, 0x73, 0x74, 0x73, 0x07, 0x24, - 0x10, 0xe0, 0x01, 0x21, 0x72, 0x68, 0xa9, 0x40, 0x0a, 0x43, 0x72, 0x60, - 0x32, 0x68, 0x11, 0x43, 0x31, 0x60, 0x31, 0x69, 0x49, 0x44, 0x08, 0x1a, - 0x30, 0x61, 0xfa, 0xf7, 0x20, 0xfe, 0x00, 0x28, 0xbe, 0xd0, 0x06, 0x24, - 0x00, 0x20, 0xff, 0xf7, 0x08, 0xff, 0x00, 0xe0, 0x04, 0x24, 0x20, 0x46, - 0xbd, 0xe8, 0xfe, 0x8f, 0x1f, 0x49, 0x01, 0x20, 0x08, 0x70, 0x70, 0x47, - 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0x19, 0x46, 0x00, 0x20, - 0xfc, 0xf7, 0xcc, 0xff, 0x00, 0x27, 0xfa, 0xf7, 0x06, 0xfe, 0x08, 0xb1, - 0x02, 0x27, 0x0d, 0xe0, 0x04, 0xf1, 0x8c, 0x40, 0x05, 0xea, 0x06, 0x01, - 0x00, 0x78, 0x28, 0x40, 0x88, 0x42, 0x05, 0xd0, 0x00, 0x20, 0xfc, 0xf7, - 0xd3, 0xff, 0x00, 0x28, 0xed, 0xd0, 0x01, 0x27, 0x00, 0x20, 0xfc, 0xf7, - 0x45, 0xff, 0x38, 0x46, 0xf2, 0xbd, 0x09, 0x48, 0x81, 0x68, 0x00, 0x68, - 0x08, 0x40, 0x88, 0x42, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, - 0x00, 0x00, 0x00, 0x00, 0x4c, 0x1f, 0x00, 0x20, 0x31, 0x04, 0x00, 0x46, - 0xfc, 0xf2, 0x00, 0x20, 0xd4, 0x28, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0x60, 0xb5, 0x00, 0x20, 0xc0, 0xe1, 0xe4, 0x00, - 0x9e, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xed, 0x52, 0x01, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x91, 0x55, 0x01, 0x01, 0x93, 0x55, 0x01, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x7d, 0x69, 0x01, 0x01, 0x7f, 0x69, 0x01, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x38, 0x01, 0x01, - 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x64, 0x01, 0x01, - 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x76, 0x01, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x11, 0x31, 0x01, 0x01, 0x13, 0x31, 0x01, 0x01, - 0xc8, 0x00, 0x00, 0x00, 0x6d, 0x75, 0x00, 0x01, 0x81, 0x75, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x5d, 0x17, 0x00, 0x01, 0xc9, 0x13, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, 0x15, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0xb7, 0x58, 0x01, 0x01, 0xf7, 0x58, 0x01, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x95, 0x5b, 0x01, 0x01, 0x8b, 0x5c, 0x01, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x91, 0x5d, 0x01, 0x01, 0xd5, 0x5d, 0x01, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xf9, 0x5c, 0x01, 0x01, 0xa5, 0x5d, 0x01, 0x01, - 0xc8, 0x00, 0x00, 0x00, 0xd9, 0xdb, 0x00, 0x01, 0x31, 0xdc, 0x00, 0x01, - 0xf8, 0x00, 0x00, 0x00, 0xbd, 0xa5, 0x00, 0x01, 0x1d, 0xa6, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0xe5, 0x60, 0x00, 0x01, 0x15, 0x61, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x4b, 0x34, 0x00, 0x01, 0x4d, 0x34, 0x00, 0x01, - 0x38, 0x00, 0x00, 0x00, 0x2e, 0x04, 0x33, 0x04, 0x35, 0x04, 0x36, 0x04, - 0x48, 0x04, 0x4c, 0x04, 0x5b, 0x04, 0x5c, 0x04, 0x5d, 0x04, 0x00, 0x00, - 0x30, 0xb5, 0x04, 0x46, 0x4a, 0x4d, 0x87, 0xb0, 0x08, 0x21, 0x28, 0x1d, - 0xf8, 0xf7, 0x0f, 0xfd, 0x28, 0x60, 0x00, 0xb1, 0x01, 0x20, 0xfe, 0xf7, - 0x8e, 0xf9, 0x03, 0x21, 0x04, 0x91, 0x00, 0xf0, 0x24, 0xf8, 0x05, 0xaa, - 0x0f, 0xf2, 0x10, 0x11, 0x16, 0x20, 0xf8, 0xf7, 0x97, 0xff, 0x00, 0x20, - 0x12, 0xe0, 0x30, 0xb5, 0x87, 0xb0, 0x03, 0x21, 0x04, 0x91, 0x04, 0x46, - 0x00, 0xf0, 0x15, 0xf8, 0x00, 0xf0, 0x0d, 0xf8, 0x05, 0xaa, 0x0f, 0xf2, - 0x00, 0x11, 0x16, 0x20, 0xf8, 0xf7, 0x86, 0xff, 0x00, 0x2d, 0x0c, 0xbf, - 0x00, 0x20, 0x02, 0x20, 0x20, 0x70, 0x07, 0xb0, 0x30, 0xbd, 0x05, 0x46, - 0x40, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0xfe, 0xf7, 0x66, 0xb9, 0x00, 0x21, - 0x03, 0x91, 0x4f, 0xf4, 0x20, 0x71, 0x02, 0x91, 0x16, 0x21, 0x2f, 0x48, - 0x01, 0x90, 0x00, 0x91, 0x00, 0xf6, 0xfc, 0x12, 0x16, 0x23, 0x00, 0x21, - 0x0f, 0xf2, 0x39, 0x00, 0xf8, 0xf7, 0xb1, 0xbe, 0x38, 0xb5, 0x04, 0x46, - 0x00, 0x20, 0xfe, 0xf7, 0x1d, 0xfb, 0x03, 0x20, 0xfe, 0xf7, 0x1a, 0xfb, - 0x24, 0x48, 0x00, 0x68, 0xf8, 0xf7, 0x00, 0xfd, 0xff, 0xf7, 0xdc, 0xff, - 0x16, 0x20, 0xf8, 0xf7, 0xe7, 0xfe, 0xff, 0xf7, 0xd6, 0xff, 0x00, 0x2d, - 0x0c, 0xbf, 0x00, 0x20, 0x02, 0x20, 0x20, 0x70, 0x31, 0xbd, 0x00, 0x00, - 0x38, 0xb5, 0x1b, 0x4c, 0x23, 0xe0, 0xfe, 0xf7, 0x36, 0xf9, 0x00, 0x20, - 0xfe, 0xf7, 0xe2, 0xfa, 0x00, 0x20, 0xf9, 0xf7, 0x7f, 0xfe, 0x01, 0x28, - 0x19, 0xd0, 0x29, 0x0e, 0x0c, 0x20, 0xfe, 0xf7, 0x0d, 0xfa, 0x01, 0x21, - 0x0b, 0x20, 0xfe, 0xf7, 0xfa, 0xf9, 0x00, 0x20, 0xf9, 0xf7, 0x87, 0xfd, - 0x01, 0x00, 0x0c, 0xd0, 0x48, 0x68, 0xc9, 0x68, 0x88, 0x47, 0x00, 0x21, - 0x0b, 0x20, 0xfe, 0xf7, 0xee, 0xf9, 0x00, 0x20, 0xf9, 0xf7, 0xe0, 0xfd, - 0x00, 0x20, 0xfe, 0xf7, 0xe1, 0xfa, 0x00, 0x20, 0xfe, 0xf7, 0xde, 0xfa, - 0x20, 0x68, 0x6a, 0x46, 0x00, 0x21, 0xf8, 0xf7, 0xd2, 0xfc, 0x00, 0x68, - 0x05, 0x04, 0xc0, 0xb2, 0x07, 0x28, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0xcb, 0xe7, 0x00, 0x00, 0x88, 0xf2, 0x00, 0x20, 0x68, 0x2c, 0x00, 0x20, - 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, 0x54, 0x61, 0x73, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x41, 0x6e, 0x61, 0x6c, 0x79, 0x73, 0x69, 0x73, - 0x54, 0x73, 0x6b, 0x00, 0x62, 0xb3, 0x8b, 0x07, 0x08, 0xd0, 0x52, 0x1e, - 0x11, 0xf8, 0x01, 0x3b, 0x00, 0xf8, 0x01, 0x3b, 0x00, 0xf0, 0x24, 0x80, - 0x8b, 0x07, 0xf6, 0xd1, 0x83, 0x07, 0x40, 0xf0, 0x20, 0x80, 0x00, 0xbf, - 0x10, 0x3a, 0x07, 0xd3, 0x30, 0xb4, 0xb1, 0xe8, 0x38, 0x10, 0x10, 0x3a, - 0xa0, 0xe8, 0x38, 0x10, 0xf9, 0xd2, 0x30, 0xbc, 0x53, 0x07, 0x24, 0xbf, - 0xb1, 0xe8, 0x08, 0x10, 0xa0, 0xe8, 0x08, 0x10, 0x44, 0xbf, 0x51, 0xf8, - 0x04, 0x3b, 0x40, 0xf8, 0x04, 0x3b, 0xd2, 0x07, 0x24, 0xbf, 0x31, 0xf8, - 0x02, 0x2b, 0x20, 0xf8, 0x02, 0x2b, 0x44, 0xbf, 0x0b, 0x78, 0x03, 0x70, - 0x70, 0x47, 0x08, 0x3a, 0x07, 0xd3, 0xb1, 0xe8, 0x08, 0x10, 0x08, 0x3a, - 0x40, 0xf8, 0x04, 0x3b, 0x40, 0xf8, 0x04, 0xcb, 0xf7, 0xd2, 0x53, 0x07, - 0xe4, 0xe7, 0x00, 0x00, 0x80, 0xb5, 0x30, 0x48, 0x4f, 0xf0, 0x80, 0x71, - 0x01, 0x63, 0xc2, 0x6b, 0x42, 0xf0, 0x80, 0x72, 0xc2, 0x63, 0x01, 0x60, - 0x20, 0x20, 0x01, 0x21, 0xfe, 0xf7, 0x07, 0xf9, 0x20, 0x20, 0xfe, 0xf7, - 0xe9, 0xf8, 0xbd, 0xe8, 0x02, 0x40, 0x20, 0x20, 0xfe, 0xf7, 0xea, 0xb8, - 0x2d, 0xe9, 0xf0, 0x41, 0x82, 0xb0, 0x00, 0x24, 0x00, 0x25, 0x24, 0x4e, - 0x06, 0xeb, 0xc5, 0x07, 0xd7, 0xf8, 0x08, 0x80, 0x0e, 0xe0, 0x30, 0x68, - 0x64, 0x1c, 0x84, 0x42, 0x05, 0xd3, 0x71, 0x68, 0xb0, 0x69, 0x6a, 0x46, - 0xf8, 0xf7, 0x68, 0xfd, 0x00, 0x24, 0x40, 0x46, 0x00, 0xf0, 0x0a, 0xf8, - 0x08, 0xf1, 0x04, 0x08, 0xf8, 0x68, 0x80, 0x45, 0xed, 0xd3, 0x6d, 0x1c, - 0x02, 0x2d, 0xe5, 0xd3, 0xbd, 0xe8, 0xf3, 0x81, 0x80, 0xb5, 0x72, 0xb6, - 0x15, 0x48, 0x16, 0x49, 0x01, 0x60, 0x00, 0x21, 0x01, 0x60, 0x62, 0xb6, - 0x00, 0x22, 0xf0, 0x21, 0x40, 0xf6, 0x59, 0x40, 0xf9, 0xf7, 0x60, 0xf9, - 0xbd, 0xe8, 0x08, 0x40, 0x00, 0x22, 0xf0, 0x21, 0x40, 0xf6, 0x51, 0x40, - 0xf9, 0xf7, 0x58, 0xb9, 0x80, 0xb5, 0xff, 0xf7, 0xaf, 0xff, 0x00, 0x22, - 0x02, 0x21, 0x4f, 0xf4, 0x45, 0x60, 0xf9, 0xf7, 0x4f, 0xf9, 0x00, 0x20, - 0xf8, 0xf7, 0x10, 0xfd, 0x04, 0x49, 0x88, 0x61, 0x01, 0xbd, 0x03, 0x48, - 0x80, 0x69, 0xf8, 0xf7, 0x8d, 0xbd, 0x00, 0x00, 0x10, 0x00, 0x00, 0x58, - 0x30, 0x1f, 0x00, 0x20, 0x48, 0x00, 0x00, 0x50, 0x00, 0x00, 0xab, 0xab, - 0x00, 0x20, 0xfe, 0xf7, 0x48, 0xb8, 0x00, 0x00, 0x0f, 0x28, 0xb4, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x70, 0x47, 0x70, 0xb5, 0x00, 0xf0, 0x12, 0xf8, - 0x2c, 0x43, 0x1c, 0x60, 0x02, 0xeb, 0x40, 0x00, 0x01, 0x23, 0x07, 0xe0, - 0x70, 0xb5, 0x00, 0xf0, 0x09, 0xf8, 0xac, 0x43, 0x1c, 0x60, 0x02, 0xeb, - 0x40, 0x00, 0x00, 0x23, 0x43, 0x70, 0x81, 0xf3, 0x10, 0x88, 0x70, 0xbd, - 0xef, 0xf3, 0x10, 0x81, 0x72, 0xb6, 0x1d, 0x4b, 0x1d, 0x4a, 0x1c, 0x68, - 0x12, 0xf9, 0x10, 0x60, 0x01, 0x25, 0xb5, 0x40, 0x70, 0x47, 0x0f, 0xf2, - 0x78, 0x02, 0x19, 0x49, 0x82, 0x5c, 0x52, 0xb9, 0x11, 0xf8, 0x10, 0x00, - 0x17, 0x49, 0xc2, 0x08, 0x00, 0xf0, 0x07, 0x00, 0x51, 0x5c, 0xc1, 0x40, - 0x01, 0xf0, 0x01, 0x00, 0x70, 0x47, 0x01, 0xeb, 0x40, 0x00, 0x40, 0x78, - 0x70, 0x47, 0x38, 0xb5, 0x0f, 0x4b, 0x03, 0xeb, 0x40, 0x03, 0xef, 0xf3, - 0x10, 0x84, 0x72, 0xb6, 0x0f, 0xf2, 0x40, 0x05, 0x45, 0x5d, 0x01, 0x2d, - 0x0a, 0xd1, 0x02, 0xb9, 0x13, 0x21, 0x19, 0x70, 0x59, 0x78, 0x11, 0xb1, - 0xff, 0xf7, 0xb9, 0xff, 0x03, 0xe0, 0xff, 0xf7, 0xbf, 0xff, 0x00, 0xe0, - 0x19, 0x70, 0x84, 0xf3, 0x10, 0x88, 0x31, 0xbd, 0x02, 0x49, 0x11, 0xf8, - 0x10, 0x00, 0x70, 0x47, 0x18, 0x00, 0x00, 0x49, 0xb4, 0x28, 0x00, 0x20, - 0x26, 0x0b, 0x00, 0x46, 0x0f, 0xf2, 0x04, 0x01, 0x40, 0x5c, 0x70, 0x47, - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, - 0x11, 0x88, 0x70, 0x47, 0xdf, 0xf8, 0x9c, 0x06, 0x00, 0x78, 0x00, 0xf0, - 0x02, 0x00, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xff, 0xf7, - 0xef, 0xff, 0x00, 0x22, 0x00, 0x23, 0xc5, 0xe9, 0x02, 0x23, 0xc5, 0xe9, - 0x04, 0x23, 0xc5, 0xe9, 0x06, 0x23, 0x00, 0x21, 0xca, 0x00, 0xdf, 0xf8, - 0x78, 0x56, 0xab, 0x50, 0x49, 0x1c, 0xdf, 0xf8, 0x74, 0x56, 0xab, 0x50, - 0x16, 0x29, 0xf5, 0xd3, 0xa1, 0x00, 0xdf, 0xf8, 0x6c, 0x26, 0x41, 0xf0, - 0x01, 0x01, 0x11, 0x60, 0x16, 0xe0, 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0xff, 0xf7, 0xd0, 0xff, 0xdf, 0xf8, 0x58, 0x26, 0x24, 0xb9, 0xdf, 0xf8, - 0x58, 0x36, 0x1c, 0x68, 0x12, 0x78, 0x03, 0xe0, 0xdf, 0xf8, 0x50, 0x36, - 0x1c, 0x68, 0x52, 0x78, 0x24, 0xf0, 0x02, 0x04, 0x44, 0xea, 0x45, 0x01, - 0x11, 0x43, 0x19, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x31, 0xbd, 0x7f, 0xb5, - 0x0a, 0xb1, 0x00, 0xf5, 0x80, 0x70, 0x40, 0xf2, 0xfc, 0x72, 0x02, 0xea, - 0x80, 0x00, 0x40, 0xf0, 0x02, 0x00, 0x00, 0x22, 0x03, 0xeb, 0x82, 0x05, - 0x33, 0xf8, 0x22, 0x60, 0xb5, 0xf9, 0x02, 0x50, 0x46, 0xea, 0x05, 0x45, - 0x4d, 0xf8, 0x22, 0x50, 0x52, 0x1c, 0x04, 0x2a, 0xf2, 0xdb, 0x03, 0x9a, - 0x02, 0x9b, 0x01, 0x9c, 0x00, 0x29, 0x0c, 0xbf, 0xdf, 0xf8, 0x00, 0x16, - 0xdf, 0xf8, 0x00, 0x16, 0x00, 0x9d, 0x4d, 0x60, 0x8c, 0x60, 0xcb, 0x60, - 0x0a, 0x61, 0x08, 0x60, 0x7f, 0xbd, 0x7f, 0xb5, 0x04, 0x46, 0x68, 0x46, - 0x10, 0x21, 0xfd, 0xf7, 0xbf, 0xfd, 0x4f, 0xf4, 0x00, 0x50, 0xad, 0xf8, - 0x00, 0x00, 0x00, 0x25, 0x00, 0x26, 0x86, 0xf0, 0x01, 0x01, 0xc9, 0xb2, - 0xe0, 0xb2, 0xff, 0xf7, 0xac, 0xff, 0x6b, 0x46, 0x32, 0x46, 0x21, 0x46, - 0x28, 0x46, 0xff, 0xf7, 0xc0, 0xff, 0x76, 0x1c, 0x02, 0x2e, 0xf0, 0xd3, - 0x6d, 0x1c, 0xff, 0x2d, 0xec, 0xd9, 0x7f, 0xbd, 0xc0, 0x0b, 0x00, 0x21, - 0x00, 0xfa, 0x01, 0xf2, 0x12, 0x05, 0x03, 0xd4, 0x49, 0x1c, 0xc9, 0xb2, - 0x07, 0x29, 0xf7, 0xdb, 0xc1, 0xf1, 0x07, 0x01, 0xc9, 0xb2, 0x00, 0x29, - 0x14, 0xbf, 0x4a, 0x1e, 0x00, 0x22, 0xd0, 0x40, 0x00, 0xf0, 0x1f, 0x00, - 0x40, 0xea, 0x41, 0x10, 0x70, 0x47, 0x41, 0x09, 0x05, 0xd0, 0x00, 0xf0, - 0x1f, 0x00, 0x40, 0xf0, 0x20, 0x00, 0x4a, 0x1e, 0x90, 0x40, 0x02, 0x29, - 0x04, 0xdb, 0x01, 0x22, 0x89, 0x1e, 0x02, 0xfa, 0x01, 0xf1, 0x08, 0x43, - 0x70, 0x47, 0x10, 0xb5, 0x02, 0x46, 0x0b, 0x46, 0x14, 0x68, 0x18, 0x46, - 0x21, 0x46, 0xfc, 0xf7, 0xb5, 0xfe, 0x38, 0xbf, 0x1c, 0x46, 0x83, 0xf0, - 0x00, 0x43, 0x20, 0x46, 0x19, 0x46, 0xfc, 0xf7, 0xad, 0xfe, 0x38, 0xbf, - 0x1c, 0x46, 0x14, 0x60, 0x10, 0xbd, 0x2d, 0xe9, 0xf7, 0x4f, 0x8e, 0xb0, - 0x9a, 0x46, 0x1a, 0x9c, 0xdf, 0xf8, 0x34, 0xb5, 0x00, 0x26, 0x4f, 0xf0, - 0x8c, 0x48, 0x0d, 0xf1, 0x14, 0x09, 0xf0, 0xb2, 0xff, 0xf7, 0xcd, 0xff, - 0x80, 0x03, 0x01, 0xf0, 0x2d, 0xf8, 0x01, 0x46, 0x0e, 0x9a, 0x00, 0x94, - 0x53, 0x46, 0x05, 0xa8, 0x01, 0xf0, 0x92, 0xfb, 0x00, 0x25, 0x59, 0xf8, - 0x35, 0x00, 0x41, 0x46, 0xfc, 0xf7, 0x9c, 0xfe, 0x49, 0xf8, 0x35, 0x00, - 0x41, 0x46, 0x05, 0xa8, 0x00, 0xeb, 0xc5, 0x07, 0x78, 0x68, 0xfc, 0xf7, - 0x93, 0xfe, 0x78, 0x60, 0x59, 0x46, 0x38, 0x46, 0xff, 0xf7, 0xbf, 0xff, - 0x59, 0x46, 0x38, 0x1d, 0xff, 0xf7, 0xbb, 0xff, 0x59, 0xf8, 0x35, 0x00, - 0xfc, 0xf7, 0xf2, 0xfe, 0x01, 0xa9, 0x21, 0xf8, 0x25, 0x00, 0x78, 0x68, - 0xfc, 0xf7, 0xec, 0xfe, 0x01, 0xa9, 0x01, 0xeb, 0x85, 0x01, 0x6d, 0x1c, - 0x04, 0x2d, 0x48, 0x80, 0xd7, 0xd3, 0x10, 0x9a, 0x0f, 0x99, 0x01, 0xab, - 0x30, 0x46, 0xff, 0xf7, 0x36, 0xff, 0x76, 0x1c, 0xff, 0x2e, 0xc0, 0xd9, - 0x11, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x10, 0xb5, 0x04, 0x00, 0x0c, 0xbf, - 0xdf, 0xf8, 0xa0, 0x24, 0xdf, 0xf8, 0xa0, 0x24, 0xc8, 0xb2, 0x10, 0x60, - 0x08, 0x1d, 0xdf, 0xf8, 0x9c, 0x14, 0xdf, 0xf8, 0x9c, 0x24, 0x89, 0x6b, - 0x52, 0x69, 0xa1, 0xfb, 0x00, 0x01, 0x00, 0x23, 0xfd, 0xf7, 0xc8, 0xf9, - 0xdf, 0xf8, 0x8c, 0x14, 0x40, 0x1c, 0x41, 0xf8, 0x24, 0x00, 0x10, 0xbd, - 0xf8, 0xb5, 0x00, 0x88, 0x00, 0x0a, 0x0c, 0x46, 0x80, 0xf0, 0x02, 0x00, - 0x59, 0x00, 0xc0, 0x00, 0x01, 0xf0, 0x02, 0x01, 0x00, 0xf0, 0x18, 0x00, - 0x08, 0x43, 0x15, 0x46, 0x40, 0xf0, 0x01, 0x07, 0xff, 0xf7, 0xbe, 0xfe, - 0x06, 0x46, 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xce, 0xff, 0xdf, 0xf8, - 0x2c, 0x04, 0x1c, 0xb9, 0x00, 0x78, 0xdf, 0xf8, 0x28, 0x14, 0x02, 0xe0, - 0x40, 0x78, 0xdf, 0xf8, 0x24, 0x14, 0x38, 0x43, 0x08, 0x60, 0x86, 0xf3, - 0x11, 0x88, 0xf1, 0xbd, 0xf8, 0xb5, 0x07, 0x00, 0x0c, 0x46, 0x1a, 0xbf, - 0x00, 0x20, 0xdf, 0xf8, 0x30, 0x14, 0xdf, 0xf8, 0x30, 0x14, 0x15, 0x46, - 0x08, 0x60, 0x1e, 0x46, 0xdf, 0xf8, 0x1c, 0x04, 0x50, 0xf8, 0x27, 0x00, - 0xfc, 0xf7, 0x91, 0xfb, 0xc7, 0xb1, 0x00, 0x20, 0xb0, 0x42, 0x2e, 0xda, - 0x41, 0x42, 0xc9, 0x00, 0xdf, 0xf8, 0x10, 0x24, 0x00, 0xf0, 0x31, 0xf8, - 0xdf, 0xf8, 0x0c, 0x24, 0x52, 0x58, 0xd2, 0x08, 0x5a, 0x80, 0xdf, 0xf8, - 0x08, 0x24, 0x52, 0x58, 0xd2, 0x08, 0x25, 0xf8, 0x20, 0x20, 0xdf, 0xf8, - 0x00, 0x24, 0x00, 0xf0, 0x1b, 0xf8, 0xe7, 0xe7, 0x00, 0x20, 0x14, 0xe0, - 0x41, 0x42, 0xc9, 0x00, 0xdf, 0xf8, 0xf0, 0x23, 0x00, 0xf0, 0x19, 0xf8, - 0xdf, 0xf8, 0xec, 0x23, 0x52, 0x58, 0xd2, 0x08, 0x5a, 0x80, 0xdf, 0xf8, - 0xe8, 0x23, 0x52, 0x58, 0xd2, 0x08, 0x25, 0xf8, 0x20, 0x20, 0xdf, 0xf8, - 0xe0, 0x23, 0x00, 0xf0, 0x03, 0xf8, 0xb0, 0x42, 0xe8, 0xdb, 0xf1, 0xbd, - 0x51, 0x58, 0x05, 0xeb, 0x80, 0x02, 0xc9, 0x08, 0x51, 0x80, 0x40, 0x1c, - 0x70, 0x47, 0x52, 0x58, 0xd2, 0x08, 0x24, 0xf8, 0x20, 0x20, 0x04, 0xeb, - 0x80, 0x03, 0x70, 0x47, 0xf8, 0xb5, 0x06, 0x46, 0x0c, 0x46, 0x15, 0x46, - 0x1f, 0x46, 0xff, 0xf7, 0x4f, 0xfe, 0x00, 0x21, 0xca, 0x00, 0x56, 0xf8, - 0x31, 0x30, 0xdf, 0xf8, 0x44, 0xc3, 0x4c, 0xf8, 0x02, 0x30, 0x06, 0xeb, - 0xc1, 0x03, 0xdf, 0xf8, 0x3c, 0xc3, 0x5b, 0x68, 0x4c, 0xf8, 0x02, 0x30, - 0x49, 0x1c, 0x15, 0x29, 0xee, 0xd3, 0xdf, 0xf8, 0x88, 0x13, 0x0c, 0x60, - 0x4d, 0x60, 0x3f, 0x06, 0x06, 0x99, 0x3a, 0x0d, 0x02, 0xf0, 0xf0, 0x02, - 0x42, 0xea, 0x81, 0x01, 0xc6, 0x4a, 0x41, 0xf0, 0x03, 0x01, 0x11, 0x60, - 0x80, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x00, 0x21, - 0x00, 0x20, 0xf9, 0xf7, 0x3e, 0xf9, 0x20, 0x69, 0x04, 0xf1, 0xbc, 0x01, - 0x00, 0xf0, 0x21, 0xf8, 0x05, 0x00, 0x07, 0xd1, 0x21, 0x68, 0x20, 0x69, - 0x00, 0xf0, 0x76, 0xf8, 0x20, 0x69, 0x00, 0xf0, 0x58, 0xf8, 0x05, 0x46, - 0x20, 0x69, 0xfc, 0xf7, 0xe9, 0xf9, 0x28, 0x46, 0x32, 0xbd, 0x10, 0xb5, - 0x04, 0x46, 0xf9, 0xf7, 0x15, 0xfc, 0x03, 0x28, 0x06, 0xd1, 0x04, 0xf0, - 0x1b, 0xf9, 0x00, 0x21, 0x04, 0xf1, 0xbc, 0x00, 0xfb, 0xf7, 0x15, 0xf9, - 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x20, 0xf9, 0xf7, 0x75, 0xb9, 0x2d, 0xe9, - 0xf0, 0x41, 0x04, 0x46, 0x88, 0x46, 0xf9, 0xf7, 0x01, 0xfc, 0x00, 0x26, - 0x03, 0x28, 0x25, 0xd1, 0xe0, 0xb2, 0xf9, 0xf7, 0x35, 0xfc, 0x05, 0x46, - 0x40, 0x46, 0xfb, 0xf7, 0xee, 0xf8, 0x00, 0x2d, 0x48, 0xbf, 0x14, 0x26, - 0x20, 0xd4, 0x28, 0x46, 0xfb, 0xf7, 0x0f, 0xf9, 0xfb, 0xf7, 0x41, 0xf9, - 0xfb, 0xf7, 0x2c, 0xf9, 0x01, 0x2d, 0x0c, 0xd1, 0x03, 0x27, 0x02, 0x20, - 0x04, 0xf0, 0x98, 0xf8, 0xb3, 0x48, 0xb0, 0xf8, 0x54, 0x10, 0x20, 0x46, - 0xfa, 0xf7, 0xc3, 0xfb, 0x60, 0xb1, 0x13, 0x26, 0x0a, 0xe0, 0x02, 0x27, - 0x00, 0x2d, 0xf0, 0xd1, 0x01, 0x20, 0xef, 0xe7, 0xf9, 0xf7, 0xd6, 0xfb, - 0x02, 0x28, 0x0c, 0xbf, 0x03, 0x27, 0x02, 0x27, 0xf8, 0xb2, 0xfa, 0xf7, - 0xd9, 0xf9, 0x18, 0xb9, 0xf9, 0xf7, 0x4b, 0xfc, 0x00, 0xb9, 0x0c, 0x26, - 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x38, 0xb5, 0x04, 0x46, 0x01, 0x20, - 0xa0, 0x40, 0xf8, 0xf7, 0xe7, 0xfe, 0x00, 0x25, 0x08, 0xb9, 0x02, 0x25, - 0x0a, 0xe0, 0x04, 0x20, 0xf8, 0xf7, 0xd2, 0xfe, 0x08, 0xb9, 0x01, 0x25, - 0x04, 0xe0, 0xe0, 0xb2, 0xfb, 0xf7, 0x5d, 0xfa, 0x00, 0xb1, 0x11, 0x25, - 0xfa, 0xf7, 0x41, 0xf9, 0x00, 0xb1, 0x00, 0x25, 0x28, 0x46, 0x32, 0xbd, - 0x10, 0xb5, 0x0c, 0x46, 0x21, 0x78, 0x09, 0x04, 0x01, 0xf4, 0xfe, 0x01, - 0x41, 0xea, 0x80, 0x70, 0x40, 0xf0, 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, - 0xfb, 0xf7, 0x27, 0xfc, 0x60, 0x78, 0xbd, 0xe8, 0x10, 0x40, 0xfb, 0xf7, - 0x45, 0xbc, 0x38, 0xb5, 0x04, 0x46, 0xf7, 0xf7, 0xf1, 0xfc, 0x20, 0x68, - 0xc0, 0x78, 0x80, 0xf0, 0x01, 0x05, 0xa0, 0x68, 0x20, 0x30, 0x2a, 0x46, - 0x01, 0x79, 0x00, 0x91, 0x03, 0x68, 0x21, 0x69, 0x04, 0xf1, 0x14, 0x00, - 0xff, 0xf7, 0x45, 0xfe, 0x20, 0x68, 0x02, 0x78, 0x21, 0x69, 0xa0, 0x68, - 0x2b, 0x46, 0xff, 0xf7, 0xa7, 0xfe, 0x20, 0x68, 0xc5, 0x70, 0xbd, 0xe8, - 0x31, 0x40, 0xf7, 0xf7, 0xea, 0xbc, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, - 0x4f, 0xf4, 0xd4, 0x70, 0x00, 0xfb, 0x08, 0xf5, 0x7a, 0x4e, 0xdf, 0xf8, - 0xec, 0x91, 0xaf, 0x19, 0xf8, 0x78, 0x80, 0xf0, 0x01, 0x04, 0x09, 0xf1, - 0x20, 0x00, 0x22, 0x46, 0x01, 0x79, 0x03, 0x68, 0x00, 0x91, 0x07, 0xf1, - 0x28, 0x00, 0x41, 0x46, 0xff, 0xf7, 0x1f, 0xfe, 0xaa, 0x5d, 0x23, 0x46, - 0x41, 0x46, 0x48, 0x46, 0xff, 0xf7, 0x82, 0xfe, 0xfc, 0x70, 0xbd, 0xe8, - 0xf1, 0x83, 0x10, 0xb5, 0xcb, 0x07, 0x55, 0x4a, 0x0d, 0xd5, 0x55, 0x4b, - 0x28, 0xb1, 0x04, 0x24, 0x14, 0x70, 0x1c, 0x68, 0x44, 0xf0, 0x04, 0x04, - 0x04, 0xe0, 0x00, 0x24, 0x14, 0x70, 0x1c, 0x68, 0x24, 0xf0, 0x04, 0x04, - 0x1c, 0x60, 0x89, 0x07, 0x0c, 0xd5, 0x4e, 0x49, 0x28, 0xb1, 0x04, 0x20, - 0x50, 0x70, 0x08, 0x68, 0x40, 0xf0, 0x04, 0x00, 0x03, 0xe0, 0x50, 0x70, - 0x08, 0x68, 0x20, 0xf0, 0x04, 0x00, 0x08, 0x60, 0x10, 0xbd, 0xf8, 0xb5, - 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0x1f, 0x46, 0x21, 0x46, 0x30, 0x46, - 0xff, 0xf7, 0x30, 0xfd, 0x20, 0x88, 0x00, 0x90, 0x4f, 0xf4, 0xd4, 0x71, - 0x20, 0x46, 0xfd, 0xf7, 0x4f, 0xfb, 0xbd, 0xf8, 0x00, 0x00, 0x20, 0x80, - 0x4f, 0xf2, 0xff, 0x71, 0x38, 0x88, 0x08, 0x40, 0xa0, 0x80, 0x04, 0xf5, - 0xce, 0x70, 0x39, 0x6a, 0x01, 0x60, 0x97, 0xf8, 0x24, 0x10, 0x01, 0x71, - 0x30, 0x46, 0xff, 0xf7, 0x78, 0xfd, 0x00, 0x20, 0xe0, 0x70, 0x00, 0x21, - 0xf0, 0xb2, 0xff, 0xf7, 0x30, 0xfd, 0x00, 0x20, 0x28, 0x85, 0x68, 0x85, - 0xf1, 0xbd, 0x46, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x10, - 0x90, 0xf8, 0xa1, 0x01, 0x00, 0xb1, 0x01, 0x20, 0x70, 0x47, 0x41, 0x4a, - 0x4f, 0xf4, 0xd4, 0x73, 0x03, 0xfb, 0x00, 0x20, 0x80, 0xf8, 0xa1, 0x11, - 0x70, 0x47, 0x3d, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x11, - 0x01, 0xf1, 0xe0, 0x00, 0x28, 0x31, 0xb8, 0x22, 0xff, 0xf7, 0xe0, 0xbb, - 0x70, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x36, 0x48, 0x4f, 0xf4, 0xd4, 0x71, - 0x01, 0xfb, 0x04, 0x06, 0x00, 0x20, 0x86, 0xf8, 0xa1, 0x01, 0x28, 0x07, - 0x03, 0xd5, 0x31, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xdf, 0xfc, 0x68, 0x07, - 0x04, 0xd5, 0xb8, 0x21, 0x06, 0xf1, 0x28, 0x00, 0xf8, 0xf7, 0x52, 0xfd, - 0xe8, 0x07, 0x08, 0xd5, 0x2c, 0x48, 0x2b, 0x4b, 0x94, 0x21, 0x01, 0xfb, - 0x04, 0x01, 0x22, 0x46, 0x30, 0x46, 0xff, 0xf7, 0x94, 0xff, 0xa8, 0x07, - 0x0a, 0xd5, 0x06, 0xf1, 0x28, 0x00, 0x06, 0xf1, 0xe0, 0x01, 0xb8, 0x22, - 0xff, 0xf7, 0xb4, 0xfb, 0x20, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x42, 0xe7, - 0x70, 0xbd, 0x1f, 0x49, 0x4f, 0xf4, 0xd4, 0x72, 0x02, 0xfb, 0x00, 0x10, - 0x80, 0x78, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, 0x10, 0x09, 0x00, 0x46, - 0x08, 0x00, 0x60, 0x59, 0x0c, 0x00, 0x60, 0x59, 0x00, 0x00, 0x60, 0x59, - 0x98, 0xf3, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, - 0x04, 0x00, 0x40, 0x59, 0x04, 0x00, 0x50, 0x59, 0x00, 0xfc, 0x7f, 0x46, - 0x18, 0x00, 0x40, 0x59, 0x18, 0x00, 0x50, 0x59, 0x00, 0xf2, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0x38, 0xf3, 0x00, 0x20, 0x1c, 0x00, 0x50, 0x59, - 0x1c, 0x00, 0x40, 0x59, 0x4c, 0x00, 0x50, 0x59, 0x50, 0x00, 0x50, 0x59, - 0x8c, 0x00, 0x50, 0x59, 0x90, 0x00, 0x50, 0x59, 0x4c, 0x00, 0x40, 0x59, - 0x50, 0x00, 0x40, 0x59, 0x8c, 0x00, 0x40, 0x59, 0x90, 0x00, 0x40, 0x59, - 0xb0, 0x00, 0x60, 0x59, 0x4c, 0x1f, 0x00, 0x20, 0x10, 0xb2, 0x00, 0x20, - 0x30, 0x27, 0x00, 0x20, 0x74, 0x27, 0x00, 0x20, 0x2d, 0xe9, 0xf8, 0x43, - 0xdf, 0xf8, 0x88, 0x8a, 0x88, 0x21, 0x40, 0x46, 0xfd, 0xf7, 0x98, 0xfa, - 0x00, 0x25, 0x0f, 0xf6, 0x4d, 0x29, 0xdf, 0xf8, 0x7c, 0x7a, 0xd4, 0x20, - 0x00, 0xfb, 0x05, 0xf4, 0x44, 0x20, 0xe5, 0x53, 0x00, 0xfb, 0x05, 0x86, - 0x6f, 0xf0, 0xc7, 0x00, 0x70, 0x61, 0xf8, 0xf7, 0xa1, 0xfa, 0x70, 0x63, - 0x00, 0x21, 0xdf, 0xf8, 0x60, 0x0a, 0x28, 0x18, 0x4b, 0x46, 0x81, 0x70, - 0x01, 0x71, 0x01, 0x22, 0xe9, 0xb2, 0x02, 0x20, 0xf8, 0xf7, 0x38, 0xfe, - 0xe0, 0x19, 0x00, 0xf0, 0xb7, 0xfc, 0x6d, 0x1c, 0x02, 0x2d, 0xe0, 0xd3, - 0xbd, 0xe8, 0xf1, 0x43, 0xf8, 0xf7, 0xdc, 0xbe, 0x2d, 0xe9, 0xf0, 0x43, - 0xdf, 0xf8, 0x34, 0x0a, 0xdf, 0xf8, 0x24, 0x9a, 0xdf, 0xf8, 0x30, 0x7a, - 0x89, 0xb0, 0x80, 0x7a, 0x00, 0xf0, 0x03, 0x08, 0xff, 0xf7, 0xc2, 0xff, - 0x00, 0x24, 0x00, 0x25, 0x28, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x3d, 0xd5, - 0xdf, 0xf8, 0x08, 0x0a, 0x01, 0x95, 0xd4, 0x21, 0x01, 0xfb, 0x05, 0x00, - 0xdf, 0xf8, 0x0c, 0x1a, 0x02, 0x91, 0x03, 0x97, 0x44, 0x21, 0x01, 0xfb, - 0x05, 0x91, 0x04, 0x91, 0x08, 0x90, 0x00, 0xf1, 0xd0, 0x06, 0x05, 0x80, - 0x00, 0x21, 0x31, 0x70, 0x71, 0x70, 0x00, 0xf0, 0x85, 0xfc, 0x01, 0xa8, - 0x00, 0xf0, 0x89, 0xfc, 0x04, 0x00, 0x09, 0xd1, 0x02, 0x98, 0x00, 0x96, - 0xb0, 0xf9, 0x02, 0x20, 0x01, 0x88, 0x03, 0x1d, 0x01, 0x98, 0xfd, 0xf7, - 0xde, 0xf8, 0x04, 0x46, 0x01, 0xa8, 0x00, 0xf0, 0xad, 0xfc, 0x14, 0xb9, - 0x30, 0x78, 0x5a, 0x28, 0x05, 0xda, 0x04, 0x98, 0x3c, 0x30, 0x00, 0x21, - 0xc1, 0x80, 0x81, 0x80, 0x0d, 0xe0, 0x04, 0x98, 0x3c, 0x30, 0x01, 0x21, - 0xc1, 0x80, 0x81, 0x80, 0x08, 0x99, 0x11, 0xf8, 0xd0, 0x2f, 0x42, 0x80, - 0x49, 0x78, 0x01, 0x80, 0x6d, 0x1c, 0x02, 0x2d, 0xba, 0xd3, 0x20, 0x46, - 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x00, 0x00, 0x2d, 0xe9, 0xf1, 0x4f, - 0xa0, 0xb0, 0xf8, 0xf7, 0x02, 0xfe, 0x02, 0x90, 0x3a, 0x21, 0x20, 0x98, - 0xdf, 0xf8, 0x70, 0x69, 0xdf, 0xf8, 0x7c, 0x49, 0x04, 0x90, 0x44, 0x22, - 0x06, 0xf1, 0x10, 0x00, 0x05, 0x90, 0x4f, 0xf4, 0x84, 0x58, 0x20, 0x98, - 0x01, 0xfb, 0x00, 0xf5, 0x28, 0x19, 0x06, 0x90, 0x20, 0x99, 0xdf, 0xf8, - 0x48, 0x09, 0x02, 0xfb, 0x01, 0x00, 0x07, 0x90, 0xd4, 0x22, 0x20, 0x99, - 0xdf, 0xf8, 0x3c, 0x09, 0x02, 0xfb, 0x01, 0x00, 0x0b, 0x90, 0x0f, 0x90, - 0xf7, 0xf7, 0x20, 0xfb, 0x28, 0x19, 0xdf, 0xf8, 0x38, 0x19, 0x3a, 0x22, - 0xff, 0xf7, 0xa2, 0xfa, 0x07, 0x98, 0x0b, 0x99, 0xc0, 0x8f, 0x81, 0xf8, - 0xd0, 0x00, 0x07, 0x98, 0x0b, 0x99, 0x80, 0x8f, 0x81, 0xf8, 0xd1, 0x00, - 0xf7, 0xf7, 0x23, 0xfb, 0x06, 0x98, 0x20, 0x99, 0x30, 0xf9, 0x11, 0x00, - 0x03, 0x90, 0x07, 0x98, 0x41, 0x6b, 0x81, 0x63, 0xf8, 0xf7, 0xec, 0xf9, - 0x07, 0x9d, 0x68, 0x63, 0x28, 0x6b, 0x40, 0x1c, 0x28, 0x63, 0x20, 0x98, - 0x06, 0xeb, 0x80, 0x00, 0x11, 0x90, 0x03, 0x98, 0xfc, 0xf7, 0x6e, 0xf9, - 0xdf, 0xf8, 0xf4, 0x18, 0xfc, 0xf7, 0x84, 0xf9, 0xdf, 0xf8, 0xf0, 0x18, - 0xfc, 0xf7, 0x80, 0xf9, 0x00, 0xf0, 0xc9, 0xfa, 0x11, 0x99, 0x88, 0x60, - 0x03, 0x98, 0x68, 0x61, 0x02, 0x98, 0x68, 0x62, 0xb5, 0xf8, 0x40, 0x00, - 0x30, 0xb9, 0x0f, 0x98, 0x00, 0xf0, 0xf0, 0xfb, 0x49, 0xf2, 0x80, 0x28, - 0x06, 0x25, 0xab, 0xe2, 0x00, 0x20, 0x0e, 0x90, 0x00, 0x90, 0x0d, 0x90, - 0x0c, 0x90, 0x10, 0x90, 0x04, 0xa8, 0x00, 0xf0, 0xea, 0xfb, 0x05, 0x00, - 0x1d, 0xd1, 0x0b, 0x98, 0x90, 0xf8, 0xd0, 0x10, 0x04, 0x98, 0xff, 0xf7, - 0x7e, 0xfc, 0xef, 0xf3, 0x11, 0x8b, 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, - 0x20, 0x98, 0xf8, 0xf7, 0x15, 0xfe, 0x20, 0x98, 0x80, 0x19, 0x01, 0x90, - 0x00, 0x20, 0x01, 0x99, 0x08, 0x71, 0x00, 0xf0, 0x9f, 0xfa, 0x00, 0x8c, - 0x48, 0xb9, 0x01, 0x99, 0x88, 0x70, 0x8b, 0xf3, 0x11, 0x88, 0x00, 0x27, - 0x84, 0xe0, 0x04, 0xa8, 0x00, 0xf0, 0xfa, 0xfb, 0x7e, 0xe2, 0x20, 0x98, - 0x00, 0x21, 0xf8, 0xf7, 0xf0, 0xfd, 0x00, 0x28, 0xef, 0xd0, 0x01, 0x20, - 0xed, 0xe7, 0x00, 0x26, 0x12, 0xaa, 0x12, 0xa8, 0x32, 0xf9, 0x26, 0x20, - 0x00, 0xeb, 0x86, 0x0a, 0xd3, 0x17, 0xa2, 0xfb, 0x02, 0x49, 0xba, 0xf9, - 0x02, 0x00, 0x02, 0xfb, 0x03, 0x99, 0x03, 0xfb, 0x02, 0x99, 0xc1, 0x17, - 0xa0, 0xfb, 0x00, 0x23, 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, - 0x49, 0x46, 0xa0, 0x18, 0x59, 0x41, 0xfc, 0xf7, 0xd1, 0xf8, 0x0e, 0x99, - 0xfc, 0xf7, 0x0c, 0xfa, 0x0e, 0x90, 0x19, 0xa8, 0x00, 0xeb, 0x86, 0x0b, - 0x30, 0xf9, 0x26, 0x00, 0xc1, 0x17, 0xa0, 0xfb, 0x00, 0x23, 0xbb, 0xf9, - 0x02, 0x40, 0x00, 0xfb, 0x01, 0x33, 0x01, 0xfb, 0x00, 0x33, 0x4f, 0xea, - 0xe4, 0x79, 0xa4, 0xfb, 0x04, 0x01, 0x04, 0xfb, 0x09, 0x11, 0x09, 0xfb, - 0x04, 0x11, 0x10, 0x18, 0x59, 0x41, 0xfc, 0xf7, 0xb3, 0xf8, 0x00, 0x99, - 0xfc, 0xf7, 0xee, 0xf9, 0x00, 0x90, 0x19, 0xa8, 0xbb, 0xf9, 0x02, 0x40, - 0x30, 0xf9, 0x26, 0xb0, 0xba, 0xf9, 0x02, 0x20, 0x12, 0xa8, 0x4f, 0xea, - 0xe4, 0x79, 0x30, 0xf9, 0x26, 0xc0, 0xa2, 0xfb, 0x04, 0x01, 0xd3, 0x17, - 0x02, 0xfb, 0x09, 0x11, 0x03, 0xfb, 0x04, 0x11, 0xcc, 0xfb, 0x0b, 0x01, - 0xfc, 0xf7, 0x98, 0xf8, 0x0d, 0x99, 0xfc, 0xf7, 0xd3, 0xf9, 0x0d, 0x90, - 0x22, 0x46, 0x12, 0xa8, 0x4b, 0x46, 0x30, 0xf9, 0x26, 0x00, 0xa0, 0xfb, - 0x02, 0x49, 0xc1, 0x17, 0x00, 0xfb, 0x03, 0x99, 0x19, 0xa8, 0x01, 0xfb, - 0x02, 0x99, 0x30, 0xf9, 0x26, 0x00, 0xba, 0xf9, 0x02, 0x10, 0x81, 0xfb, - 0x00, 0x01, 0x20, 0x1a, 0x69, 0xeb, 0x01, 0x01, 0xfc, 0xf7, 0x7c, 0xf8, - 0x0c, 0x99, 0xfc, 0xf7, 0xb7, 0xf9, 0x76, 0x1c, 0x07, 0x2e, 0x0c, 0x90, - 0x88, 0xd3, 0x7f, 0x1c, 0x00, 0xf0, 0x10, 0xfa, 0x00, 0x8b, 0x87, 0x42, - 0x19, 0xd2, 0x0f, 0x98, 0x00, 0x88, 0x07, 0x23, 0x12, 0xaa, 0x19, 0xa9, - 0xff, 0xf7, 0x16, 0xfc, 0xf9, 0xf7, 0x57, 0xfe, 0x00, 0x28, 0x3f, 0xf4, - 0x76, 0xaf, 0x07, 0x99, 0x04, 0x20, 0x08, 0x60, 0x7f, 0x1e, 0x04, 0xa8, - 0x00, 0xf0, 0x60, 0xfb, 0x04, 0xa8, 0x00, 0xf0, 0x2a, 0xfb, 0x05, 0x00, - 0xe1, 0xd0, 0x01, 0x20, 0x10, 0x90, 0x04, 0xa8, 0x00, 0xf0, 0x56, 0xfb, - 0x10, 0x98, 0x00, 0x28, 0x02, 0xbf, 0x01, 0x98, 0x00, 0x79, 0x00, 0x28, - 0x05, 0xd1, 0x01, 0x98, 0x80, 0x78, 0x18, 0xb1, 0x0f, 0x25, 0x49, 0xf2, - 0x80, 0x28, 0xcd, 0xe1, 0x06, 0x98, 0x20, 0x99, 0xdf, 0xf8, 0x04, 0xb7, - 0x00, 0xeb, 0x41, 0x07, 0x38, 0x8b, 0xc0, 0xeb, 0xc0, 0x00, 0xfc, 0xf7, - 0x6b, 0xf8, 0x04, 0x46, 0x00, 0x98, 0x21, 0x46, 0xfc, 0xf7, 0x80, 0xf8, - 0xfc, 0xf7, 0xb2, 0xf9, 0x00, 0xf0, 0xc3, 0xf9, 0x06, 0x46, 0x0e, 0x98, - 0x21, 0x46, 0xfc, 0xf7, 0x77, 0xf8, 0xfc, 0xf7, 0xa9, 0xf9, 0x00, 0xf0, - 0xba, 0xf9, 0x81, 0x46, 0x07, 0x9c, 0x01, 0x21, 0x30, 0x46, 0x03, 0xf0, - 0x05, 0xfb, 0x00, 0xf0, 0xe3, 0xfa, 0x00, 0xf0, 0xb8, 0xf9, 0xfc, 0xf7, - 0x61, 0xfa, 0xa0, 0x62, 0x01, 0x21, 0x48, 0x46, 0x03, 0xf0, 0xfa, 0xfa, - 0x00, 0xf0, 0xd8, 0xfa, 0x00, 0xf0, 0xad, 0xf9, 0xfc, 0xf7, 0x56, 0xfa, - 0xe0, 0x62, 0x01, 0x98, 0x80, 0x78, 0x10, 0xb1, 0x49, 0xf2, 0x80, 0x28, - 0x29, 0xe0, 0xf8, 0x8e, 0xfc, 0xf7, 0x42, 0xf8, 0x4f, 0xf0, 0x5e, 0x5a, - 0x00, 0xf0, 0xc3, 0xfa, 0x01, 0x46, 0x30, 0x46, 0xfc, 0xf7, 0xc6, 0xf9, - 0x04, 0xd2, 0x02, 0x98, 0x60, 0x62, 0x49, 0xf2, 0xb2, 0x28, 0x12, 0x25, - 0xb8, 0x8b, 0xfc, 0xf7, 0x31, 0xf8, 0x00, 0xf0, 0xb4, 0xfa, 0x01, 0x46, - 0x48, 0x46, 0xfc, 0xf7, 0xb7, 0xf9, 0x10, 0xd2, 0x02, 0x98, 0x60, 0x62, - 0x49, 0xf2, 0xb2, 0x28, 0x13, 0x25, 0x66, 0x6a, 0x48, 0xf4, 0x02, 0x40, - 0x40, 0xf0, 0xe4, 0x08, 0x01, 0x98, 0x80, 0x78, 0x00, 0x28, 0x00, 0xf0, - 0x27, 0x81, 0x0f, 0x25, 0x66, 0xe1, 0x00, 0x2d, 0xf1, 0xd1, 0x01, 0x98, - 0x04, 0x78, 0xb8, 0x8a, 0xfc, 0xf7, 0x12, 0xf8, 0xdf, 0xf8, 0x30, 0x16, - 0xfc, 0xf7, 0x1e, 0xf8, 0x31, 0x46, 0xfc, 0xf7, 0x97, 0xf9, 0x4f, 0xf0, - 0x00, 0x0a, 0x38, 0xbf, 0x00, 0x20, 0x0b, 0xd3, 0x38, 0x8a, 0xfc, 0xf7, - 0x03, 0xf8, 0xdf, 0xf8, 0x14, 0x16, 0xfc, 0xf7, 0x0f, 0xf8, 0x31, 0x46, - 0xfc, 0xf7, 0x88, 0xf9, 0x16, 0xd2, 0x01, 0x20, 0x04, 0x2c, 0x13, 0xd8, - 0xdf, 0xe8, 0x04, 0xf0, 0x03, 0x0c, 0x05, 0x03, 0x03, 0x00, 0x20, 0xb9, - 0x07, 0xe0, 0x10, 0xb9, 0x4f, 0xf0, 0x04, 0x0a, 0x08, 0xe0, 0x4f, 0xf0, - 0x02, 0x0a, 0x05, 0xe0, 0x10, 0xb9, 0x4f, 0xf0, 0x01, 0x0a, 0x01, 0xe0, - 0x4f, 0xf0, 0x03, 0x0a, 0x01, 0x98, 0x80, 0xf8, 0x00, 0xa0, 0xf7, 0xf7, - 0x5f, 0xf9, 0x01, 0x98, 0x04, 0x78, 0x54, 0xb9, 0x07, 0x9c, 0x00, 0x20, - 0xa0, 0x61, 0xe0, 0x61, 0x20, 0x62, 0x48, 0xf4, 0x02, 0x48, 0xf7, 0xf7, - 0x68, 0xf9, 0x0b, 0x25, 0x1e, 0xe1, 0x48, 0x46, 0x31, 0x46, 0xfb, 0xf7, - 0xdd, 0xff, 0x81, 0x46, 0x0d, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xd8, 0xff, - 0x4f, 0xf0, 0x8c, 0x47, 0x39, 0x46, 0xfc, 0xf7, 0x61, 0xf9, 0x00, 0xf0, - 0x18, 0xf9, 0x82, 0x46, 0x0c, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xcc, 0xff, - 0x39, 0x46, 0xfc, 0xf7, 0x57, 0xf9, 0x00, 0xf0, 0x0e, 0xf9, 0x07, 0x46, - 0x50, 0x46, 0x00, 0xf0, 0x38, 0xfa, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, - 0xfc, 0xf7, 0x4c, 0xf9, 0x00, 0x99, 0xfc, 0xf7, 0xad, 0xf8, 0xfc, 0xf7, - 0xed, 0xf8, 0x01, 0x2c, 0x1c, 0xbf, 0x03, 0x2c, 0x81, 0x46, 0x07, 0x9c, - 0x01, 0x21, 0x48, 0x46, 0x03, 0xf0, 0x48, 0xfa, 0x00, 0xf0, 0x26, 0xfa, - 0x00, 0xf0, 0xfb, 0xf8, 0xfc, 0xf7, 0xa4, 0xf9, 0xa0, 0x61, 0x51, 0x46, - 0xdf, 0xf8, 0x34, 0x05, 0xfc, 0xf7, 0x32, 0xf9, 0xfc, 0xf7, 0x9c, 0xf9, - 0xe0, 0x61, 0x39, 0x46, 0xdf, 0xf8, 0x24, 0x05, 0xfc, 0xf7, 0x2a, 0xf9, - 0xfc, 0xf7, 0x94, 0xf9, 0x20, 0x62, 0xf7, 0xf7, 0x1c, 0xf9, 0x00, 0xf0, - 0xe7, 0xf8, 0x81, 0x8c, 0x61, 0xb1, 0x07, 0x99, 0x03, 0x9a, 0x89, 0x69, - 0x00, 0x8d, 0x89, 0x1a, 0x48, 0xbf, 0x49, 0x42, 0x88, 0x42, 0x03, 0xda, - 0x48, 0xf4, 0x02, 0x48, 0x10, 0x25, 0xc3, 0xe0, 0x02, 0xa8, 0x00, 0x88, - 0xfb, 0xf7, 0x72, 0xff, 0x04, 0x46, 0xdf, 0xf8, 0xf4, 0x04, 0x21, 0x46, - 0xfc, 0xf7, 0x0a, 0xf9, 0xdf, 0xf8, 0xec, 0x14, 0xfb, 0xf7, 0x78, 0xff, - 0x00, 0xf0, 0xc1, 0xf8, 0x01, 0x46, 0x0f, 0x98, 0x33, 0x46, 0x4a, 0x46, - 0x00, 0xf0, 0xc7, 0xf8, 0x07, 0x46, 0xfc, 0xf7, 0x67, 0xf9, 0x10, 0xf1, - 0x01, 0x0f, 0x18, 0xbf, 0x10, 0xf1, 0x02, 0x0f, 0x49, 0xf2, 0xcb, 0x21, - 0x05, 0xd0, 0x10, 0xf1, 0x03, 0x0f, 0x18, 0xbf, 0x10, 0xf1, 0x04, 0x0f, - 0x05, 0xd1, 0x07, 0x9a, 0x02, 0x98, 0x50, 0x62, 0x88, 0x46, 0x07, 0x25, - 0x96, 0xe0, 0x06, 0x98, 0x20, 0x9a, 0x00, 0xeb, 0x42, 0x06, 0xb0, 0x88, - 0x28, 0xb9, 0x07, 0x9a, 0x02, 0x98, 0x50, 0x62, 0x88, 0x46, 0x09, 0x25, - 0x8a, 0xe0, 0xb0, 0x89, 0xfb, 0xf7, 0x3a, 0xff, 0xdf, 0xf8, 0x8c, 0x14, - 0xfc, 0xf7, 0xd4, 0xf8, 0x11, 0x99, 0x89, 0x68, 0x81, 0x46, 0x38, 0x46, - 0xfb, 0xf7, 0x40, 0xff, 0x01, 0x21, 0x03, 0xf0, 0xd5, 0xf9, 0x00, 0xf0, - 0xb3, 0xf9, 0x00, 0x90, 0x00, 0xf0, 0xb3, 0xf9, 0x00, 0xf0, 0xae, 0xf9, - 0x21, 0x46, 0xfc, 0xf7, 0x25, 0xf8, 0x82, 0x46, 0x11, 0xe0, 0x4f, 0xf0, - 0x7c, 0x50, 0x00, 0xf0, 0xa8, 0xf9, 0x81, 0x46, 0x00, 0x98, 0x00, 0xf0, - 0xa4, 0xf9, 0x00, 0xf0, 0x9f, 0xf9, 0x21, 0x46, 0xfc, 0xf7, 0x16, 0xf8, - 0x07, 0x99, 0x82, 0x46, 0x08, 0x20, 0x08, 0x60, 0x50, 0x46, 0xfc, 0xf7, - 0x17, 0xf9, 0x07, 0xb2, 0xb7, 0xf5, 0x52, 0x7f, 0xe7, 0xd2, 0x30, 0x89, - 0xfb, 0xf7, 0x06, 0xff, 0x00, 0xf0, 0x8c, 0xf9, 0x06, 0x46, 0x38, 0x46, - 0xfb, 0xf7, 0xf6, 0xfe, 0x01, 0x46, 0x30, 0x46, 0xfc, 0xf7, 0xa2, 0xf9, - 0x9c, 0xbf, 0xb2, 0x46, 0x0a, 0x25, 0x50, 0x46, 0xfc, 0xf7, 0x00, 0xf9, - 0x06, 0x46, 0xcf, 0xe6, 0x06, 0x98, 0x20, 0x99, 0x00, 0xeb, 0x41, 0x02, - 0xd1, 0x8d, 0x53, 0x8e, 0x5a, 0x18, 0xcb, 0x1a, 0xb6, 0xb2, 0xb2, 0x42, - 0xb4, 0xbf, 0x4f, 0xf0, 0x01, 0x0c, 0x4f, 0xf0, 0x00, 0x0c, 0x9e, 0x42, - 0xb4, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x4f, 0xf0, 0x00, 0x0b, 0x5b, 0xea, - 0x0c, 0x04, 0x13, 0xd0, 0x20, 0x9d, 0x28, 0x18, 0x90, 0xf8, 0x2c, 0x00, - 0x10, 0xb1, 0x02, 0x28, 0x02, 0xd0, 0x07, 0xe0, 0x0e, 0x46, 0x07, 0xe0, - 0xbc, 0xf1, 0x00, 0x0f, 0x0c, 0xbf, 0x1e, 0x46, 0x16, 0x46, 0x01, 0xe0, - 0x07, 0x98, 0x46, 0x6a, 0x11, 0x25, 0x01, 0xe0, 0x49, 0xf6, 0xe4, 0x28, - 0x20, 0x98, 0x0f, 0xf2, 0xc4, 0x34, 0x4f, 0xea, 0x40, 0x0b, 0x30, 0x04, - 0x01, 0x0e, 0x34, 0xf8, 0x1b, 0x00, 0xf8, 0xf7, 0x9b, 0xf9, 0x04, 0xeb, - 0x4b, 0x00, 0xf1, 0xb2, 0x40, 0x88, 0xf8, 0xf7, 0x95, 0xf9, 0x07, 0x98, - 0xb6, 0xb2, 0x46, 0x62, 0x42, 0x46, 0x07, 0x98, 0x29, 0x46, 0x03, 0xf0, - 0x15, 0xf9, 0x28, 0x46, 0x21, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x4f, 0xf0, - 0x64, 0x51, 0xfc, 0xf7, 0x43, 0xb8, 0x01, 0x46, 0xd9, 0x48, 0xfc, 0xf7, - 0xb6, 0xba, 0xd2, 0x49, 0xfc, 0xf7, 0x3c, 0xb8, 0x06, 0x98, 0x20, 0x99, - 0x00, 0xeb, 0x41, 0x00, 0x70, 0x47, 0x2d, 0xe9, 0xf6, 0x4f, 0x04, 0x46, - 0x1d, 0x46, 0x87, 0xb0, 0x28, 0x46, 0x00, 0x21, 0xfc, 0xf7, 0x1c, 0xf8, - 0x04, 0xd2, 0x20, 0x46, 0x00, 0xf0, 0x1a, 0xf9, 0xce, 0x48, 0x07, 0xe1, - 0x60, 0x88, 0x10, 0x28, 0x1d, 0xda, 0x0c, 0x22, 0x07, 0x99, 0x02, 0xfb, - 0x00, 0x40, 0x01, 0x61, 0x60, 0x88, 0x08, 0x99, 0x02, 0xfb, 0x00, 0x40, - 0x41, 0x61, 0x29, 0x46, 0x60, 0x88, 0x02, 0xfb, 0x00, 0x40, 0x85, 0x61, - 0xa0, 0x68, 0xfc, 0xf7, 0x01, 0xf8, 0x38, 0xbf, 0xa5, 0x60, 0x03, 0xd3, - 0x00, 0xf0, 0xf1, 0xf8, 0x38, 0xbf, 0xe5, 0x60, 0x60, 0x88, 0x40, 0x1c, - 0x60, 0x80, 0x08, 0x98, 0xe6, 0xe0, 0x8b, 0x46, 0x00, 0x26, 0x8a, 0x46, - 0x88, 0x46, 0x89, 0x46, 0x02, 0x91, 0x06, 0x91, 0x05, 0x91, 0xad, 0xf8, - 0x10, 0x10, 0x00, 0x27, 0x0c, 0x20, 0x00, 0xfb, 0x07, 0x40, 0x03, 0x90, - 0x59, 0x46, 0x00, 0x69, 0x01, 0x90, 0x7f, 0x1c, 0xfb, 0xf7, 0x56, 0xff, - 0x83, 0x46, 0x03, 0x98, 0x40, 0x69, 0x00, 0x90, 0x31, 0x46, 0xfb, 0xf7, - 0x4f, 0xff, 0x06, 0x46, 0x01, 0x98, 0x00, 0x99, 0xfb, 0xf7, 0xe6, 0xff, - 0x49, 0x46, 0xfb, 0xf7, 0x47, 0xff, 0x81, 0x46, 0x01, 0x98, 0x01, 0x46, - 0xfb, 0xf7, 0xde, 0xff, 0x51, 0x46, 0xfb, 0xf7, 0x3f, 0xff, 0x82, 0x46, - 0x00, 0x98, 0x01, 0x46, 0xfb, 0xf7, 0xd6, 0xff, 0x41, 0x46, 0xfb, 0xf7, - 0x37, 0xff, 0x10, 0x2f, 0x80, 0x46, 0xd3, 0xd3, 0x4f, 0xf0, 0x83, 0x40, - 0x00, 0xf0, 0xb3, 0xf8, 0x07, 0x46, 0x58, 0x46, 0x00, 0xf0, 0xb2, 0xf8, - 0x01, 0x46, 0x38, 0x46, 0xfb, 0xf7, 0xb4, 0xfe, 0x07, 0x46, 0x4f, 0xf0, - 0x83, 0x40, 0x41, 0x46, 0xfb, 0xf7, 0xbe, 0xff, 0x80, 0x46, 0x30, 0x46, - 0x31, 0x46, 0xfb, 0xf7, 0xb9, 0xff, 0x01, 0x46, 0x40, 0x46, 0xfb, 0xf7, - 0xa5, 0xfe, 0x80, 0x46, 0x4f, 0xf0, 0x83, 0x40, 0x00, 0xf0, 0x9d, 0xf8, - 0x81, 0x46, 0x58, 0x46, 0x31, 0x46, 0xfb, 0xf7, 0xab, 0xff, 0x01, 0x46, - 0x48, 0x46, 0xfb, 0xf7, 0x97, 0xfe, 0x81, 0x46, 0x8d, 0x49, 0x38, 0x46, - 0xfc, 0xf7, 0xaa, 0xf8, 0x21, 0xd8, 0x40, 0x46, 0xfc, 0xf7, 0xa6, 0xf8, - 0x1d, 0xd8, 0x01, 0x20, 0xad, 0xf8, 0x10, 0x00, 0x41, 0x46, 0x38, 0x46, - 0xfb, 0xf7, 0x96, 0xff, 0xfb, 0xf7, 0x3a, 0xff, 0x01, 0x46, 0x48, 0x46, - 0xfb, 0xf7, 0x02, 0xfe, 0x05, 0x90, 0x39, 0x46, 0x48, 0x46, 0xfb, 0xf7, - 0xfd, 0xfd, 0x02, 0x90, 0x00, 0xf0, 0x72, 0xf8, 0x01, 0x46, 0x30, 0x46, - 0xfb, 0xf7, 0x74, 0xfe, 0x4f, 0xf0, 0x76, 0x51, 0xfb, 0xf7, 0x80, 0xff, - 0x06, 0x90, 0x29, 0x46, 0xe0, 0x68, 0xfb, 0xf7, 0x69, 0xff, 0x03, 0xd2, - 0xa1, 0x68, 0x00, 0xf0, 0x5b, 0xf8, 0x26, 0xd3, 0xbd, 0xf8, 0x10, 0x00, - 0x20, 0xb1, 0x05, 0x98, 0x74, 0x49, 0xfb, 0xf7, 0x5d, 0xff, 0x01, 0xd2, - 0x73, 0x4a, 0x1d, 0xe0, 0x02, 0x99, 0x07, 0x98, 0xfb, 0xf7, 0x68, 0xff, - 0x06, 0x99, 0xfb, 0xf7, 0xc9, 0xfe, 0x08, 0x99, 0x06, 0x46, 0xfb, 0xf7, - 0x51, 0xfe, 0x00, 0x21, 0xfb, 0xf7, 0x4c, 0xff, 0x03, 0xd2, 0x08, 0x98, - 0x31, 0x46, 0xfb, 0xf7, 0x49, 0xfe, 0x08, 0x99, 0xfb, 0xf7, 0xc8, 0xfd, - 0x68, 0x49, 0xfc, 0xf7, 0x5b, 0xf8, 0x98, 0xbf, 0x4f, 0xf0, 0x40, 0x42, - 0x00, 0xd9, 0x08, 0x9a, 0xa0, 0x88, 0x0c, 0x21, 0x01, 0xfb, 0x00, 0x40, - 0x07, 0x99, 0x01, 0x61, 0x0c, 0x21, 0xa0, 0x88, 0x01, 0xfb, 0x00, 0x40, - 0x08, 0x99, 0x41, 0x61, 0x0c, 0x21, 0xa0, 0x88, 0x01, 0xfb, 0x00, 0x40, - 0x00, 0x23, 0x85, 0x61, 0xa0, 0x88, 0x40, 0x1c, 0xc1, 0x10, 0x00, 0xeb, - 0x11, 0x71, 0x09, 0x11, 0xa0, 0xeb, 0x01, 0x10, 0xa0, 0x80, 0x0c, 0x20, - 0x00, 0xfb, 0x03, 0x40, 0x85, 0x69, 0xa0, 0x68, 0x29, 0x46, 0xfb, 0xf7, - 0x19, 0xff, 0x38, 0xbf, 0xa5, 0x60, 0x03, 0xd3, 0x00, 0xf0, 0x09, 0xf8, - 0x38, 0xbf, 0xe5, 0x60, 0x5b, 0x1c, 0x10, 0x2b, 0xed, 0xd3, 0x10, 0x46, - 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0xe1, 0x68, 0x28, 0x46, 0xfb, 0xf7, - 0x07, 0xbf, 0x51, 0x46, 0xfb, 0xf7, 0x16, 0xbf, 0x59, 0x46, 0xfb, 0xf7, - 0x13, 0xbf, 0x49, 0x46, 0xfb, 0xf7, 0x10, 0xbf, 0x00, 0x21, 0x41, 0x80, - 0x81, 0x80, 0x81, 0x60, 0x44, 0x49, 0xc1, 0x60, 0x70, 0x47, 0x38, 0xb5, - 0x04, 0x46, 0x00, 0x21, 0x00, 0x20, 0xf8, 0xf7, 0x9a, 0xfa, 0x20, 0x68, - 0x04, 0xf1, 0x10, 0x01, 0xff, 0xf7, 0x7d, 0xf9, 0x05, 0x00, 0x09, 0xd1, - 0xe0, 0x69, 0x00, 0xf1, 0xd0, 0x01, 0x20, 0x68, 0xff, 0xf7, 0xd0, 0xf9, - 0x20, 0x68, 0xff, 0xf7, 0xb2, 0xf9, 0x05, 0x46, 0x01, 0x2d, 0x0b, 0xd0, - 0x02, 0x2d, 0x0b, 0xd0, 0x0c, 0x2d, 0x0b, 0xd0, 0x11, 0x2d, 0x0b, 0xd0, - 0x13, 0x2d, 0x0b, 0xd0, 0x14, 0x2d, 0x08, 0xbf, 0x0d, 0x25, 0x08, 0xe0, - 0x02, 0x25, 0x06, 0xe0, 0x01, 0x25, 0x04, 0xe0, 0x0e, 0x25, 0x02, 0xe0, - 0x03, 0x25, 0x00, 0xe0, 0x0c, 0x25, 0x20, 0x68, 0xfb, 0xf7, 0x2c, 0xfb, - 0x28, 0x46, 0x32, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xf8, 0xf7, 0x58, 0xfd, - 0x03, 0x28, 0x06, 0xd1, 0x03, 0xf0, 0x5e, 0xfa, 0x00, 0x21, 0x04, 0xf1, - 0x10, 0x00, 0xfa, 0xf7, 0x58, 0xfa, 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x20, - 0xf8, 0xf7, 0xb8, 0xba, 0x11, 0x4a, 0x22, 0xf8, 0x10, 0x10, 0x70, 0x47, - 0x10, 0xb5, 0x04, 0x46, 0x0e, 0x49, 0x01, 0xeb, 0x44, 0x01, 0x09, 0x8c, - 0x29, 0xb1, 0x01, 0x21, 0xf8, 0xf7, 0xdb, 0xf9, 0x10, 0xb1, 0x01, 0x20, - 0x00, 0xe0, 0x00, 0x20, 0x06, 0x49, 0x61, 0x18, 0x88, 0x70, 0x8a, 0x78, - 0x50, 0x1e, 0x80, 0x41, 0xc0, 0x0f, 0x08, 0x71, 0x10, 0xbd, 0x00, 0x00, - 0xa8, 0xef, 0x00, 0x20, 0xcc, 0xe6, 0x00, 0x20, 0xb0, 0x26, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0xd8, 0x26, 0x00, 0x20, 0xc0, 0x26, 0x00, 0x20, - 0xd4, 0xac, 0x00, 0x20, 0x00, 0x00, 0xc8, 0x42, 0x00, 0x00, 0xa0, 0x41, - 0x00, 0x00, 0x7a, 0x44, 0xcd, 0xcc, 0x4c, 0x3d, 0x00, 0x00, 0xa0, 0xc1, - 0x0a, 0xd7, 0x23, 0x3c, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x80, 0xc0, - 0x70, 0x12, 0x83, 0x3a, 0xcd, 0xcc, 0xcc, 0x3d, 0x00, 0x00, 0x40, 0xc0, - 0xce, 0xcc, 0x4c, 0x3d, 0xec, 0x78, 0xad, 0x60, 0x61, 0x09, 0x60, 0x09, - 0x63, 0x09, 0x62, 0x09, 0x01, 0x22, 0x41, 0x1c, 0x03, 0xe0, 0x0a, 0x46, - 0xb0, 0xfb, 0xf2, 0xf1, 0x89, 0x18, 0x49, 0x08, 0x8a, 0x1a, 0x48, 0xbf, - 0x52, 0x42, 0x02, 0x2a, 0xf5, 0xda, 0x01, 0xfb, 0x01, 0xf2, 0x90, 0x42, - 0x38, 0xbf, 0x49, 0x1e, 0xf9, 0xd3, 0x08, 0x46, 0x70, 0x47, 0x30, 0xb5, - 0x4f, 0xf4, 0x80, 0x53, 0x03, 0x60, 0x41, 0x60, 0x02, 0x23, 0x00, 0xeb, - 0x83, 0x05, 0x01, 0xfb, 0x02, 0xf4, 0x55, 0xf8, 0x04, 0x5c, 0x6c, 0x43, - 0x64, 0x0b, 0x40, 0xf8, 0x23, 0x40, 0x5b, 0x1c, 0x08, 0x2b, 0xf2, 0xdb, - 0x30, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x9e, 0x00, 0x24, 0x00, 0x25, - 0x26, 0xfa, 0x05, 0xfe, 0x5f, 0xea, 0xce, 0x7e, 0x4f, 0xea, 0xd5, 0x0c, - 0x05, 0xf0, 0x07, 0x07, 0x49, 0xd5, 0xbc, 0xf1, 0x03, 0x0f, 0x01, 0xeb, - 0x87, 0x07, 0x11, 0xd0, 0xbc, 0xf1, 0x01, 0x0f, 0x05, 0xd1, 0x3f, 0x6a, - 0xb2, 0xf9, 0x00, 0xc0, 0xb2, 0xf9, 0x02, 0xe0, 0x1f, 0xe0, 0x3f, 0x68, - 0xbc, 0xf1, 0x02, 0x0f, 0xf6, 0xd1, 0xb2, 0xf9, 0x04, 0xc0, 0xb2, 0xf9, - 0x06, 0xe0, 0x16, 0xe0, 0x93, 0xb1, 0x5f, 0xea, 0x83, 0x7c, 0x4c, 0xbf, - 0x3f, 0x6c, 0x3f, 0x6a, 0x5f, 0xea, 0xc3, 0x7c, 0xe8, 0xd5, 0xb2, 0xf8, - 0x00, 0xc0, 0xb2, 0xf8, 0x04, 0xe0, 0xb2, 0xf8, 0x06, 0x80, 0xf4, 0x44, - 0xb2, 0xf8, 0x02, 0xe0, 0xc6, 0x44, 0x02, 0xe0, 0x00, 0x27, 0xbe, 0x46, - 0xbc, 0x46, 0x0f, 0xfa, 0x8c, 0xfc, 0x07, 0xfb, 0x0c, 0xfc, 0x4f, 0xea, - 0x6c, 0x28, 0x0c, 0xeb, 0x98, 0x5c, 0x4f, 0xea, 0xac, 0x2c, 0x40, 0xf8, - 0x34, 0xc0, 0x0f, 0xfa, 0x8e, 0xfe, 0x07, 0xfb, 0x0e, 0xf7, 0x4f, 0xea, - 0x67, 0x2c, 0x07, 0xeb, 0x9c, 0x57, 0x00, 0xeb, 0xc4, 0x0c, 0x64, 0x1c, - 0xbf, 0x12, 0x15, 0x2c, 0xcc, 0xf8, 0x04, 0x70, 0x02, 0xd2, 0x6d, 0x1c, - 0x20, 0x2d, 0xa9, 0xd3, 0xbd, 0xe8, 0xf0, 0x81, 0x2d, 0xe9, 0xf0, 0x43, - 0x00, 0x24, 0x61, 0xe0, 0x00, 0x26, 0x00, 0xeb, 0x44, 0x05, 0xa8, 0x27, - 0x07, 0xfb, 0x04, 0x27, 0x07, 0xeb, 0xc6, 0x07, 0x57, 0xf8, 0xa8, 0xef, - 0x95, 0xf9, 0x01, 0x80, 0xd7, 0xf8, 0x04, 0x90, 0x10, 0xf9, 0x14, 0xc0, - 0x09, 0xfb, 0x08, 0xf8, 0x0e, 0xfb, 0x0c, 0x8c, 0x52, 0xf8, 0x36, 0xe0, - 0x4f, 0xea, 0x6c, 0x18, 0x0c, 0xeb, 0x98, 0x6c, 0x0e, 0xeb, 0xac, 0x1c, - 0x42, 0xf8, 0x36, 0xc0, 0xd7, 0xf8, 0x04, 0xe0, 0x10, 0xf9, 0x14, 0xc0, - 0x3f, 0x68, 0x0e, 0xfb, 0x0c, 0xfc, 0x95, 0xf9, 0x01, 0xe0, 0x07, 0xfb, - 0x1e, 0xc7, 0x02, 0xeb, 0xc6, 0x0c, 0x4f, 0xea, 0x67, 0x18, 0xdc, 0xf8, - 0x04, 0xe0, 0x07, 0xeb, 0x98, 0x67, 0x76, 0x1c, 0x0e, 0xeb, 0xa7, 0x17, - 0x15, 0x2e, 0xcc, 0xf8, 0x04, 0x70, 0xca, 0xd3, 0x03, 0xeb, 0xc4, 0x06, - 0x95, 0xf9, 0x01, 0xe0, 0xd6, 0xf8, 0x0c, 0x80, 0x10, 0xf9, 0x14, 0x70, - 0xd6, 0xf8, 0x08, 0xc0, 0x08, 0xfb, 0x0e, 0xfe, 0x0c, 0xfb, 0x07, 0xe7, - 0xd3, 0xf8, 0x00, 0xc0, 0x4f, 0xea, 0x67, 0x1e, 0x07, 0xeb, 0x9e, 0x67, - 0x0c, 0xeb, 0xa7, 0x17, 0x1f, 0x60, 0xd6, 0xf8, 0x0c, 0xc0, 0x10, 0xf9, - 0x14, 0x70, 0x95, 0xf9, 0x01, 0x50, 0xb6, 0x68, 0x0c, 0xfb, 0x07, 0xf7, - 0x06, 0xfb, 0x15, 0x75, 0x5e, 0x68, 0x6f, 0x11, 0x05, 0xeb, 0x97, 0x65, - 0x06, 0xeb, 0xa5, 0x15, 0x5d, 0x60, 0x64, 0x1c, 0x8c, 0x42, 0x9b, 0xd3, - 0xbd, 0xe8, 0xf0, 0x83, 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0xad, 0xf2, - 0x5c, 0x4d, 0xa0, 0x68, 0x00, 0x88, 0xc0, 0xf3, 0x01, 0x1a, 0x20, 0x68, - 0x0f, 0x46, 0x81, 0x88, 0x08, 0x0a, 0x00, 0xf0, 0x03, 0x00, 0x8d, 0xf8, - 0x04, 0x00, 0x90, 0x46, 0x01, 0xf0, 0x0f, 0x00, 0x8d, 0xf8, 0x05, 0x00, - 0x00, 0x25, 0x08, 0xeb, 0x85, 0x00, 0xb0, 0xf9, 0x02, 0x00, 0x38, 0xf9, - 0x25, 0x10, 0x00, 0xf0, 0x63, 0xfb, 0xa1, 0x68, 0x91, 0xf8, 0x24, 0x20, - 0x01, 0x46, 0xde, 0xa8, 0x00, 0xeb, 0x45, 0x10, 0xff, 0xf7, 0xfd, 0xfe, - 0x6d, 0x1c, 0x07, 0x2d, 0xeb, 0xd3, 0x00, 0x20, 0x02, 0xae, 0x37, 0xf9, - 0x20, 0x10, 0x46, 0xf8, 0x30, 0x10, 0x02, 0xaa, 0x07, 0xeb, 0x80, 0x01, - 0x02, 0xeb, 0xc0, 0x02, 0xb1, 0xf9, 0x02, 0x10, 0x51, 0x60, 0x40, 0x1c, - 0x05, 0x28, 0xf0, 0xd3, 0x00, 0x27, 0xa8, 0x25, 0x02, 0xe0, 0x00, 0xf0, - 0x29, 0xf8, 0x7f, 0x1c, 0x57, 0x45, 0xfa, 0xd3, 0x05, 0x2f, 0x1f, 0xd2, - 0x00, 0xf0, 0x22, 0xf8, 0xa7, 0xeb, 0x0a, 0x0b, 0x0c, 0xa8, 0x05, 0xfb, - 0x0b, 0x09, 0x02, 0xa8, 0x00, 0xeb, 0xcb, 0x03, 0xa0, 0x68, 0x4a, 0x46, - 0x51, 0x46, 0x0e, 0x30, 0xff, 0xf7, 0x40, 0xff, 0x20, 0x69, 0x9d, 0xf8, - 0x05, 0x30, 0xc0, 0xb2, 0x00, 0x90, 0x06, 0xeb, 0xcb, 0x02, 0x7f, 0x1c, - 0xd2, 0xe9, 0x00, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x48, 0x46, 0xfe, 0xf7, - 0x4f, 0xff, 0xdd, 0xe7, 0x0d, 0xf2, 0x5c, 0x4d, 0xbd, 0xe8, 0xf0, 0x8f, - 0xa0, 0x68, 0x00, 0x6a, 0x9d, 0xf8, 0x04, 0x30, 0x00, 0x90, 0x08, 0xeb, - 0x87, 0x02, 0xde, 0xa8, 0x00, 0xeb, 0x47, 0x11, 0x0c, 0xa8, 0x05, 0xfb, - 0x07, 0x00, 0xc0, 0xe6, 0x2d, 0xe9, 0xf6, 0x4f, 0xdf, 0xb0, 0x04, 0x46, - 0x01, 0x20, 0xa2, 0x68, 0xd2, 0x7e, 0x00, 0x21, 0xfb, 0xf7, 0x84, 0xff, - 0x04, 0xf0, 0x74, 0xf8, 0xcd, 0xe9, 0x0e, 0x01, 0x20, 0x69, 0x00, 0x28, - 0x14, 0xbf, 0xdf, 0xf8, 0x6c, 0x0b, 0xdf, 0xf8, 0x6c, 0x0b, 0x04, 0x90, - 0x00, 0x20, 0x02, 0x90, 0x5f, 0x98, 0x02, 0x99, 0xa8, 0x22, 0x02, 0xfb, - 0x01, 0x00, 0x00, 0x27, 0x03, 0x90, 0x04, 0x98, 0x02, 0x99, 0x00, 0xeb, - 0xc1, 0x00, 0x00, 0xeb, 0x07, 0x22, 0x00, 0xf0, 0xc5, 0xf9, 0x04, 0x46, - 0x88, 0x46, 0x5f, 0x98, 0xa8, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x06, 0x90, - 0x5f, 0x98, 0x02, 0x99, 0x00, 0xeb, 0xc7, 0x00, 0x07, 0x90, 0x5f, 0x98, - 0x00, 0xeb, 0xc1, 0x00, 0x05, 0x90, 0x02, 0x98, 0xb8, 0x42, 0x37, 0xd1, - 0x38, 0xb1, 0xdd, 0xe9, 0x0e, 0x01, 0x22, 0x46, 0x43, 0x46, 0x04, 0xf0, - 0x5f, 0xf8, 0x04, 0x46, 0x88, 0x46, 0x00, 0x25, 0x21, 0xe0, 0xa8, 0x20, - 0x00, 0xfb, 0x05, 0xf2, 0x05, 0x98, 0x13, 0x18, 0xd3, 0xe9, 0x00, 0x01, - 0x07, 0x9b, 0xd6, 0x18, 0xd6, 0xe9, 0x00, 0x23, 0x04, 0xf0, 0xc2, 0xf8, - 0x06, 0x46, 0x03, 0x98, 0x00, 0xeb, 0xc5, 0x02, 0x89, 0x46, 0xd2, 0xe9, - 0x00, 0x01, 0x06, 0x9a, 0x02, 0xeb, 0xc5, 0x0c, 0x6d, 0x1c, 0xdc, 0xe9, - 0x00, 0x23, 0x04, 0xf0, 0xb3, 0xf8, 0x00, 0xf0, 0x7f, 0xf9, 0x00, 0xf0, - 0x6c, 0xf9, 0x04, 0x46, 0x88, 0x46, 0xbd, 0x42, 0xdb, 0xdb, 0x20, 0x46, - 0x41, 0x46, 0x04, 0xf0, 0x79, 0xf9, 0x03, 0x9a, 0x02, 0x9b, 0x02, 0xeb, - 0xc3, 0x02, 0x5c, 0xe0, 0x04, 0x98, 0x02, 0x99, 0x00, 0xeb, 0x01, 0x20, - 0x00, 0xeb, 0xc7, 0x02, 0x00, 0x25, 0x00, 0xf0, 0x71, 0xf9, 0x40, 0xe0, - 0x06, 0x98, 0x00, 0xeb, 0xc5, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0xcd, 0xe9, - 0x0c, 0x01, 0x00, 0xf0, 0x46, 0xf9, 0xcd, 0xe9, 0x0a, 0x01, 0xa8, 0x20, - 0x00, 0xfb, 0x05, 0xf2, 0x07, 0x98, 0x13, 0x18, 0x6d, 0x1c, 0xd3, 0xe9, - 0x00, 0x01, 0xcd, 0xe9, 0x08, 0x01, 0x05, 0x98, 0x10, 0x18, 0xd0, 0xe9, - 0x00, 0xab, 0xdd, 0xe9, 0x08, 0x01, 0x00, 0xf0, 0x28, 0xf9, 0xcd, 0xe9, - 0x00, 0x01, 0xdd, 0xe9, 0x0a, 0x23, 0xdd, 0xe9, 0x0c, 0x01, 0x04, 0xf0, - 0x73, 0xf8, 0xdd, 0xe9, 0x00, 0x23, 0x03, 0xf0, 0xfb, 0xff, 0x00, 0xf0, - 0x2a, 0xf9, 0x04, 0x46, 0x88, 0x46, 0xdd, 0xe9, 0x0c, 0x01, 0x00, 0xf0, - 0x14, 0xf9, 0x82, 0x46, 0x8b, 0x46, 0xdd, 0xe9, 0x0a, 0x23, 0xdd, 0xe9, - 0x08, 0x01, 0x04, 0xf0, 0x5f, 0xf8, 0x02, 0x46, 0x0b, 0x46, 0x50, 0x46, - 0x59, 0x46, 0x04, 0xf0, 0xa3, 0xf9, 0x00, 0xf0, 0x25, 0xf9, 0x06, 0x46, - 0x89, 0x46, 0xbd, 0x42, 0xba, 0xdb, 0x06, 0x9a, 0x00, 0xf0, 0x37, 0xf9, - 0x00, 0xf0, 0x20, 0xf9, 0x05, 0x9a, 0xa8, 0x23, 0x03, 0xfb, 0x07, 0x22, - 0x00, 0xf0, 0x0e, 0xf9, 0x03, 0x9a, 0x02, 0xeb, 0xc7, 0x02, 0xc2, 0xe9, - 0x00, 0x01, 0x02, 0x98, 0x7f, 0x1c, 0xb8, 0x42, 0xbf, 0xf6, 0x49, 0xaf, - 0x40, 0x1c, 0x15, 0x28, 0x02, 0x90, 0xff, 0xf6, 0x3d, 0xaf, 0x00, 0x27, - 0x04, 0x98, 0x00, 0xeb, 0x07, 0x22, 0x7d, 0x1e, 0xd2, 0xe9, 0x2a, 0x01, - 0x03, 0xf0, 0x8e, 0xff, 0x04, 0x46, 0x04, 0x98, 0x00, 0xeb, 0xc7, 0x00, - 0x00, 0xf5, 0xa8, 0x52, 0x88, 0x46, 0x00, 0xf0, 0xff, 0xf8, 0x06, 0x46, - 0x89, 0x46, 0x5f, 0x98, 0xa8, 0x21, 0x01, 0xfb, 0x07, 0x00, 0x03, 0x90, - 0x3d, 0xe0, 0x00, 0xf0, 0xd4, 0xf8, 0xcd, 0xe9, 0x06, 0x01, 0x00, 0xf0, - 0xf5, 0xf8, 0x00, 0xeb, 0x05, 0x10, 0x02, 0x90, 0x5b, 0x46, 0x0a, 0xa8, - 0x00, 0xeb, 0x05, 0x12, 0xd2, 0xe9, 0x00, 0x01, 0x52, 0x46, 0x04, 0xf0, - 0x0d, 0xf8, 0xcd, 0xe9, 0x00, 0x01, 0xdd, 0xf8, 0x08, 0xc0, 0xdd, 0xe9, - 0x06, 0x23, 0xdc, 0xe9, 0x02, 0x01, 0x04, 0xf0, 0x03, 0xf8, 0xdd, 0xe9, - 0x00, 0x23, 0x03, 0xf0, 0x8b, 0xff, 0x00, 0xf0, 0xba, 0xf8, 0x04, 0x46, - 0x0a, 0xa8, 0x00, 0xeb, 0x05, 0x1c, 0x88, 0x46, 0xdd, 0xe9, 0x06, 0x23, - 0xdc, 0xe9, 0x00, 0x01, 0x03, 0xf0, 0xf2, 0xff, 0xdd, 0xf8, 0x08, 0xc0, - 0xcd, 0xe9, 0x00, 0x01, 0xdc, 0xe9, 0x02, 0x23, 0x50, 0x46, 0x59, 0x46, - 0x03, 0xf0, 0xe8, 0xff, 0x00, 0xf0, 0x97, 0xf8, 0x00, 0xf0, 0xb2, 0xf8, - 0x06, 0x46, 0x89, 0x46, 0x6d, 0x1e, 0x00, 0x2d, 0xbf, 0xd5, 0x00, 0xf0, - 0xc3, 0xf8, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, 0x9c, 0xf8, 0x0a, 0xaa, - 0x02, 0xeb, 0x07, 0x12, 0x7f, 0x1c, 0xc2, 0xe9, 0x02, 0x01, 0x15, 0x2f, - 0x98, 0xdb, 0x14, 0x27, 0x0a, 0xa8, 0x00, 0xeb, 0x07, 0x10, 0xa8, 0x21, - 0xd0, 0xe9, 0x00, 0x48, 0x0a, 0xa8, 0x00, 0xeb, 0x07, 0x10, 0x04, 0x90, - 0xd0, 0xe9, 0x02, 0x69, 0x5f, 0x98, 0x01, 0xfb, 0x07, 0x00, 0x7d, 0x1c, - 0x03, 0x90, 0x41, 0xe0, 0x00, 0xf0, 0x73, 0xf8, 0xcd, 0xe9, 0x08, 0x01, - 0x00, 0xf0, 0x94, 0xf8, 0x00, 0xeb, 0x05, 0x13, 0xd3, 0xe9, 0x00, 0x01, - 0xcd, 0xe9, 0x06, 0x01, 0x5b, 0x46, 0x0a, 0xa8, 0x00, 0xeb, 0x05, 0x10, - 0x02, 0x90, 0x02, 0x46, 0x6d, 0x1c, 0xd2, 0xe9, 0x02, 0x01, 0x52, 0x46, - 0x03, 0xf0, 0xa6, 0xff, 0xcd, 0xe9, 0x00, 0x01, 0xdd, 0xe9, 0x08, 0x23, - 0xdd, 0xe9, 0x06, 0x01, 0x03, 0xf0, 0x9e, 0xff, 0x00, 0xf0, 0x4d, 0xf8, - 0x22, 0x46, 0x43, 0x46, 0x03, 0xf0, 0x24, 0xff, 0x04, 0x46, 0x88, 0x46, - 0xdd, 0xe9, 0x06, 0x01, 0x00, 0xf0, 0x3f, 0xf8, 0xdd, 0xf8, 0x08, 0xc0, - 0x82, 0x46, 0x8b, 0x46, 0xdd, 0xe9, 0x08, 0x23, 0xdc, 0xe9, 0x02, 0x01, - 0x03, 0xf0, 0x88, 0xff, 0x52, 0x46, 0x5b, 0x46, 0x03, 0xf0, 0x10, 0xff, - 0x02, 0x46, 0x0b, 0x46, 0x30, 0x46, 0x49, 0x46, 0x04, 0xf0, 0xc8, 0xf8, - 0x06, 0x46, 0x89, 0x46, 0x15, 0x2d, 0xbb, 0xdb, 0x00, 0xf0, 0x5e, 0xf8, - 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, 0x37, 0xf8, 0x04, 0x9a, 0x7f, 0x1e, - 0xc2, 0xe9, 0x02, 0x01, 0x9e, 0xd5, 0x00, 0x24, 0x0a, 0xa8, 0x00, 0xeb, - 0x04, 0x12, 0xd2, 0xe9, 0x00, 0x01, 0x04, 0xf0, 0x71, 0xf9, 0x60, 0x99, - 0x41, 0xf8, 0x34, 0x00, 0x0a, 0xa8, 0x00, 0xeb, 0x04, 0x12, 0xd2, 0xe9, - 0x02, 0x01, 0x04, 0xf0, 0x67, 0xf9, 0x60, 0x99, 0x01, 0xeb, 0xc4, 0x01, - 0x64, 0x1c, 0x15, 0x2c, 0x48, 0x60, 0xe7, 0xdb, 0x61, 0xb0, 0xbd, 0xe8, - 0xf0, 0x8f, 0x52, 0x46, 0x5b, 0x46, 0x03, 0xf0, 0x4f, 0xbf, 0x02, 0x46, - 0x0b, 0x46, 0xdd, 0xe9, 0x00, 0x01, 0x04, 0xf0, 0x93, 0xb8, 0x03, 0x98, - 0x00, 0xeb, 0xc5, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x70, 0x47, 0x02, 0x46, - 0x0b, 0x46, 0x20, 0x46, 0x41, 0x46, 0x04, 0xf0, 0x87, 0xb8, 0x0a, 0xaa, - 0x02, 0xeb, 0x07, 0x12, 0x4b, 0x46, 0xc2, 0xe9, 0x00, 0x01, 0x32, 0x46, - 0x28, 0x46, 0x59, 0x46, 0x03, 0xf0, 0x32, 0xbf, 0x32, 0x46, 0x4b, 0x46, - 0x03, 0xf0, 0xba, 0xbe, 0x05, 0x46, 0x8b, 0x46, 0x22, 0x46, 0x43, 0x46, - 0x03, 0xf0, 0x28, 0xbf, 0xd2, 0xe9, 0x00, 0x01, 0x03, 0xf0, 0x82, 0xbe, - 0x5f, 0x98, 0x00, 0xeb, 0xc7, 0x00, 0xa8, 0x21, 0x01, 0xfb, 0x05, 0x00, - 0xd0, 0xe9, 0x00, 0xab, 0x0a, 0xa8, 0x70, 0x47, 0x03, 0x9a, 0xdf, 0xf8, - 0xa0, 0x17, 0x02, 0xeb, 0xc7, 0x0c, 0x00, 0x20, 0xdc, 0xe9, 0x00, 0x23, - 0x04, 0xf0, 0x62, 0xb9, 0x2d, 0xe9, 0xf0, 0x4f, 0x89, 0xb0, 0x90, 0x46, - 0x04, 0x46, 0x12, 0x9a, 0x9b, 0x46, 0x68, 0x46, 0xff, 0xf7, 0x9f, 0xfc, - 0x00, 0x20, 0x00, 0x21, 0x44, 0xf8, 0x30, 0x10, 0x04, 0xeb, 0xc0, 0x02, - 0x40, 0x1c, 0x04, 0x28, 0x51, 0x60, 0xf7, 0xd3, 0x00, 0x27, 0x00, 0x25, - 0x4f, 0xf0, 0x6a, 0x59, 0x2b, 0xfa, 0x05, 0xf0, 0xc0, 0x07, 0x27, 0xd5, - 0x05, 0xf0, 0x07, 0x00, 0x5d, 0xf8, 0x20, 0x00, 0xfb, 0xf7, 0x46, 0xf9, - 0x82, 0x46, 0x58, 0xf8, 0x37, 0x00, 0x51, 0x46, 0xfb, 0xf7, 0xe8, 0xfa, - 0x49, 0x46, 0xfb, 0xf7, 0xe5, 0xfa, 0xee, 0x08, 0x54, 0xf8, 0x36, 0x10, - 0xfb, 0xf7, 0x44, 0xfa, 0x51, 0x46, 0x44, 0xf8, 0x36, 0x00, 0x04, 0xeb, - 0xc6, 0x06, 0x08, 0xeb, 0xc7, 0x00, 0x7f, 0x1c, 0x40, 0x68, 0xfb, 0xf7, - 0xd5, 0xfa, 0x49, 0x46, 0xfb, 0xf7, 0xd2, 0xfa, 0x71, 0x68, 0xfb, 0xf7, - 0x33, 0xfa, 0x15, 0x2f, 0x70, 0x60, 0x02, 0xd2, 0x6d, 0x1c, 0x20, 0x2d, - 0xd0, 0xd3, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x4f, - 0x0d, 0x46, 0x9d, 0xb0, 0x82, 0x46, 0xa8, 0x68, 0x00, 0x88, 0x00, 0x0a, - 0x00, 0xf0, 0x03, 0x04, 0x00, 0x26, 0x0a, 0xeb, 0x86, 0x00, 0xb0, 0xf9, - 0x02, 0x00, 0x3a, 0xf9, 0x26, 0x10, 0x00, 0xf0, 0xa9, 0xf8, 0xa9, 0x68, - 0x20, 0x31, 0x0a, 0x79, 0x00, 0x92, 0x05, 0xf1, 0x14, 0x02, 0x0b, 0x68, - 0x01, 0x46, 0x04, 0xa8, 0x00, 0xeb, 0x46, 0x10, 0xff, 0xf7, 0x96, 0xff, - 0x76, 0x1c, 0x03, 0x2e, 0xe7, 0xd3, 0xa0, 0x07, 0x4c, 0xbf, 0x40, 0x27, - 0x20, 0x27, 0xba, 0xf9, 0x06, 0x00, 0xfb, 0xf7, 0xf3, 0xf8, 0x04, 0xae, - 0x05, 0x46, 0x71, 0x68, 0xf0, 0x6a, 0xfb, 0xf7, 0xf9, 0xf9, 0x83, 0x46, - 0xba, 0xf9, 0x02, 0x00, 0xfb, 0xf7, 0xe8, 0xf8, 0x03, 0x90, 0xba, 0xf9, - 0x04, 0x00, 0xfb, 0xf7, 0xe3, 0xf8, 0x80, 0x46, 0x04, 0x99, 0xb0, 0x6a, - 0xfb, 0xf7, 0xea, 0xf9, 0x81, 0x46, 0xba, 0xf9, 0x00, 0x00, 0xfb, 0xf7, - 0xd9, 0xf8, 0x82, 0x46, 0x04, 0xa8, 0x3f, 0x18, 0x49, 0x46, 0xb8, 0x69, - 0xfb, 0xf7, 0xde, 0xf9, 0x51, 0x46, 0xfb, 0xf7, 0x77, 0xfa, 0x00, 0x90, - 0x41, 0x46, 0x30, 0x69, 0xfb, 0xf7, 0x72, 0xfa, 0x00, 0x99, 0xfb, 0xf7, - 0xd3, 0xf9, 0x01, 0x90, 0x59, 0x46, 0xf8, 0x69, 0xfb, 0xf7, 0xce, 0xf9, - 0x03, 0x99, 0xfb, 0xf7, 0x67, 0xfa, 0x00, 0x90, 0x29, 0x46, 0x70, 0x69, - 0xfb, 0xf7, 0x62, 0xfa, 0x00, 0x99, 0xfb, 0xf7, 0xc3, 0xf9, 0x01, 0x46, - 0x01, 0x98, 0xfb, 0xf7, 0x4b, 0xf9, 0xfb, 0xf7, 0xc5, 0xfa, 0xad, 0xf8, - 0x08, 0x00, 0x49, 0x46, 0xb8, 0x69, 0xfb, 0xf7, 0xb7, 0xf9, 0x03, 0x99, - 0xfb, 0xf7, 0x50, 0xfa, 0x81, 0x46, 0x30, 0x69, 0x00, 0xf0, 0x98, 0xf8, - 0x49, 0x46, 0xfb, 0xf7, 0xad, 0xf9, 0x81, 0x46, 0xf8, 0x69, 0x59, 0x46, - 0xfb, 0xf7, 0xa8, 0xf9, 0x51, 0x46, 0xfb, 0xf7, 0x41, 0xfa, 0x83, 0x46, - 0x70, 0x69, 0x00, 0xf0, 0x15, 0xff, 0x59, 0x46, 0xfb, 0xf7, 0x9e, 0xf9, - 0x49, 0x46, 0xfb, 0xf7, 0x9b, 0xf9, 0xfb, 0xf7, 0xa1, 0xfa, 0x06, 0x46, - 0xe0, 0x07, 0xad, 0xf8, 0x0a, 0x60, 0x21, 0xd5, 0xbd, 0xf8, 0x08, 0x40, - 0xb8, 0x69, 0x00, 0xf0, 0x03, 0xff, 0x83, 0x46, 0xf8, 0x69, 0x00, 0xf0, - 0x73, 0xf8, 0x01, 0x46, 0x58, 0x46, 0xfb, 0xf7, 0x13, 0xf9, 0xfb, 0xf7, - 0x8d, 0xfa, 0x00, 0x19, 0xad, 0xf8, 0x08, 0x00, 0x29, 0x46, 0xb8, 0x69, - 0xfb, 0xf7, 0x1a, 0xfa, 0x04, 0x46, 0xf8, 0x69, 0x00, 0xf0, 0xee, 0xfe, - 0x21, 0x46, 0xfb, 0xf7, 0x77, 0xf9, 0xfb, 0xf7, 0x7d, 0xfa, 0x80, 0x19, - 0xad, 0xf8, 0x0a, 0x00, 0x02, 0x98, 0x1d, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, - 0x40, 0x43, 0x01, 0xfb, 0x01, 0x00, 0x00, 0xeb, 0xd0, 0x70, 0x40, 0x10, - 0xff, 0xf7, 0x86, 0xbb, 0x01, 0xb4, 0xbd, 0xf9, 0x02, 0x00, 0xbd, 0xf9, - 0x00, 0x10, 0x40, 0x43, 0x01, 0xfb, 0x01, 0x00, 0x01, 0xb0, 0x70, 0x47, - 0x49, 0x43, 0x00, 0xfb, 0x00, 0x10, 0x70, 0x47, 0x38, 0xb5, 0x0d, 0x46, - 0x01, 0x46, 0xfb, 0xf7, 0xef, 0xf9, 0x04, 0x46, 0x28, 0x46, 0x00, 0xf0, - 0x37, 0xf8, 0x21, 0x46, 0xbd, 0xe8, 0x34, 0x40, 0xfb, 0xf7, 0x4a, 0xb9, - 0x2d, 0xe9, 0xf9, 0x42, 0x82, 0xb0, 0x0c, 0x46, 0xbd, 0xf9, 0x0a, 0x00, - 0x15, 0x46, 0xfb, 0xf7, 0x35, 0xf8, 0x07, 0x46, 0xbd, 0xf9, 0x08, 0x00, - 0xfb, 0xf7, 0x30, 0xf8, 0x06, 0x46, 0x20, 0x46, 0x31, 0x46, 0xfb, 0xf7, - 0xd3, 0xf9, 0x81, 0x46, 0x38, 0x46, 0x00, 0xf0, 0x1b, 0xf8, 0x01, 0x46, - 0x48, 0x46, 0xfb, 0xf7, 0xbb, 0xf8, 0xfb, 0xf7, 0x35, 0xfa, 0xad, 0xf8, - 0x00, 0x00, 0x39, 0x46, 0x20, 0x46, 0xfb, 0xf7, 0xc3, 0xf9, 0x04, 0x46, - 0x30, 0x46, 0x00, 0xf0, 0x0b, 0xf8, 0x21, 0x46, 0xfb, 0xf7, 0x20, 0xf9, - 0xfb, 0xf7, 0x26, 0xfa, 0xad, 0xf8, 0x02, 0x00, 0x00, 0x98, 0x04, 0xb0, - 0xbd, 0xe8, 0xf0, 0x82, 0x29, 0x46, 0xfb, 0xf7, 0xb1, 0xb9, 0x0e, 0xb4, - 0x2d, 0xe9, 0xf0, 0x4a, 0x84, 0xb0, 0x81, 0x46, 0x0f, 0x98, 0x00, 0x28, - 0x14, 0xbf, 0x4f, 0xf0, 0xff, 0x37, 0x01, 0x27, 0xdd, 0xe9, 0x0d, 0x45, - 0x93, 0x46, 0x20, 0x46, 0xfb, 0xf7, 0xa0, 0xf9, 0x00, 0x90, 0x38, 0x46, - 0xfa, 0xf7, 0xf4, 0xff, 0x59, 0x46, 0xfb, 0xf7, 0x99, 0xf9, 0xff, 0xf7, - 0xe3, 0xff, 0x01, 0x46, 0x00, 0x98, 0xfb, 0xf7, 0x83, 0xf8, 0x06, 0x46, - 0x20, 0x46, 0x59, 0x46, 0xfb, 0xf7, 0x8e, 0xf9, 0x04, 0x46, 0x38, 0x46, - 0xfa, 0xf7, 0xe2, 0xff, 0x0b, 0x99, 0xfb, 0xf7, 0x87, 0xf9, 0xff, 0xf7, - 0xd1, 0xff, 0x21, 0x46, 0xfb, 0xf7, 0xe6, 0xf8, 0xc9, 0xe9, 0x00, 0x60, - 0x04, 0xb0, 0xbd, 0xe8, 0xf0, 0x0a, 0x5d, 0xf8, 0x10, 0xfb, 0xfe, 0xb5, - 0x06, 0x46, 0x10, 0x46, 0x19, 0x46, 0xfa, 0xf7, 0x9b, 0xff, 0x07, 0x46, - 0xdd, 0xe9, 0x08, 0x01, 0xfa, 0xf7, 0x96, 0xff, 0x39, 0x46, 0xfa, 0xf7, - 0xdf, 0xff, 0x05, 0x46, 0xdd, 0xe9, 0x0a, 0x01, 0xfa, 0xf7, 0x8e, 0xff, - 0x39, 0x46, 0xfa, 0xf7, 0xd7, 0xff, 0x07, 0x46, 0x28, 0x46, 0x39, 0x46, - 0xff, 0xf7, 0x6c, 0xff, 0x04, 0x46, 0x29, 0x46, 0xdf, 0xf8, 0x88, 0x0d, - 0xfb, 0xf7, 0x5a, 0xf9, 0x21, 0x46, 0xfa, 0xf7, 0xc9, 0xff, 0x04, 0x46, - 0x28, 0x46, 0x39, 0x46, 0xff, 0xf7, 0x5e, 0xff, 0x05, 0x46, 0xdf, 0xf8, - 0x74, 0x0d, 0x39, 0x46, 0xfb, 0xf7, 0x4c, 0xf9, 0x29, 0x46, 0xfa, 0xf7, - 0xbb, 0xff, 0xc6, 0xe9, 0x00, 0x40, 0xfe, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, - 0x07, 0x46, 0x8f, 0xb0, 0x38, 0x68, 0x00, 0x22, 0xc0, 0xe9, 0x06, 0x22, - 0xc0, 0xe9, 0x04, 0x22, 0xc0, 0xe9, 0x02, 0x22, 0x00, 0x24, 0x0d, 0xf1, - 0x04, 0x0a, 0x0d, 0xf1, 0x20, 0x09, 0x38, 0x69, 0x07, 0x23, 0x01, 0xaa, - 0x08, 0xa9, 0xfe, 0xf7, 0x03, 0xfb, 0xf8, 0xf7, 0x44, 0xfd, 0x48, 0xb1, - 0x38, 0x46, 0xfe, 0xf7, 0x96, 0xfb, 0x38, 0x46, 0xfe, 0xf7, 0x79, 0xfb, - 0x64, 0x1e, 0x00, 0x28, 0x40, 0xd0, 0x56, 0xe0, 0x00, 0x25, 0x01, 0xa8, - 0x00, 0xeb, 0x85, 0x06, 0xd7, 0xf8, 0x00, 0xc0, 0xb6, 0xf9, 0x02, 0xb0, - 0x08, 0xa8, 0x00, 0xeb, 0x85, 0x08, 0xdc, 0xe9, 0x02, 0x01, 0x02, 0x46, - 0x0b, 0x46, 0xb8, 0xf9, 0x02, 0xe0, 0x39, 0xf9, 0x25, 0x00, 0x3a, 0xf9, - 0x25, 0x10, 0x0b, 0xfb, 0x0e, 0xfe, 0x01, 0xfb, 0x00, 0xe0, 0xc1, 0x17, - 0x10, 0x18, 0x59, 0x41, 0xcc, 0xe9, 0x02, 0x01, 0x39, 0xf9, 0x25, 0x20, - 0xb6, 0xf9, 0x02, 0x30, 0x3a, 0xf9, 0x25, 0x60, 0x5a, 0x43, 0xdc, 0xe9, - 0x04, 0x01, 0xb8, 0xf9, 0x02, 0x30, 0x06, 0xfb, 0x13, 0x22, 0x80, 0x18, - 0x41, 0xeb, 0xe2, 0x71, 0xcc, 0xe9, 0x04, 0x01, 0x59, 0xf8, 0x25, 0x00, - 0x00, 0x90, 0xff, 0xf7, 0xeb, 0xfe, 0x3e, 0x68, 0x00, 0x21, 0xd6, 0xe9, - 0x06, 0x23, 0x10, 0x18, 0x59, 0x41, 0xc6, 0xe9, 0x06, 0x01, 0x6d, 0x1c, - 0x07, 0x2d, 0xc0, 0xdb, 0x64, 0x1c, 0x80, 0x2c, 0xa9, 0xdb, 0x3a, 0x68, - 0xb8, 0x68, 0x80, 0x8b, 0xd2, 0xe9, 0x06, 0x45, 0xa0, 0xfb, 0x00, 0x23, - 0x4f, 0xf4, 0x60, 0x70, 0xa0, 0xfb, 0x02, 0x68, 0x00, 0xfb, 0x03, 0x88, - 0x45, 0x45, 0x03, 0xd8, 0x2c, 0xbf, 0xb4, 0x42, 0x07, 0x20, 0x00, 0xd3, - 0x00, 0x20, 0x0f, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf1, 0x4f, - 0xad, 0xf5, 0x06, 0x7d, 0x84, 0x68, 0x00, 0x68, 0x03, 0x90, 0x20, 0x21, - 0x7e, 0xa8, 0xfb, 0xf7, 0x6d, 0xff, 0x66, 0xa8, 0x60, 0x21, 0xfb, 0xf7, - 0x69, 0xff, 0x3c, 0xa8, 0xa8, 0x21, 0xfb, 0xf7, 0x65, 0xff, 0x12, 0xa8, - 0xa8, 0x21, 0xfb, 0xf7, 0x61, 0xff, 0x07, 0xa8, 0x00, 0x21, 0x00, 0x22, - 0x06, 0xc0, 0x03, 0x98, 0xd4, 0x30, 0x02, 0x90, 0x00, 0x68, 0xfb, 0xf7, - 0x87, 0xf8, 0x05, 0xd1, 0x02, 0x98, 0x40, 0x68, 0xfb, 0xf7, 0x82, 0xf8, - 0x00, 0xf0, 0xf2, 0x80, 0x03, 0x9a, 0x0d, 0xf5, 0xfc, 0x7a, 0xd2, 0xe9, - 0x08, 0x01, 0xff, 0xf7, 0xa5, 0xfe, 0x02, 0x9a, 0x09, 0x90, 0xd2, 0xe9, - 0x00, 0x01, 0xff, 0xf7, 0x9f, 0xfe, 0x04, 0x90, 0x01, 0x20, 0x01, 0x90, - 0x02, 0x98, 0xd0, 0xe9, 0x00, 0x9b, 0x03, 0x98, 0xcd, 0xf8, 0x00, 0xb0, - 0x4b, 0x46, 0xd0, 0xe9, 0x08, 0x9b, 0x49, 0x46, 0x5a, 0x46, 0x05, 0xa8, - 0xff, 0xf7, 0xd1, 0xfe, 0x05, 0x98, 0x04, 0x99, 0xfa, 0xf7, 0xf0, 0xfe, - 0x05, 0x90, 0x4f, 0xf0, 0x8c, 0x49, 0x06, 0x98, 0x04, 0x99, 0xfa, 0xf7, - 0xe9, 0xfe, 0x02, 0x99, 0x06, 0x90, 0x09, 0x89, 0x34, 0xf8, 0x0c, 0x2f, - 0x8d, 0x1a, 0x49, 0x46, 0xfb, 0xf7, 0x6e, 0xf8, 0xfb, 0xf7, 0xd8, 0xf8, - 0xad, 0xf8, 0x06, 0x00, 0x49, 0x46, 0x05, 0x98, 0xfb, 0xf7, 0x66, 0xf8, - 0xfb, 0xf7, 0xd0, 0xf8, 0xad, 0xf8, 0x04, 0x00, 0x0d, 0xf1, 0x48, 0x0b, - 0x0b, 0xe0, 0x00, 0xbf, 0x00, 0x98, 0x41, 0x1e, 0x00, 0x28, 0x00, 0x91, - 0xf9, 0xd1, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, 0x04, 0x0f, 0x6f, 0xd3, - 0x6d, 0x1c, 0x02, 0x99, 0x09, 0x89, 0xe8, 0xb2, 0x88, 0x42, 0x80, 0xf0, - 0x9f, 0x80, 0xfe, 0xf7, 0x6c, 0xf9, 0x80, 0x03, 0xff, 0xf7, 0xcc, 0xf9, - 0x01, 0x46, 0x20, 0x7e, 0x00, 0x90, 0x00, 0x27, 0x03, 0x98, 0x63, 0x69, - 0x00, 0xf1, 0x28, 0x02, 0x0a, 0xa8, 0xff, 0xf7, 0x2d, 0xfd, 0x0a, 0xa8, - 0x49, 0x46, 0x50, 0xf8, 0x37, 0x00, 0xfb, 0xf7, 0x37, 0xf8, 0xfb, 0xf7, - 0xa1, 0xf8, 0x4a, 0xf8, 0x37, 0x00, 0x49, 0x46, 0x0a, 0xa8, 0x00, 0xeb, - 0xc7, 0x00, 0x40, 0x68, 0xfb, 0xf7, 0x2c, 0xf8, 0xfb, 0xf7, 0x96, 0xf8, - 0x7e, 0xa9, 0x01, 0xeb, 0xc7, 0x01, 0x7f, 0x1c, 0x04, 0x2f, 0x48, 0x60, - 0xe5, 0xdb, 0xe8, 0xb2, 0xfe, 0xf7, 0x41, 0xf9, 0xfa, 0xf7, 0x80, 0xfe, - 0x4f, 0xf0, 0x8d, 0x41, 0xfb, 0xf7, 0x1a, 0xf8, 0x09, 0x99, 0xfb, 0xf7, - 0x17, 0xf8, 0x04, 0x99, 0xfa, 0xf7, 0x86, 0xfe, 0x01, 0xf0, 0x12, 0xff, - 0xff, 0xf7, 0x94, 0xf9, 0x07, 0x46, 0xbd, 0xf8, 0x04, 0x00, 0xad, 0xf8, - 0x1c, 0x00, 0x00, 0x26, 0xbd, 0xf8, 0x06, 0x00, 0xad, 0xf8, 0x1e, 0x00, - 0xbd, 0xf8, 0x04, 0x00, 0xad, 0xf8, 0x20, 0x00, 0xbd, 0xf8, 0x06, 0x00, - 0xad, 0xf8, 0x22, 0x00, 0x22, 0x7e, 0x66, 0xa8, 0x39, 0x46, 0x00, 0xeb, - 0x46, 0x10, 0xff, 0xf7, 0x90, 0xf9, 0x76, 0x1c, 0x03, 0x2e, 0xf5, 0xdb, - 0x07, 0xaa, 0x86, 0x98, 0x80, 0x68, 0x00, 0x6a, 0x00, 0x90, 0x66, 0xa9, - 0x03, 0x98, 0x80, 0x88, 0x00, 0x0a, 0x00, 0xf0, 0x03, 0x03, 0x3c, 0xa8, - 0xff, 0xf7, 0x93, 0xf9, 0x00, 0x26, 0xb0, 0x46, 0x00, 0x27, 0x00, 0x20, - 0x4b, 0xf8, 0x37, 0x00, 0x12, 0xa9, 0x01, 0xeb, 0xc7, 0x01, 0x7f, 0x1c, - 0x15, 0x2f, 0x48, 0x60, 0xf6, 0xdb, 0x61, 0x69, 0x00, 0xeb, 0xc8, 0x02, - 0xd1, 0x40, 0xc9, 0x07, 0x0f, 0xd5, 0x3c, 0xa9, 0x12, 0xaa, 0x51, 0xf8, - 0x36, 0x10, 0x4b, 0xf8, 0x36, 0x10, 0x02, 0xeb, 0xc6, 0x02, 0x3c, 0xa9, - 0x01, 0xeb, 0xc6, 0x01, 0x76, 0x1c, 0x49, 0x68, 0x51, 0x60, 0x15, 0x2e, - 0x02, 0xd2, 0x40, 0x1c, 0x08, 0x28, 0xe6, 0xd3, 0x86, 0x98, 0x00, 0x69, - 0xc0, 0xb2, 0x00, 0x90, 0x0a, 0xeb, 0xc8, 0x02, 0x00, 0x23, 0xd2, 0xe9, - 0x00, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x12, 0xa8, 0xfe, 0xf7, 0xda, 0xf9, - 0x4f, 0xf4, 0xc8, 0x70, 0x00, 0x90, 0x4f, 0xe7, 0x0d, 0xf5, 0x07, 0x7d, - 0xbd, 0xe8, 0xf0, 0x8f, 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x00, 0x25, - 0x00, 0x26, 0x54, 0xf8, 0x26, 0x00, 0x00, 0x90, 0x76, 0x1c, 0xff, 0xf7, - 0x9d, 0xfd, 0x45, 0x19, 0x07, 0x2e, 0xf6, 0xd3, 0x28, 0x46, 0x76, 0xbd, - 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x00, 0x25, 0x00, 0x26, 0x54, 0xf8, - 0x26, 0x00, 0x00, 0x90, 0xff, 0xf7, 0x8e, 0xfd, 0x85, 0x42, 0x38, 0xbf, - 0x05, 0x46, 0x76, 0x1c, 0x07, 0x2e, 0xf4, 0xd3, 0x28, 0x46, 0x76, 0xbd, - 0x38, 0xb5, 0x00, 0x24, 0x02, 0xfb, 0x02, 0xf5, 0x11, 0xb9, 0xff, 0xf7, - 0xe7, 0xff, 0x03, 0xe0, 0xff, 0xf7, 0xd4, 0xff, 0xc5, 0xeb, 0xc5, 0x05, - 0xa8, 0x42, 0x28, 0xbf, 0x01, 0x24, 0x20, 0x46, 0x32, 0xbd, 0xc9, 0xb2, - 0x51, 0xb1, 0x15, 0x29, 0x08, 0xda, 0xc0, 0x68, 0x00, 0xeb, 0x81, 0x01, - 0x0a, 0x6c, 0x52, 0x1c, 0x0a, 0x64, 0x01, 0x6c, 0x49, 0x1c, 0x01, 0x64, - 0x70, 0x47, 0x03, 0x68, 0x00, 0xf1, 0x08, 0x01, 0x03, 0xf1, 0x14, 0x02, - 0x18, 0x46, 0xff, 0xf7, 0x4d, 0xba, 0x10, 0xb5, 0x82, 0xb0, 0x04, 0x46, - 0x6a, 0x46, 0x00, 0x21, 0x00, 0x20, 0xf7, 0xf7, 0xa2, 0xfc, 0x00, 0x98, - 0xdf, 0xf8, 0x84, 0x29, 0x04, 0x60, 0x00, 0x21, 0x00, 0x20, 0xf7, 0xf7, - 0x26, 0xfd, 0x00, 0x20, 0xf7, 0xf7, 0xdf, 0xfc, 0x13, 0xbd, 0x00, 0x00, - 0x00, 0x20, 0x70, 0x59, 0x00, 0x00, 0x70, 0x59, 0x00, 0x00, 0xf0, 0x3f, - 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0xd3, 0xb0, 0xa3, 0x68, 0x08, 0x93, - 0x20, 0x68, 0x08, 0x9a, 0x05, 0x90, 0xe1, 0x68, 0x06, 0x91, 0x00, 0x21, - 0x10, 0x91, 0x0f, 0x91, 0x0e, 0x91, 0x08, 0x99, 0x24, 0x31, 0x04, 0x91, - 0x05, 0x99, 0x01, 0xf5, 0xcc, 0x71, 0x09, 0x91, 0x05, 0x99, 0x12, 0x88, - 0x89, 0x88, 0x22, 0xf4, 0x00, 0x62, 0x91, 0x42, 0x0b, 0xd1, 0x09, 0x99, - 0x08, 0x9a, 0x49, 0x68, 0x12, 0x6a, 0x91, 0x42, 0x05, 0xd1, 0x09, 0x99, - 0x04, 0x9a, 0x09, 0x7a, 0x12, 0x78, 0x91, 0x42, 0x03, 0xd0, 0x22, 0x69, - 0x06, 0x99, 0xfe, 0xf7, 0x6a, 0xfa, 0x05, 0x98, 0x08, 0x30, 0x07, 0x90, - 0xd0, 0xe9, 0x04, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x0b, 0xd0, - 0xd0, 0xe9, 0x00, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x0c, 0xd1, - 0xd0, 0xe9, 0x02, 0x23, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, 0x06, 0xd1, - 0x20, 0x46, 0xff, 0xf7, 0xbb, 0xfd, 0x5f, 0xea, 0x00, 0x09, 0x40, 0xf0, - 0xbe, 0x82, 0x00, 0x20, 0x0b, 0x90, 0x6a, 0x46, 0x07, 0x98, 0x0a, 0xc8, - 0x0a, 0xc2, 0x0a, 0xc8, 0x0a, 0xc2, 0x07, 0x98, 0x00, 0x25, 0xd0, 0xe9, - 0x04, 0x23, 0x0c, 0xa8, 0xff, 0xf7, 0x73, 0xfd, 0xdd, 0xe9, 0x0c, 0x01, - 0x05, 0x9a, 0xc2, 0xe9, 0x08, 0x01, 0x00, 0x20, 0xcd, 0xe9, 0x18, 0x00, - 0xcd, 0xe9, 0x0c, 0x00, 0x04, 0x9a, 0x08, 0x98, 0x04, 0x99, 0x04, 0x9b, - 0x40, 0x88, 0x92, 0x89, 0x49, 0x8a, 0xdb, 0x89, 0x03, 0x90, 0x12, 0x18, - 0x64, 0x31, 0x9a, 0x18, 0x51, 0x43, 0x64, 0x22, 0xb1, 0xfb, 0xf2, 0xf1, - 0x01, 0x20, 0x14, 0x91, 0x01, 0x90, 0x0d, 0xe0, 0x02, 0x28, 0x03, 0xd1, - 0x04, 0x99, 0x03, 0x98, 0x89, 0x89, 0x04, 0xe0, 0x03, 0x28, 0x05, 0xd1, - 0x04, 0x99, 0x03, 0x98, 0xc9, 0x89, 0x08, 0x18, 0x80, 0xb2, 0x03, 0x90, - 0x01, 0x20, 0xad, 0xf8, 0x00, 0x00, 0x00, 0xf0, 0xa1, 0xfb, 0x0a, 0x90, - 0x00, 0x20, 0x02, 0x90, 0x76, 0xe0, 0xdd, 0xe9, 0x18, 0x01, 0x0b, 0x46, - 0x00, 0x21, 0xc0, 0x19, 0x59, 0x41, 0xcd, 0xe9, 0x18, 0x01, 0xdd, 0xe9, - 0x0c, 0x23, 0x00, 0x21, 0x12, 0xeb, 0x0b, 0x00, 0x59, 0x41, 0xcd, 0xe9, - 0x0c, 0x01, 0x05, 0x98, 0x00, 0x79, 0x00, 0xf0, 0x0f, 0x00, 0x01, 0x21, - 0x08, 0x30, 0x01, 0xfa, 0x00, 0xf0, 0xc1, 0x17, 0xcd, 0xe9, 0x16, 0x01, - 0x07, 0x98, 0xd0, 0xe9, 0x00, 0x79, 0x00, 0xf0, 0x6b, 0xfb, 0x38, 0x1a, - 0x69, 0xeb, 0x01, 0x01, 0x07, 0x9a, 0x10, 0xeb, 0x0a, 0x00, 0x41, 0xeb, - 0xea, 0x71, 0xc2, 0xe9, 0x00, 0x01, 0x07, 0x98, 0xd0, 0xe9, 0x02, 0x79, - 0x00, 0xf0, 0x5c, 0xfb, 0x3a, 0x1a, 0x15, 0x98, 0x69, 0xeb, 0x01, 0x03, - 0xc1, 0x17, 0x10, 0x18, 0x07, 0x9a, 0x59, 0x41, 0xc2, 0xe9, 0x02, 0x01, - 0x07, 0x98, 0xd0, 0xe9, 0x04, 0x79, 0x00, 0xf0, 0x4d, 0xfb, 0x38, 0x1a, - 0x69, 0xeb, 0x01, 0x01, 0x00, 0x23, 0x07, 0x9a, 0x10, 0xeb, 0x0b, 0x00, - 0x59, 0x41, 0xc2, 0xe9, 0x04, 0x01, 0x1a, 0xa8, 0x50, 0xf8, 0x26, 0x00, - 0x15, 0x90, 0x05, 0x98, 0xd0, 0xe9, 0x08, 0x23, 0x11, 0x46, 0x15, 0x98, - 0x1a, 0x46, 0xff, 0xf7, 0x7f, 0xfc, 0x1a, 0xa9, 0x41, 0xf8, 0x26, 0x00, - 0x1a, 0xa8, 0x21, 0xa9, 0x30, 0xf9, 0x26, 0x00, 0x31, 0xf9, 0x26, 0x10, - 0x40, 0x1a, 0x11, 0x90, 0x13, 0x98, 0xb8, 0xf9, 0x02, 0x10, 0xb0, 0xf9, - 0x02, 0x00, 0x00, 0xf0, 0x14, 0xfb, 0x08, 0x99, 0x49, 0x89, 0x49, 0x43, - 0x81, 0x42, 0x02, 0xd2, 0x0e, 0x98, 0x40, 0x1c, 0x0e, 0x90, 0x76, 0x1c, - 0x07, 0x2e, 0x62, 0xd3, 0x1a, 0xaa, 0x21, 0xa9, 0x20, 0x46, 0xff, 0xf7, - 0xb7, 0xf8, 0x6d, 0x1c, 0x03, 0x98, 0x85, 0x42, 0x80, 0xf0, 0x90, 0x80, - 0x00, 0xf0, 0x28, 0xfb, 0x06, 0x99, 0x0a, 0x98, 0x08, 0x62, 0x6e, 0x1e, - 0xf8, 0xf7, 0x4d, 0xfa, 0x88, 0xb1, 0x00, 0xf0, 0x0e, 0xfb, 0x20, 0x46, - 0xfe, 0xf7, 0x83, 0xf8, 0x5f, 0xea, 0x00, 0x09, 0x35, 0x46, 0x07, 0xd1, - 0x08, 0x99, 0x05, 0x98, 0x09, 0x88, 0x80, 0x88, 0x21, 0xf4, 0x00, 0x61, - 0x88, 0x42, 0xe0, 0xd0, 0xe3, 0xe1, 0x01, 0x98, 0x01, 0x28, 0x31, 0xd0, - 0x0a, 0x98, 0xfa, 0xf7, 0x89, 0xfe, 0x00, 0xf0, 0xf9, 0xfa, 0x40, 0xbb, - 0x02, 0x98, 0x45, 0x1c, 0x01, 0x98, 0x03, 0x28, 0x1b, 0xd1, 0x04, 0x99, - 0xbd, 0xf8, 0x00, 0x00, 0x09, 0x8a, 0x88, 0x42, 0x03, 0xd2, 0x40, 0x1c, - 0xad, 0xf8, 0x00, 0x00, 0x12, 0xe0, 0x04, 0x98, 0xc0, 0x88, 0xfa, 0xf7, - 0x69, 0xfc, 0x00, 0xf0, 0xd4, 0xfa, 0x00, 0xf0, 0xcf, 0xfa, 0x00, 0xf0, - 0xf3, 0xfa, 0x01, 0x46, 0x0a, 0x98, 0xfa, 0xf7, 0xfd, 0xfd, 0x0a, 0x90, - 0x01, 0x20, 0xad, 0xf8, 0x00, 0x00, 0x02, 0x95, 0x02, 0x98, 0x14, 0x99, - 0x88, 0x42, 0x80, 0xf0, 0xdc, 0x81, 0x35, 0x46, 0xad, 0xe7, 0x00, 0xf0, - 0xd3, 0xfa, 0x0a, 0x90, 0x21, 0xa8, 0xff, 0xf7, 0x51, 0xfe, 0x0b, 0x99, - 0x81, 0x42, 0x38, 0xbf, 0x01, 0x46, 0x0b, 0x91, 0x00, 0x26, 0x21, 0xa8, - 0x00, 0xf0, 0xa9, 0xfa, 0x83, 0x46, 0x1a, 0xa8, 0x00, 0xf0, 0xa5, 0xfa, - 0x07, 0x46, 0x1a, 0xa8, 0x00, 0xeb, 0x86, 0x01, 0x13, 0x91, 0x1a, 0xaa, - 0xb1, 0xf9, 0x02, 0x00, 0x32, 0xf9, 0x26, 0x20, 0x21, 0xa9, 0x01, 0xeb, - 0x86, 0x08, 0xb8, 0xf9, 0x02, 0x30, 0x31, 0xf9, 0x26, 0x10, 0x43, 0x43, - 0x02, 0xfb, 0x01, 0x3a, 0x21, 0xa9, 0x1a, 0xaa, 0x31, 0xf9, 0x26, 0x10, - 0x32, 0xf9, 0x26, 0x20, 0x48, 0x43, 0xb8, 0xf9, 0x02, 0x10, 0x02, 0xfb, - 0x11, 0x01, 0x08, 0x98, 0x15, 0x91, 0x00, 0x89, 0x40, 0x43, 0x58, 0x45, - 0x03, 0xd2, 0x10, 0x98, 0x40, 0x1c, 0x10, 0x90, 0x69, 0xe7, 0xb8, 0x42, - 0xbf, 0xf4, 0xf9, 0xae, 0x0f, 0x98, 0x40, 0x1c, 0x0f, 0x90, 0x62, 0xe7, - 0x01, 0x98, 0x40, 0x1c, 0xc0, 0xb2, 0x04, 0x28, 0x01, 0x90, 0xff, 0xf6, - 0xd7, 0xae, 0x00, 0xf0, 0x80, 0xfa, 0x03, 0xa8, 0x00, 0x21, 0x00, 0x88, - 0xcd, 0xe9, 0x00, 0x01, 0x07, 0x26, 0x04, 0x98, 0x80, 0x7e, 0x00, 0x28, - 0x60, 0xd0, 0x04, 0x98, 0xc0, 0x8b, 0xfa, 0xf7, 0xf9, 0xfb, 0x00, 0xf0, - 0x64, 0xfa, 0xdf, 0xf8, 0x04, 0x16, 0xfa, 0xf7, 0x03, 0xfc, 0x00, 0xf0, - 0x81, 0xfa, 0x05, 0x46, 0x04, 0x98, 0x82, 0x8b, 0xdd, 0xe9, 0x00, 0x01, - 0xa2, 0xfb, 0x00, 0x79, 0x02, 0xfb, 0x01, 0x99, 0xa2, 0xfb, 0x07, 0x01, - 0x02, 0xfb, 0x09, 0x11, 0xa6, 0xfb, 0x00, 0x79, 0x06, 0xfb, 0x01, 0x99, - 0x38, 0x46, 0x49, 0x46, 0xfa, 0xf7, 0xae, 0xfb, 0xff, 0xf7, 0xc4, 0xfb, - 0x03, 0xf0, 0xf4, 0xfc, 0x02, 0x46, 0x20, 0x69, 0x0b, 0x46, 0x01, 0x28, - 0x0c, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x00, 0x25, 0xef, 0xf3, 0x11, 0x8a, - 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, 0x09, 0x98, 0xc0, 0x7a, 0x38, 0xbb, - 0x09, 0x98, 0x80, 0x7a, 0x80, 0xb1, 0xdd, 0xe9, 0x0c, 0x70, 0x83, 0x42, - 0x08, 0xd8, 0x28, 0xbf, 0xba, 0x42, 0x05, 0xd2, 0x09, 0x9a, 0x95, 0x72, - 0x01, 0x20, 0xfe, 0xf7, 0x86, 0xf8, 0x17, 0xe0, 0x00, 0x20, 0xfe, 0xf7, - 0x82, 0xf8, 0x12, 0xe0, 0xdd, 0xe9, 0x0c, 0x23, 0x4b, 0x45, 0x0f, 0xd8, - 0x28, 0xbf, 0xba, 0x42, 0x0c, 0xd2, 0x09, 0x9a, 0x01, 0x20, 0x90, 0x72, - 0x00, 0x20, 0xfe, 0xf7, 0x74, 0xf8, 0xa0, 0x68, 0x90, 0xf8, 0x3f, 0x10, - 0x20, 0x69, 0xfe, 0xf7, 0xd9, 0xf8, 0x0f, 0x25, 0x8a, 0xf3, 0x11, 0x88, - 0x00, 0x2d, 0x72, 0xd1, 0x08, 0x98, 0x80, 0x8b, 0xdd, 0xe9, 0x00, 0x23, - 0xa0, 0xfb, 0x02, 0x79, 0x00, 0xfb, 0x03, 0x99, 0xa0, 0xfb, 0x07, 0x23, - 0x00, 0xfb, 0x09, 0x33, 0xa6, 0xfb, 0x02, 0x01, 0x06, 0xfb, 0x03, 0x11, - 0xdd, 0xe9, 0x0c, 0x23, 0x8b, 0x42, 0x07, 0xd8, 0x28, 0xbf, 0x82, 0x42, - 0x04, 0xd2, 0x21, 0x68, 0x00, 0xf0, 0x09, 0xfa, 0x07, 0x20, 0xdb, 0xe1, - 0x10, 0x9a, 0x02, 0x2a, 0x07, 0xd3, 0xa3, 0x68, 0x22, 0x69, 0x06, 0x99, - 0x05, 0x98, 0xfe, 0xf7, 0x66, 0xf8, 0x08, 0x20, 0xd0, 0xe1, 0xdd, 0xe9, - 0x18, 0x23, 0x8b, 0x42, 0x03, 0xd8, 0x2c, 0xbf, 0x82, 0x42, 0x05, 0x20, - 0xf6, 0xd3, 0x0f, 0x98, 0x04, 0x28, 0x03, 0xd3, 0x00, 0xf0, 0xee, 0xf9, - 0x06, 0x20, 0xc1, 0xe1, 0x0e, 0x98, 0x03, 0x28, 0x03, 0xd3, 0x00, 0xf0, - 0xe7, 0xf9, 0x0a, 0x20, 0xba, 0xe1, 0xdd, 0xe9, 0x0c, 0x01, 0xdd, 0xe9, - 0x00, 0x23, 0xfb, 0xf7, 0x67, 0xf8, 0xfa, 0xf7, 0x29, 0xfb, 0xfa, 0xf7, - 0x99, 0xfc, 0x01, 0xf0, 0xf1, 0xfb, 0x07, 0x90, 0x11, 0x25, 0x0f, 0xf2, - 0x80, 0x56, 0x0f, 0xf2, 0xd4, 0x47, 0x28, 0xa8, 0x39, 0x46, 0xa8, 0x22, - 0xfd, 0xf7, 0x60, 0xfc, 0xd6, 0xe9, 0x00, 0x01, 0x28, 0xab, 0x01, 0x22, - 0x43, 0xf8, 0x35, 0x20, 0x00, 0x23, 0x22, 0x69, 0xd2, 0xb2, 0x00, 0x92, - 0x6d, 0x1c, 0x0a, 0x46, 0x01, 0x46, 0x28, 0xa8, 0xfd, 0xf7, 0xfe, 0xfe, - 0x15, 0x2d, 0xe8, 0xd3, 0x20, 0x46, 0xff, 0xf7, 0x09, 0xfc, 0x20, 0x46, - 0xff, 0xf7, 0x6d, 0xfd, 0x20, 0x46, 0xfd, 0xf7, 0x1e, 0xff, 0x05, 0x00, - 0x03, 0xd0, 0x00, 0xf0, 0xa2, 0xf9, 0x28, 0x46, 0x82, 0xe1, 0x00, 0x20, - 0xcd, 0xe9, 0x0c, 0x00, 0x03, 0x90, 0x00, 0x27, 0x00, 0xf0, 0xa2, 0xf9, - 0x80, 0x46, 0x02, 0x97, 0xbb, 0x46, 0xba, 0x46, 0x01, 0x25, 0x00, 0x26, - 0x63, 0xe0, 0x80, 0x88, 0xfa, 0xf7, 0x16, 0xfb, 0x80, 0x46, 0x4f, 0xf0, - 0x00, 0x09, 0x1a, 0xa8, 0x50, 0xf8, 0x29, 0x00, 0x05, 0x9a, 0x00, 0x90, - 0xd2, 0xe9, 0x08, 0x01, 0x0a, 0x46, 0x01, 0x46, 0x00, 0x98, 0xff, 0xf7, - 0xbf, 0xfa, 0x1a, 0xa9, 0x41, 0xf8, 0x29, 0x00, 0x09, 0xf1, 0x01, 0x09, - 0xb9, 0xf1, 0x03, 0x0f, 0xeb, 0xd3, 0x21, 0x46, 0x1a, 0xa8, 0xff, 0xf7, - 0xd3, 0xf9, 0x00, 0x90, 0xbd, 0xf9, 0x00, 0x10, 0xbd, 0xf9, 0x84, 0x00, - 0x40, 0x1a, 0x11, 0x90, 0xbd, 0xf9, 0x02, 0x10, 0xbd, 0xf9, 0x86, 0x00, - 0x00, 0xf0, 0x4d, 0xf9, 0xfa, 0xf7, 0xec, 0xfa, 0x03, 0x99, 0xfa, 0xf7, - 0xeb, 0xfb, 0x03, 0x90, 0x1a, 0x98, 0xff, 0xf7, 0x81, 0xfa, 0xfa, 0xf7, - 0xe3, 0xfa, 0x59, 0x46, 0xfa, 0xf7, 0xe2, 0xfb, 0x83, 0x46, 0x00, 0x98, - 0xff, 0xf7, 0x78, 0xfa, 0xfa, 0xf7, 0xda, 0xfa, 0x51, 0x46, 0xfa, 0xf7, - 0xd9, 0xfb, 0x82, 0x46, 0x21, 0x98, 0xff, 0xf7, 0x6f, 0xfa, 0xfd, 0xf7, - 0x79, 0xfd, 0x5f, 0xfa, 0x80, 0xf9, 0xdd, 0xe9, 0x11, 0x01, 0xff, 0xf7, - 0x71, 0xfa, 0x04, 0x99, 0x49, 0x88, 0x49, 0x43, 0x88, 0x42, 0x3c, 0xbf, - 0x4f, 0x45, 0x4f, 0x46, 0xdd, 0xe9, 0x0c, 0x01, 0xcd, 0xe9, 0x00, 0x01, - 0x21, 0x98, 0xff, 0xf7, 0x59, 0xfa, 0xdd, 0xe9, 0x00, 0x23, 0x00, 0x21, - 0x10, 0x18, 0x59, 0x41, 0xcd, 0xe9, 0x0c, 0x01, 0x76, 0x1c, 0x08, 0x98, - 0xc0, 0x88, 0x86, 0x42, 0x3d, 0xda, 0x00, 0xf0, 0x39, 0xf9, 0xf8, 0xf7, - 0x62, 0xf8, 0xa6, 0xf1, 0x01, 0x09, 0x60, 0xb1, 0x00, 0xf0, 0x21, 0xf9, - 0x20, 0x46, 0xfd, 0xf7, 0x96, 0xfe, 0x4e, 0x46, 0x5f, 0xea, 0x00, 0x09, - 0xea, 0xd0, 0x00, 0xf0, 0x18, 0xf9, 0x48, 0x46, 0xf8, 0xe0, 0x40, 0x46, - 0xfa, 0xf7, 0xa4, 0xfc, 0x00, 0xf0, 0x14, 0xf9, 0x00, 0x28, 0x04, 0x98, - 0x7f, 0xf4, 0x7b, 0xaf, 0x00, 0x8a, 0xad, 0xb2, 0x85, 0x42, 0x38, 0xbf, - 0x6d, 0x1c, 0x10, 0xd3, 0x04, 0x98, 0xc0, 0x88, 0xfa, 0xf7, 0x8a, 0xfa, - 0x00, 0xf0, 0xf5, 0xf8, 0x00, 0xf0, 0xf0, 0xf8, 0x00, 0xf0, 0x14, 0xf9, - 0x00, 0xf0, 0xf8, 0xf8, 0x80, 0x46, 0x02, 0x98, 0x40, 0x1c, 0x01, 0x25, - 0x02, 0x90, 0x02, 0x98, 0x14, 0x99, 0x88, 0x42, 0x03, 0xd3, 0x00, 0xf0, - 0xf0, 0xf8, 0x0d, 0x20, 0xd0, 0xe0, 0x4e, 0x46, 0xbc, 0xe7, 0x00, 0xf0, - 0xea, 0xf8, 0xdd, 0xe9, 0x0c, 0x01, 0x40, 0x1c, 0x41, 0xf1, 0x00, 0x01, - 0xfa, 0xf7, 0x3c, 0xfa, 0x01, 0x46, 0x03, 0x98, 0xfa, 0xf7, 0x76, 0xfa, - 0xfa, 0xf7, 0xa8, 0xfb, 0xb8, 0x49, 0xfa, 0xf7, 0xff, 0xfb, 0x01, 0xf0, - 0xfd, 0xfa, 0x06, 0x99, 0xc8, 0x60, 0x09, 0x98, 0x06, 0x99, 0x00, 0x68, - 0x48, 0x62, 0x06, 0x98, 0xc6, 0x68, 0x08, 0x98, 0x80, 0x88, 0xb0, 0x42, - 0x02, 0xd2, 0x00, 0xf0, 0xd7, 0xf8, 0x33, 0xe0, 0x04, 0x98, 0xb0, 0xf8, - 0x0a, 0x80, 0xb8, 0xf1, 0x00, 0x0f, 0x2f, 0xd0, 0x00, 0x89, 0xfa, 0xf7, - 0x47, 0xfa, 0x00, 0xf0, 0xb2, 0xf8, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, - 0xd1, 0xf8, 0x05, 0x46, 0x40, 0x46, 0xfa, 0xf7, 0x3d, 0xfa, 0x00, 0xf0, - 0xa8, 0xf8, 0x80, 0x46, 0x30, 0x46, 0xfa, 0xf7, 0x37, 0xfa, 0x06, 0x46, - 0x09, 0x98, 0x00, 0x68, 0xff, 0xf7, 0x1c, 0xfa, 0x81, 0x46, 0x4f, 0xf0, - 0x7e, 0x50, 0x29, 0x46, 0xfa, 0xf7, 0xba, 0xfa, 0x31, 0x46, 0xfa, 0xf7, - 0xc7, 0xfb, 0x49, 0x46, 0xfa, 0xf7, 0x28, 0xfb, 0x01, 0x46, 0x09, 0x98, - 0x01, 0x60, 0x40, 0x46, 0xfa, 0xf7, 0xbe, 0xfb, 0x31, 0x46, 0xfa, 0xf7, - 0xa9, 0xfb, 0x01, 0xd2, 0x09, 0x20, 0x75, 0xe0, 0xa0, 0x68, 0x90, 0xf8, - 0x3a, 0x00, 0xa0, 0xb3, 0x01, 0x21, 0x58, 0x46, 0x01, 0xf0, 0xba, 0xfc, - 0x90, 0x49, 0xfa, 0xf7, 0xad, 0xfb, 0x06, 0x46, 0x01, 0x21, 0x50, 0x46, - 0x01, 0xf0, 0xb2, 0xfc, 0x8c, 0x49, 0xfa, 0xf7, 0xa5, 0xfb, 0x80, 0x46, - 0x30, 0x46, 0x41, 0x46, 0xfa, 0xf7, 0x90, 0xfa, 0x00, 0x21, 0xfa, 0xf7, - 0x8b, 0xfb, 0x05, 0x46, 0x04, 0xd2, 0x40, 0x46, 0x31, 0x46, 0xfa, 0xf7, - 0x87, 0xfa, 0x05, 0x46, 0x84, 0x48, 0xff, 0xf7, 0xdf, 0xf9, 0x05, 0x46, - 0x01, 0xf0, 0x90, 0xfa, 0xe1, 0x68, 0x08, 0x63, 0xa6, 0x68, 0xb0, 0x8f, - 0xfa, 0xf7, 0xec, 0xf9, 0x29, 0x46, 0xfa, 0xf7, 0x75, 0xfb, 0x06, 0xd2, - 0x96, 0xf8, 0x3b, 0x10, 0x20, 0x69, 0xfd, 0xf7, 0x1b, 0xff, 0x0e, 0x20, - 0x3c, 0xe0, 0x20, 0x46, 0xfd, 0xf7, 0x69, 0xfe, 0x0b, 0x98, 0xfe, 0xf7, - 0xfd, 0xfc, 0x06, 0x99, 0x08, 0x85, 0x06, 0x98, 0x06, 0x99, 0x40, 0x8d, - 0x09, 0x8d, 0x88, 0x42, 0x38, 0xbf, 0x08, 0x46, 0x06, 0x99, 0x48, 0x85, - 0xa0, 0x68, 0x00, 0x88, 0x40, 0x05, 0x26, 0xd5, 0x05, 0x98, 0x08, 0x9a, - 0x50, 0xf8, 0xd0, 0x1f, 0x92, 0x7e, 0x51, 0x43, 0x64, 0x22, 0x91, 0xfb, - 0xf2, 0xf1, 0x07, 0x9a, 0x91, 0x42, 0x1a, 0xd2, 0x81, 0x89, 0x02, 0x60, - 0xb9, 0x42, 0x38, 0xbf, 0x87, 0x81, 0x05, 0x98, 0x00, 0x25, 0xd0, 0xe9, - 0x08, 0x23, 0xd4, 0x30, 0xc0, 0xe9, 0x00, 0x23, 0x04, 0xeb, 0xc5, 0x00, - 0x00, 0xf1, 0x14, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0x05, 0x9a, 0x02, 0xeb, - 0xc5, 0x02, 0x28, 0x32, 0x6d, 0x1c, 0xc2, 0xe9, 0x00, 0x01, 0x15, 0x2d, - 0xf0, 0xd3, 0x00, 0x20, 0x53, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x40, 0x1a, - 0x12, 0x90, 0xdd, 0xe9, 0x11, 0x01, 0xff, 0xf7, 0x41, 0xb9, 0x50, 0xf8, - 0x26, 0x00, 0x13, 0x90, 0xff, 0xf7, 0x32, 0xb9, 0x54, 0x49, 0xfa, 0xf7, - 0xa3, 0xb9, 0x52, 0x49, 0xfa, 0xf7, 0xa0, 0xb9, 0xdd, 0xe9, 0x16, 0x23, - 0x38, 0x46, 0x49, 0x46, 0xfa, 0xf7, 0x76, 0xbe, 0x41, 0x46, 0xfa, 0xf7, - 0x25, 0xbb, 0x20, 0x46, 0xfd, 0xf7, 0x8f, 0xbd, 0x02, 0x46, 0x04, 0x98, - 0x81, 0x8a, 0x21, 0xa8, 0xff, 0xf7, 0x94, 0xbb, 0x04, 0x98, 0x80, 0x88, - 0xfa, 0xf7, 0x7a, 0xb9, 0x05, 0x99, 0x20, 0x69, 0xfd, 0xf7, 0x9e, 0xbb, - 0x20, 0x69, 0x07, 0x23, 0x1a, 0xaa, 0x21, 0xa9, 0xfd, 0xf7, 0xe2, 0xbc, - 0x01, 0x46, 0x3f, 0x48, 0xfa, 0xf7, 0x81, 0xbd, 0x80, 0xb5, 0x41, 0x68, - 0x02, 0x68, 0x00, 0x92, 0x0b, 0x1d, 0xb1, 0xf9, 0x02, 0x20, 0x09, 0x88, - 0x00, 0x69, 0xfb, 0xf7, 0x56, 0xf8, 0x02, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, - 0x04, 0x46, 0x25, 0x69, 0x26, 0x68, 0xd4, 0xf8, 0x0c, 0x90, 0x88, 0x46, - 0xfd, 0xf7, 0x78, 0xfb, 0x00, 0x27, 0x08, 0xb9, 0x0b, 0x27, 0x30, 0xe0, - 0x00, 0x2d, 0x14, 0xbf, 0x32, 0x48, 0x33, 0x48, 0x01, 0x21, 0x01, 0x60, - 0x2a, 0x46, 0xa3, 0x68, 0x49, 0x46, 0x30, 0x46, 0xfd, 0xf7, 0x35, 0xfe, - 0xb8, 0xf1, 0x00, 0x0f, 0x86, 0xf8, 0xa1, 0x71, 0x03, 0xd1, 0xe0, 0x68, - 0xf3, 0x78, 0x42, 0x8b, 0x15, 0xe0, 0x20, 0x46, 0xff, 0xf7, 0xce, 0xff, - 0x07, 0x00, 0x03, 0xd1, 0x20, 0x68, 0x01, 0x78, 0x5a, 0x29, 0x04, 0xda, - 0xe1, 0x68, 0x00, 0x20, 0x88, 0x83, 0x03, 0x27, 0x0d, 0xe0, 0xe2, 0x68, - 0x51, 0x83, 0x40, 0x78, 0x10, 0x83, 0x01, 0x20, 0x90, 0x83, 0xf3, 0x78, - 0x32, 0x78, 0xa0, 0x68, 0x29, 0x46, 0xfd, 0xf7, 0x6f, 0xfc, 0x01, 0x20, - 0xb0, 0x70, 0x38, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x10, 0xb5, 0x00, 0x21, - 0x1a, 0x4a, 0x20, 0xfa, 0x01, 0xf3, 0xdb, 0x07, 0x06, 0xd5, 0x4f, 0xf4, - 0xd4, 0x74, 0x04, 0xfb, 0x01, 0x24, 0x01, 0x23, 0x84, 0xf8, 0xa3, 0x31, - 0x49, 0x1c, 0x02, 0x29, 0xf1, 0xd3, 0x10, 0xbd, 0x10, 0xb5, 0x00, 0x21, - 0x11, 0x4a, 0x20, 0xfa, 0x01, 0xf3, 0xdb, 0x07, 0x06, 0xd5, 0x4f, 0xf4, - 0xd4, 0x74, 0x04, 0xfb, 0x01, 0x24, 0x00, 0x23, 0x84, 0xf8, 0xa3, 0x31, - 0x49, 0x1c, 0x02, 0x29, 0xf1, 0xd3, 0x10, 0xbd, 0xae, 0x47, 0x81, 0x3f, - 0xae, 0x47, 0x81, 0xbf, 0xcb, 0xbe, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x41, - 0x00, 0x00, 0x7a, 0x44, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0xc8, 0x42, - 0x00, 0x00, 0xa0, 0xc1, 0x00, 0x00, 0x50, 0x59, 0x00, 0x00, 0x40, 0x59, - 0x10, 0xb2, 0x00, 0x20, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x10, 0xb4, 0x50, 0xf8, 0x04, 0x1b, 0x79, 0xb1, 0x02, 0x68, 0x43, 0x68, - 0x12, 0x18, 0x08, 0x30, 0xdc, 0x07, 0x44, 0xbf, 0xa9, 0xf1, 0x01, 0x04, - 0xe3, 0x18, 0x52, 0xf8, 0x04, 0x4b, 0x43, 0xf8, 0x04, 0x4b, 0x09, 0x1f, - 0xf9, 0xd1, 0xec, 0xe7, 0x10, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x00, 0x00, - 0x04, 0x28, 0x07, 0xda, 0xdf, 0xf8, 0xa0, 0x1c, 0x28, 0x22, 0x02, 0xfb, - 0x00, 0x12, 0xd2, 0xe9, 0x02, 0x01, 0x70, 0x47, 0x00, 0x20, 0x00, 0x21, - 0x70, 0x47, 0xf0, 0xb5, 0xdf, 0xf8, 0x8c, 0x3c, 0x0f, 0xf2, 0x48, 0x05, - 0x1b, 0x68, 0x4f, 0xf4, 0x7a, 0x74, 0x0a, 0x46, 0xb3, 0xfb, 0xf4, 0xf3, - 0x00, 0x21, 0x00, 0x24, 0x42, 0xf2, 0x10, 0x77, 0x15, 0xf8, 0x14, 0x60, - 0x7e, 0x43, 0x9e, 0x42, 0x0d, 0xd3, 0x05, 0xeb, 0x44, 0x04, 0x94, 0xf9, - 0x01, 0x40, 0x00, 0x2c, 0x0a, 0xd4, 0x14, 0x70, 0x03, 0x2c, 0x07, 0xbf, - 0x5a, 0x00, 0x02, 0x60, 0xe3, 0x40, 0x03, 0x60, 0x03, 0xe0, 0x64, 0x1c, - 0x05, 0x2c, 0xe9, 0xd3, 0x04, 0x21, 0x08, 0x46, 0xf0, 0xbd, 0x00, 0x00, - 0x02, 0xff, 0x04, 0x03, 0x08, 0x00, 0x10, 0x01, 0x20, 0x02, 0x00, 0x00, - 0xf8, 0xb5, 0x00, 0x24, 0x00, 0x27, 0x0f, 0xf2, 0xf4, 0x25, 0xdf, 0xf8, - 0x24, 0x6c, 0x28, 0x20, 0x78, 0x43, 0xf9, 0xb2, 0x81, 0x53, 0x80, 0x19, - 0x35, 0xf8, 0x17, 0x20, 0x42, 0x80, 0x01, 0x21, 0x80, 0xf8, 0x27, 0x10, - 0x02, 0xf1, 0x22, 0x00, 0x0e, 0x21, 0x00, 0xf0, 0x70, 0xfb, 0x7f, 0x1c, - 0x04, 0x2f, 0xec, 0xdb, 0xdf, 0xf8, 0xfc, 0x5b, 0x68, 0x89, 0xc0, 0xf3, - 0x81, 0x00, 0x80, 0xb1, 0x00, 0x22, 0x10, 0x21, 0x4f, 0xf4, 0x10, 0x70, - 0xf6, 0xf7, 0xfc, 0xfa, 0x03, 0x22, 0x32, 0x21, 0x00, 0x20, 0x00, 0xf0, - 0x36, 0xfc, 0x04, 0x46, 0x4f, 0xf4, 0x10, 0x70, 0x00, 0xf0, 0x20, 0xfc, - 0xec, 0xb9, 0xa8, 0x7a, 0x03, 0x21, 0x08, 0x42, 0x1a, 0xd0, 0x00, 0x22, - 0x10, 0x21, 0x4f, 0xf4, 0x2c, 0x70, 0xf6, 0xf7, 0xe7, 0xfa, 0x03, 0x22, - 0x32, 0x21, 0x01, 0x20, 0x00, 0xf0, 0x21, 0xfc, 0x04, 0x46, 0x4f, 0xf4, - 0x2c, 0x70, 0x00, 0xf0, 0x0b, 0xfc, 0xa8, 0x69, 0xdf, 0xf8, 0xa8, 0x2b, - 0x40, 0x08, 0x00, 0xf5, 0x43, 0x40, 0x50, 0x30, 0x00, 0x21, 0xc2, 0xe9, - 0x00, 0x01, 0xec, 0xb9, 0x68, 0x89, 0x4f, 0xf4, 0xf8, 0x71, 0x08, 0x42, - 0x18, 0xd0, 0x00, 0x22, 0x10, 0x21, 0x4f, 0xf4, 0x50, 0x70, 0xf6, 0xf7, - 0xc7, 0xfa, 0x03, 0x22, 0x4f, 0xf4, 0xfa, 0x71, 0x02, 0x20, 0x00, 0xf0, - 0x00, 0xfc, 0x04, 0x46, 0x03, 0x22, 0x4f, 0xf4, 0xfa, 0x71, 0x03, 0x20, - 0x00, 0xf0, 0xf9, 0xfb, 0x04, 0xb9, 0x04, 0x46, 0x4f, 0xf4, 0x50, 0x70, - 0x00, 0xf0, 0xe2, 0xfb, 0x20, 0x46, 0xf2, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, - 0x16, 0x46, 0x86, 0xb0, 0x04, 0x46, 0x8a, 0x46, 0x35, 0x88, 0x06, 0xf1, - 0x10, 0x01, 0x02, 0xa8, 0xff, 0xf7, 0x55, 0xff, 0x00, 0x28, 0x42, 0xd1, - 0x30, 0x7c, 0x0f, 0xf6, 0x44, 0x51, 0x00, 0xf0, 0x03, 0x00, 0x80, 0x00, - 0x40, 0xf0, 0x13, 0x00, 0x30, 0x74, 0x00, 0x27, 0x4f, 0xf4, 0x7a, 0x70, - 0x51, 0xf8, 0x27, 0x20, 0xa0, 0xfb, 0x02, 0x89, 0xca, 0x45, 0x05, 0xd3, - 0x01, 0xd8, 0x44, 0x45, 0x02, 0xd3, 0x7f, 0x1c, 0x08, 0x2f, 0xf3, 0xd3, - 0x00, 0x2f, 0x18, 0xbf, 0x08, 0x2f, 0x25, 0xd0, 0xc7, 0xf1, 0x07, 0x07, - 0x02, 0x22, 0xba, 0x40, 0xd3, 0x17, 0xa4, 0xfb, 0x02, 0x89, 0x04, 0xfb, - 0x03, 0x99, 0x0a, 0xfb, 0x02, 0x99, 0xcd, 0xe9, 0x04, 0x89, 0x77, 0x74, - 0x00, 0x27, 0x0f, 0xf6, 0x64, 0x31, 0xdd, 0xe9, 0x04, 0x23, 0xcd, 0xe9, - 0x00, 0x23, 0x51, 0xf8, 0x27, 0x80, 0xa0, 0xfb, 0x08, 0x23, 0xdd, 0xe9, - 0x00, 0x89, 0x99, 0x45, 0x04, 0xd8, 0x2e, 0xbf, 0x90, 0x45, 0x7f, 0x1c, - 0x34, 0x2f, 0xee, 0xd3, 0x78, 0x1c, 0x01, 0xd0, 0x36, 0x28, 0x01, 0xd3, - 0x04, 0x20, 0x8c, 0xe0, 0x00, 0x27, 0x0f, 0xf6, 0xdc, 0x41, 0x7a, 0x5c, - 0x82, 0x42, 0x3c, 0xbf, 0x7f, 0x1c, 0x07, 0x2f, 0xf9, 0xd3, 0xc7, 0xf1, - 0x0d, 0x01, 0x41, 0xf0, 0x40, 0x01, 0xb1, 0x74, 0xa0, 0xf1, 0x1e, 0x01, - 0x05, 0x29, 0x34, 0xbf, 0xc2, 0x22, 0xc1, 0x22, 0xf2, 0x74, 0x08, 0x28, - 0x38, 0xbf, 0x04, 0x22, 0x06, 0xd3, 0x11, 0x28, 0x38, 0xbf, 0x06, 0x22, - 0x02, 0xd3, 0x07, 0x22, 0x1a, 0x28, 0x05, 0xd0, 0x08, 0x29, 0x03, 0xd3, - 0x28, 0x28, 0x01, 0xd0, 0x2c, 0x28, 0x01, 0xd3, 0x03, 0x21, 0x00, 0xe0, - 0x02, 0x21, 0x42, 0xea, 0xc1, 0x01, 0x31, 0x75, 0x0f, 0xf6, 0xa0, 0x21, - 0x41, 0x18, 0x11, 0xf8, 0x01, 0x1c, 0x01, 0xf0, 0x0f, 0x01, 0xc9, 0x00, - 0x71, 0x75, 0x1e, 0x28, 0x38, 0xbf, 0x0c, 0x21, 0x03, 0xd3, 0x23, 0x28, - 0x34, 0xbf, 0x0d, 0x21, 0x0e, 0x21, 0xb1, 0x75, 0xd4, 0x22, 0xdf, 0xf8, - 0x38, 0x1a, 0xdf, 0xf8, 0x38, 0x7a, 0x02, 0xfb, 0x05, 0x11, 0x01, 0xeb, - 0x80, 0x00, 0x00, 0x21, 0x50, 0xf8, 0x04, 0x0c, 0x0f, 0xf6, 0x20, 0x42, - 0xc6, 0xf8, 0x17, 0x00, 0x00, 0x20, 0x12, 0xf8, 0x11, 0x30, 0xa7, 0xfb, - 0x03, 0x89, 0xd1, 0x45, 0x06, 0xd8, 0x28, 0xbf, 0xa0, 0x45, 0x03, 0xd2, - 0x49, 0x1c, 0x04, 0x29, 0xf3, 0xd3, 0x02, 0xe0, 0x02, 0xeb, 0x41, 0x00, - 0x40, 0x78, 0xf0, 0x76, 0x4f, 0xf4, 0x7a, 0x71, 0x02, 0x98, 0x01, 0xfb, - 0x00, 0xf4, 0xdd, 0xe9, 0x04, 0x01, 0x00, 0xf0, 0xe9, 0xfc, 0xdd, 0xe9, - 0x04, 0x23, 0x07, 0x46, 0x04, 0xfb, 0x10, 0x20, 0xdf, 0xf8, 0xe0, 0x19, - 0xa1, 0xfb, 0x00, 0x01, 0x00, 0xf0, 0xde, 0xfc, 0x40, 0x1c, 0x40, 0x08, - 0xdf, 0xf8, 0xd4, 0x19, 0x88, 0x42, 0x06, 0xf1, 0x21, 0x01, 0x04, 0xbf, - 0x00, 0x20, 0x7f, 0x1c, 0x0f, 0x70, 0x3f, 0x04, 0x3a, 0x0e, 0x02, 0xf0, - 0x03, 0x02, 0x4a, 0x70, 0xb0, 0x77, 0x01, 0x0a, 0x00, 0x0c, 0x00, 0xf0, - 0x7f, 0x00, 0x86, 0xf8, 0x20, 0x00, 0xf1, 0x77, 0x00, 0x20, 0x06, 0xb0, - 0xbd, 0xe8, 0xf0, 0x87, 0x70, 0xb5, 0x04, 0x46, 0x0f, 0xf2, 0x50, 0x00, - 0x30, 0xf8, 0x14, 0x60, 0x4f, 0xf4, 0x96, 0x71, 0x02, 0x20, 0xf9, 0xf7, - 0x53, 0xfe, 0x00, 0x25, 0x06, 0xf1, 0x8c, 0x46, 0x30, 0x78, 0xc0, 0x07, - 0x04, 0xd5, 0x02, 0x20, 0xf9, 0xf7, 0x62, 0xfe, 0x00, 0x28, 0xf7, 0xd0, - 0x30, 0x78, 0xc0, 0x07, 0x0d, 0xd4, 0x20, 0x46, 0x00, 0xf0, 0x92, 0xf9, - 0x20, 0xb9, 0x02, 0x20, 0xf9, 0xf7, 0x56, 0xfe, 0x00, 0x28, 0xf6, 0xd0, - 0x20, 0x46, 0x00, 0xf0, 0x89, 0xf9, 0x00, 0xb1, 0x01, 0x25, 0x02, 0x20, - 0xf9, 0xf7, 0xc4, 0xfd, 0x28, 0x46, 0x70, 0xbd, 0x40, 0x02, 0xb0, 0x02, - 0x40, 0x03, 0x40, 0x03, 0x2d, 0xe9, 0xf0, 0x4d, 0x80, 0x46, 0x8a, 0x46, - 0x15, 0x46, 0xdf, 0xf8, 0x20, 0x09, 0xdf, 0xf8, 0x38, 0x29, 0x28, 0x21, - 0x01, 0xfb, 0x05, 0x06, 0x00, 0x20, 0x01, 0x23, 0x9a, 0x45, 0x04, 0xd3, - 0x01, 0xd8, 0x90, 0x45, 0x01, 0xd3, 0x02, 0x20, 0x06, 0xe0, 0x82, 0x45, - 0xdf, 0xf8, 0x1c, 0x29, 0x01, 0xd8, 0x90, 0x45, 0x00, 0xd3, 0x01, 0x20, - 0xdf, 0xf8, 0x14, 0x19, 0xdf, 0xf8, 0xf0, 0x28, 0x47, 0x18, 0x20, 0x31, - 0x05, 0xb3, 0x02, 0x2d, 0x3b, 0xd0, 0x62, 0xd2, 0x93, 0x7a, 0x12, 0x7b, - 0x08, 0x70, 0x02, 0xf0, 0x01, 0x0b, 0x3a, 0x78, 0x03, 0xf0, 0x03, 0x04, - 0x3f, 0x21, 0x4f, 0xf4, 0x01, 0x60, 0xf6, 0xf7, 0x6d, 0xf9, 0xba, 0x79, - 0x3f, 0x21, 0x40, 0xf6, 0x11, 0x00, 0xf6, 0xf7, 0x67, 0xf9, 0xfa, 0x78, - 0x3f, 0x21, 0x40, 0xf6, 0x12, 0x00, 0xf6, 0xf7, 0x61, 0xf9, 0x7a, 0x7a, - 0x3f, 0x21, 0x40, 0xf6, 0x13, 0x00, 0x2f, 0xe0, 0x50, 0x89, 0xc0, 0xf3, - 0x81, 0x04, 0x10, 0x7b, 0x3a, 0x78, 0x00, 0xf0, 0x02, 0x0b, 0x3f, 0x21, - 0x4f, 0xf4, 0xa4, 0x60, 0xf6, 0xf7, 0x50, 0xf9, 0xba, 0x79, 0x3f, 0x21, - 0x40, 0xf2, 0x21, 0x50, 0xf6, 0xf7, 0x4a, 0xf9, 0xfa, 0x78, 0x3f, 0x21, - 0x40, 0xf2, 0x22, 0x50, 0xf6, 0xf7, 0x44, 0xf9, 0x7a, 0x7a, 0x3f, 0x21, - 0x40, 0xf2, 0x23, 0x50, 0x12, 0xe0, 0x52, 0x89, 0x12, 0xf4, 0xf8, 0x72, - 0x14, 0x46, 0x18, 0xbf, 0x01, 0x24, 0x48, 0x70, 0x3f, 0x21, 0x3a, 0x7b, - 0x40, 0xf6, 0x1e, 0x00, 0xf6, 0xf7, 0x32, 0xf9, 0xfa, 0x7b, 0x4f, 0xf0, - 0x00, 0x0b, 0x3f, 0x21, 0x40, 0xf6, 0x1f, 0x00, 0xf6, 0xf7, 0x2a, 0xf9, - 0x00, 0x20, 0xc6, 0xe9, 0x02, 0x00, 0x4f, 0xf0, 0xff, 0x31, 0xdf, 0xf8, - 0x5c, 0x08, 0x18, 0xeb, 0x00, 0x02, 0x4a, 0xeb, 0x01, 0x03, 0x01, 0x21, - 0x8b, 0x42, 0xdf, 0xf8, 0x50, 0x08, 0x04, 0xd3, 0x01, 0xd8, 0x82, 0x42, - 0x01, 0xd3, 0x05, 0x20, 0x4b, 0xe0, 0x0c, 0xb9, 0x05, 0x27, 0x47, 0xe0, - 0x32, 0x46, 0x40, 0x46, 0x51, 0x46, 0xff, 0xf7, 0x5b, 0xfe, 0x07, 0x00, - 0x6e, 0xd1, 0x74, 0x88, 0xbb, 0xf1, 0x00, 0x0f, 0x3f, 0xd0, 0x01, 0x2d, - 0x1a, 0xd1, 0x80, 0x21, 0x40, 0xf2, 0x02, 0x20, 0xf6, 0xf7, 0xf6, 0xf8, - 0x01, 0x21, 0x4f, 0xf4, 0x40, 0x70, 0xf6, 0xf7, 0xf1, 0xf8, 0x10, 0x21, - 0x40, 0xf2, 0xca, 0x20, 0xf6, 0xf7, 0xec, 0xf8, 0xf2, 0x7e, 0x1f, 0x21, - 0x40, 0xf6, 0x15, 0x00, 0xf6, 0xf7, 0xf0, 0xf8, 0x40, 0x46, 0x51, 0x46, - 0x00, 0xf0, 0x52, 0xf8, 0x07, 0x46, 0x14, 0xe0, 0x80, 0x21, 0x4f, 0xf4, - 0x00, 0x70, 0xf6, 0xf7, 0xdb, 0xf8, 0x01, 0x21, 0x4f, 0xf4, 0x24, 0x70, - 0xf6, 0xf7, 0xd6, 0xf8, 0x10, 0x21, 0x40, 0xf2, 0x5a, 0x20, 0xf6, 0xf7, - 0xd1, 0xf8, 0xf2, 0x7e, 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0xf6, 0xf7, - 0xd5, 0xf8, 0x04, 0xf1, 0x42, 0x00, 0x07, 0x21, 0x00, 0xf0, 0x35, 0xf9, - 0x27, 0xb9, 0xc6, 0xe9, 0x02, 0x8a, 0x28, 0x46, 0xfa, 0xf7, 0x66, 0xfe, - 0x38, 0x46, 0xbd, 0xe8, 0xf0, 0x8d, 0x00, 0x21, 0x30, 0x46, 0x00, 0xf0, - 0xaf, 0xf8, 0x28, 0x46, 0xff, 0xf7, 0xf0, 0xfe, 0x08, 0xb9, 0x07, 0x27, - 0xf2, 0xe7, 0x04, 0xf1, 0x08, 0x00, 0x80, 0xb2, 0x00, 0xf1, 0x8c, 0x40, - 0x00, 0x78, 0x00, 0xf0, 0xfd, 0x00, 0x70, 0x75, 0xe0, 0x1d, 0x80, 0xb2, - 0x00, 0xf1, 0x8c, 0x40, 0x00, 0x78, 0x30, 0x77, 0xa0, 0x1d, 0x80, 0xb2, - 0x00, 0xf1, 0x8c, 0x40, 0x01, 0x2d, 0x00, 0x78, 0x00, 0xf0, 0x7f, 0x00, - 0x70, 0x77, 0xd4, 0xd1, 0x40, 0x46, 0x51, 0x46, 0x00, 0xf0, 0x06, 0xf8, - 0x07, 0x46, 0x00, 0xf0, 0x64, 0xf8, 0xcb, 0xe7, 0x06, 0x27, 0xcf, 0xe7, - 0x2d, 0xe9, 0xf0, 0x42, 0xdf, 0xf8, 0x20, 0x47, 0xdf, 0xf8, 0x44, 0x77, - 0xd4, 0xe9, 0x00, 0x23, 0x00, 0x26, 0x84, 0x18, 0x41, 0xeb, 0x03, 0x09, - 0x01, 0x25, 0xa9, 0x45, 0x05, 0xd3, 0x01, 0xd8, 0xbc, 0x42, 0x02, 0xd3, - 0x84, 0x1a, 0x61, 0xeb, 0x03, 0x09, 0xdf, 0xf8, 0xf4, 0x56, 0x05, 0xf1, - 0x80, 0x07, 0xd7, 0xe9, 0x00, 0x01, 0x89, 0x45, 0x08, 0xbf, 0x84, 0x42, - 0x22, 0xd0, 0xc7, 0xe9, 0x00, 0x66, 0x05, 0xf1, 0x78, 0x02, 0x20, 0x46, - 0x49, 0x46, 0xff, 0xf7, 0xc1, 0xfd, 0x06, 0x00, 0x18, 0xd1, 0x00, 0x21, - 0x05, 0xf1, 0x78, 0x00, 0x00, 0xf0, 0x58, 0xf8, 0x02, 0x20, 0xff, 0xf7, - 0x99, 0xfe, 0x70, 0xb1, 0xdf, 0xf8, 0xec, 0x06, 0x81, 0x78, 0x01, 0xf0, - 0xfd, 0x01, 0x79, 0x73, 0x41, 0x78, 0x39, 0x75, 0x00, 0x78, 0xc7, 0xe9, - 0x00, 0x49, 0x00, 0xf0, 0x7f, 0x00, 0x78, 0x75, 0x00, 0xe0, 0x04, 0x26, - 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x82, 0xdf, 0xf8, 0x94, 0x06, 0x10, 0xb5, - 0xd0, 0xe9, 0x20, 0x23, 0x00, 0x24, 0x00, 0x2b, 0x08, 0xbf, 0x00, 0x2a, - 0x0b, 0xd0, 0x01, 0x21, 0x78, 0x30, 0x00, 0xf0, 0xaf, 0xf8, 0x04, 0x46, - 0x32, 0x20, 0xf9, 0xf7, 0x7d, 0xfc, 0xdf, 0xf8, 0xa8, 0x16, 0x01, 0x20, - 0x08, 0x60, 0x20, 0x46, 0x10, 0xbd, 0xdf, 0xf8, 0x9c, 0x06, 0x00, 0x68, - 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0x58, 0x26, 0x04, 0x20, 0xd2, 0xe9, - 0x16, 0x45, 0x00, 0x2d, 0x08, 0xbf, 0x00, 0x2c, 0x0b, 0xd0, 0x01, 0x21, - 0x02, 0xf1, 0x50, 0x00, 0x00, 0xf0, 0x16, 0xf8, 0x32, 0x20, 0xf9, 0xf7, - 0x61, 0xfc, 0xdf, 0xf8, 0x70, 0x16, 0x00, 0x20, 0x08, 0x60, 0x32, 0xbd, - 0x30, 0xb1, 0x01, 0x28, 0x0c, 0xbf, 0xdf, 0xf8, 0x64, 0x06, 0xdf, 0xf8, - 0x64, 0x06, 0x01, 0xe0, 0xdf, 0xf8, 0x60, 0x06, 0x00, 0x78, 0x00, 0xf0, - 0x01, 0x00, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, 0x07, 0x46, 0xbc, 0x1c, - 0x88, 0x46, 0x25, 0x88, 0xb5, 0xf5, 0x10, 0x7f, 0x0c, 0xd0, 0xb5, 0xf5, - 0x2c, 0x7f, 0xa1, 0x7b, 0x14, 0xd1, 0x40, 0xf2, 0x32, 0x20, 0xf5, 0xf7, - 0xf9, 0xff, 0x62, 0x7e, 0x1f, 0x21, 0x40, 0xf6, 0x15, 0x00, 0x08, 0xe0, - 0xa1, 0x7b, 0x4f, 0xf4, 0x0c, 0x70, 0xf5, 0xf7, 0xef, 0xff, 0x62, 0x7e, - 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0xf5, 0xf7, 0xf3, 0xff, 0x03, 0xe0, - 0x40, 0xf2, 0x33, 0x20, 0xf5, 0xf7, 0xe4, 0xff, 0x39, 0x46, 0x00, 0x20, - 0x00, 0xf0, 0xd3, 0xf8, 0x17, 0xf8, 0x22, 0x2f, 0xa8, 0x1c, 0x07, 0x21, - 0x80, 0xb2, 0xf5, 0xf7, 0xe3, 0xff, 0xe1, 0x7f, 0x68, 0x1c, 0x00, 0xf0, - 0x44, 0xf8, 0xe1, 0x7b, 0x05, 0xf1, 0x42, 0x00, 0x00, 0xf0, 0x3f, 0xf8, - 0x78, 0x79, 0x28, 0xb1, 0x4f, 0xf4, 0xfa, 0x60, 0xf9, 0xf7, 0x0e, 0xfc, - 0x00, 0x20, 0x78, 0x71, 0xae, 0x1d, 0xb8, 0xf1, 0x00, 0x0f, 0x05, 0xf1, - 0x08, 0x07, 0x12, 0xd1, 0x80, 0x22, 0x80, 0x21, 0xb0, 0xb2, 0xf5, 0xf7, - 0xc7, 0xff, 0x00, 0x22, 0x80, 0x21, 0xb0, 0xb2, 0xf5, 0xf7, 0xc2, 0xff, - 0x00, 0x22, 0x02, 0x21, 0xb8, 0xb2, 0xf5, 0xf7, 0xbd, 0xff, 0x01, 0x22, - 0x01, 0x21, 0x28, 0x46, 0x18, 0xe0, 0x00, 0xf0, 0x99, 0xf8, 0xf5, 0xf7, - 0xb5, 0xff, 0xe0, 0x7e, 0x40, 0xf0, 0x80, 0x01, 0xb0, 0xb2, 0xf5, 0xf7, - 0xa5, 0xff, 0xa1, 0x7e, 0xe8, 0x1d, 0x00, 0xf0, 0x10, 0xf8, 0x00, 0xf0, - 0x84, 0xf8, 0xb8, 0xb2, 0xf5, 0xf7, 0xa6, 0xff, 0x01, 0x20, 0xf9, 0xf7, - 0xdd, 0xfb, 0x00, 0x22, 0x00, 0xf0, 0x85, 0xf8, 0xf5, 0xf7, 0x9e, 0xff, - 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x81, 0x80, 0xb2, 0xf5, 0xf7, 0x8e, 0xbf, - 0x2d, 0xe9, 0xf0, 0x41, 0x06, 0x46, 0xb4, 0x1c, 0x88, 0x46, 0x25, 0x88, - 0xb5, 0xf5, 0x10, 0x7f, 0x40, 0xf6, 0x15, 0x07, 0x08, 0xd0, 0xa1, 0x7b, - 0xb5, 0xf5, 0x2c, 0x7f, 0x0c, 0xbf, 0x40, 0xf2, 0x32, 0x20, 0x40, 0xf2, - 0x33, 0x20, 0x09, 0xe0, 0xa1, 0x7b, 0x4f, 0xf4, 0x0c, 0x70, 0xf8, 0xf7, - 0x2a, 0xf9, 0x62, 0x7e, 0x1f, 0x21, 0x40, 0xf2, 0x25, 0x50, 0x04, 0xe0, - 0xf8, 0xf7, 0x23, 0xf9, 0x62, 0x7e, 0x1f, 0x21, 0x38, 0x46, 0xf8, 0xf7, - 0x45, 0xf9, 0x31, 0x46, 0x01, 0x20, 0x00, 0xf0, 0x58, 0xf8, 0x96, 0xf8, - 0x22, 0x20, 0xa8, 0x1c, 0x07, 0x21, 0x80, 0xb2, 0xf8, 0xf7, 0x3a, 0xf9, - 0xe1, 0x7f, 0x68, 0x1c, 0x80, 0xb2, 0xf8, 0xf7, 0x0e, 0xf9, 0xe1, 0x7b, - 0x05, 0xf1, 0x42, 0x00, 0x80, 0xb2, 0xf8, 0xf7, 0x08, 0xf9, 0xaf, 0x1d, - 0xb8, 0xf1, 0x00, 0x0f, 0x05, 0xf1, 0x08, 0x06, 0x12, 0xd1, 0x80, 0x22, - 0x80, 0x21, 0xb8, 0xb2, 0xf8, 0xf7, 0x24, 0xf9, 0x00, 0x22, 0x80, 0x21, - 0xb8, 0xb2, 0xf8, 0xf7, 0x1f, 0xf9, 0x00, 0x22, 0x02, 0x21, 0xb0, 0xb2, - 0xf8, 0xf7, 0x1a, 0xf9, 0x01, 0x22, 0x01, 0x21, 0x28, 0x46, 0x19, 0xe0, - 0x00, 0xf0, 0x24, 0xf8, 0xf8, 0xf7, 0x12, 0xf9, 0xe0, 0x7e, 0x40, 0xf0, - 0x80, 0x01, 0xb8, 0xb2, 0xf8, 0xf7, 0xe5, 0xf8, 0xa1, 0x7e, 0xe8, 0x1d, - 0x80, 0xb2, 0xf8, 0xf7, 0xe0, 0xf8, 0x00, 0xf0, 0x0e, 0xf8, 0xb0, 0xb2, - 0xf8, 0xf7, 0x02, 0xf9, 0x01, 0x20, 0xf9, 0xf7, 0x67, 0xfb, 0x00, 0x22, - 0x00, 0xf0, 0x0f, 0xf8, 0xf8, 0xf7, 0xfa, 0xf8, 0x04, 0x20, 0xbd, 0xe8, - 0xf0, 0x81, 0xe0, 0x7c, 0x00, 0xf0, 0x01, 0x00, 0x40, 0xf0, 0x02, 0x02, - 0x03, 0x21, 0x70, 0x47, 0x05, 0xf1, 0x13, 0x08, 0x80, 0x22, 0x80, 0x21, - 0x1f, 0xfa, 0x88, 0xf0, 0x70, 0x47, 0xb0, 0xb5, 0x88, 0xb0, 0x04, 0x46, - 0x0d, 0x46, 0x68, 0x46, 0x0f, 0xf2, 0x48, 0x61, 0x20, 0x22, 0xfc, 0xf7, - 0x3b, 0xfd, 0xa8, 0x7c, 0x8d, 0xf8, 0x01, 0x00, 0x00, 0x27, 0xe8, 0x7c, - 0x8d, 0xf8, 0x03, 0x00, 0x28, 0x7d, 0x8d, 0xf8, 0x05, 0x00, 0x68, 0x7d, - 0x8d, 0xf8, 0x07, 0x00, 0xa8, 0x7d, 0x8d, 0xf8, 0x0b, 0x00, 0xe8, 0x7d, - 0x8d, 0xf8, 0x0f, 0x00, 0x28, 0x7e, 0x8d, 0xf8, 0x11, 0x00, 0x68, 0x7e, - 0x8d, 0xf8, 0x13, 0x00, 0xa8, 0x7e, 0x8d, 0xf8, 0x15, 0x00, 0xa8, 0x7f, - 0x8d, 0xf8, 0x19, 0x00, 0xe8, 0x7f, 0x8d, 0xf8, 0x1b, 0x00, 0x95, 0xf8, - 0x20, 0x00, 0x8d, 0xf8, 0x1d, 0x00, 0x68, 0x88, 0x1d, 0xf8, 0x17, 0x10, - 0x08, 0x18, 0x69, 0x46, 0x01, 0xeb, 0x47, 0x01, 0x01, 0x2c, 0x49, 0x78, - 0x80, 0xb2, 0x02, 0xd1, 0xf8, 0xf7, 0x85, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, - 0xcd, 0xfe, 0x7f, 0x1c, 0x0f, 0x2f, 0xec, 0xd3, 0x08, 0xb0, 0xb0, 0xbd, - 0x70, 0xb5, 0x04, 0x46, 0x00, 0x25, 0x0f, 0xf2, 0xe4, 0x56, 0x06, 0xeb, - 0x45, 0x00, 0x41, 0x78, 0x16, 0xf8, 0x15, 0x00, 0x00, 0x19, 0xff, 0xf7, - 0x2a, 0xff, 0x6d, 0x1c, 0x14, 0x2d, 0xf4, 0xd3, 0x70, 0xbd, 0x03, 0x46, - 0x06, 0x20, 0x04, 0x2b, 0x00, 0xdb, 0x70, 0x47, 0x10, 0xb5, 0x0f, 0xf2, - 0xe4, 0x54, 0x34, 0xf8, 0x13, 0x40, 0xa1, 0x42, 0x22, 0xbf, 0x0f, 0xf2, - 0xe0, 0x54, 0x34, 0xf8, 0x13, 0x40, 0x8c, 0x42, 0x14, 0xd3, 0x0f, 0xf2, - 0xdc, 0x54, 0x1c, 0x5d, 0xa2, 0x42, 0x22, 0xbf, 0x0f, 0xf2, 0xd4, 0x54, - 0x1c, 0x5d, 0x94, 0x42, 0x0a, 0xd3, 0xcd, 0x48, 0x28, 0x24, 0x04, 0xfb, - 0x03, 0x00, 0x00, 0xf1, 0x24, 0x03, 0x19, 0x80, 0x9a, 0x70, 0xbd, 0xe8, - 0x10, 0x40, 0x0b, 0xe0, 0x10, 0xbd, 0x10, 0xb5, 0xc6, 0x4b, 0x28, 0x24, - 0x04, 0xfb, 0x00, 0x30, 0x30, 0xf8, 0x24, 0x3f, 0x0b, 0x80, 0x80, 0x78, - 0x10, 0x70, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x04, 0x46, 0x89, 0xb0, - 0x20, 0x78, 0x0f, 0xf2, 0x98, 0x58, 0x0f, 0xf2, 0x80, 0x39, 0x07, 0x90, - 0x04, 0xf1, 0x10, 0x01, 0x06, 0xa8, 0xff, 0xf7, 0x2e, 0xfb, 0xc0, 0xb2, - 0x00, 0x25, 0x00, 0x28, 0x55, 0xd1, 0x59, 0xf8, 0x25, 0x00, 0x06, 0x99, - 0xb0, 0xfb, 0xf1, 0xfb, 0x0f, 0xf2, 0x74, 0x40, 0x30, 0xf8, 0x15, 0xa0, - 0x0f, 0xf2, 0x18, 0x30, 0x00, 0x68, 0x03, 0x90, 0x00, 0x27, 0x03, 0xa8, - 0x02, 0x90, 0x08, 0xeb, 0x87, 0x06, 0x04, 0xa8, 0x01, 0x90, 0xcd, 0xf8, - 0x00, 0xa0, 0x72, 0x78, 0x31, 0x78, 0x5b, 0x46, 0x20, 0x46, 0x00, 0xf0, - 0x3d, 0xf8, 0xf1, 0x78, 0x01, 0x29, 0x05, 0xd1, 0xbd, 0xf8, 0x0c, 0x10, - 0xb2, 0x78, 0x91, 0x42, 0x07, 0xd1, 0x09, 0xe0, 0x02, 0x29, 0x02, 0xbf, - 0xbd, 0xf8, 0x0e, 0x10, 0xb2, 0x78, 0x91, 0x42, 0x02, 0xd0, 0x7f, 0x1c, - 0x04, 0x2f, 0xde, 0xd3, 0x10, 0xbb, 0x07, 0x9a, 0xa2, 0x49, 0xd4, 0x23, - 0x03, 0xfb, 0x02, 0x11, 0x9d, 0xf8, 0x15, 0x20, 0x01, 0xeb, 0x85, 0x01, - 0x02, 0xf0, 0x3f, 0x02, 0x0a, 0x70, 0x9d, 0xf8, 0x10, 0x30, 0x9d, 0xf8, - 0x11, 0x20, 0x03, 0xf0, 0x0f, 0x03, 0x43, 0xea, 0x02, 0x12, 0x4a, 0x70, - 0x9d, 0xf8, 0x12, 0x30, 0x9d, 0xf8, 0x13, 0x20, 0x03, 0xf0, 0x0f, 0x03, - 0x43, 0xea, 0x02, 0x12, 0x8a, 0x70, 0x9d, 0xf8, 0x14, 0x20, 0x02, 0xf0, - 0x0f, 0x02, 0xca, 0x70, 0x6d, 0x1c, 0x35, 0x2d, 0xa7, 0xd3, 0x09, 0xb0, - 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xfe, 0x4f, 0x9c, 0xb0, 0x04, 0x46, - 0x04, 0xa8, 0x28, 0x21, 0xfa, 0xf7, 0x7e, 0xfb, 0x12, 0xa8, 0x28, 0x21, - 0xfa, 0xf7, 0x7a, 0xfb, 0x04, 0xf1, 0x24, 0x00, 0x4f, 0xf4, 0x7a, 0x72, - 0x01, 0x88, 0x0f, 0xf2, 0x6c, 0x3b, 0x51, 0x43, 0x93, 0x4a, 0xa2, 0xfb, - 0x01, 0x23, 0x12, 0x0c, 0x42, 0xea, 0x03, 0x42, 0x1b, 0x0c, 0xcd, 0xe9, - 0x00, 0x23, 0x84, 0x78, 0xdd, 0xe9, 0x00, 0x01, 0x00, 0x23, 0x22, 0x46, - 0xfa, 0xf7, 0x22, 0xf8, 0xcd, 0xe9, 0x10, 0x01, 0x4f, 0xf0, 0x00, 0x09, - 0xdd, 0xe9, 0x00, 0x01, 0xa4, 0xfb, 0x00, 0x23, 0x04, 0xfb, 0x01, 0x33, - 0xcd, 0xe9, 0x02, 0x23, 0xdd, 0xe9, 0x02, 0x01, 0x89, 0x00, 0x41, 0xea, - 0x90, 0x71, 0x80, 0x00, 0xcd, 0xe9, 0x0e, 0x01, 0xca, 0x46, 0x3f, 0x27, - 0x0c, 0x97, 0xdd, 0xe9, 0x00, 0x45, 0x1e, 0x9a, 0x28, 0x9b, 0xa2, 0xfb, - 0x04, 0x01, 0x02, 0xfb, 0x05, 0x11, 0x3a, 0x46, 0x5a, 0x43, 0x00, 0xf0, - 0xce, 0xf8, 0xdd, 0xe9, 0x10, 0x45, 0x0a, 0x90, 0x02, 0x46, 0xa2, 0xfb, - 0x04, 0x68, 0x02, 0xfb, 0x05, 0x88, 0xcd, 0xe9, 0x04, 0x68, 0x14, 0x46, - 0x50, 0x08, 0xdd, 0xe9, 0x02, 0x23, 0xa2, 0xfb, 0x04, 0x68, 0x03, 0xfb, - 0x04, 0x88, 0xdd, 0xe9, 0x04, 0x23, 0xb2, 0x1a, 0x68, 0xeb, 0x03, 0x03, - 0xcd, 0xe9, 0x06, 0x23, 0x0b, 0x90, 0xdd, 0xe9, 0x0e, 0x23, 0xa0, 0xfb, - 0x02, 0x45, 0x00, 0xfb, 0x03, 0x55, 0xcd, 0xe9, 0x08, 0x45, 0x00, 0x22, - 0x04, 0xab, 0x0a, 0xac, 0x00, 0x25, 0x0b, 0xeb, 0x05, 0x1e, 0xd3, 0xe9, - 0x00, 0x01, 0xde, 0xe9, 0x02, 0x68, 0x41, 0x45, 0x0c, 0xd3, 0x01, 0xd8, - 0xb0, 0x42, 0x09, 0xd3, 0x0b, 0xeb, 0x05, 0x1c, 0xdc, 0xe9, 0x00, 0x68, - 0x88, 0x45, 0x03, 0xd3, 0x01, 0xd8, 0x86, 0x42, 0x00, 0xd3, 0x52, 0x1c, - 0x08, 0x33, 0x6d, 0x1c, 0x03, 0x2d, 0xe6, 0xd3, 0x00, 0x20, 0x0f, 0xf2, - 0xb0, 0x23, 0x21, 0x68, 0x53, 0xf8, 0x30, 0x30, 0x99, 0x42, 0x21, 0xbf, - 0x0f, 0xf2, 0xa0, 0x23, 0x03, 0xeb, 0xc0, 0x03, 0x5b, 0x68, 0x8b, 0x42, - 0x28, 0xbf, 0x52, 0x1c, 0x24, 0x1d, 0x40, 0x1c, 0x02, 0x28, 0xec, 0xd3, - 0xad, 0xf8, 0x34, 0x20, 0x92, 0xb2, 0xbd, 0xf9, 0x70, 0x10, 0x8a, 0x42, - 0x18, 0xda, 0xbd, 0xf9, 0x74, 0x10, 0x8a, 0x42, 0x07, 0xdb, 0x91, 0x46, - 0x12, 0xa8, 0x04, 0xa9, 0x28, 0x22, 0xfc, 0xf7, 0xa5, 0xfb, 0xad, 0xf8, - 0x6e, 0x90, 0x7f, 0x1e, 0x01, 0x2f, 0x89, 0xda, 0xbd, 0xf9, 0x74, 0x00, - 0x81, 0x45, 0x0d, 0xdb, 0x29, 0x99, 0x12, 0xa8, 0x00, 0xf0, 0x10, 0xf8, - 0x1b, 0x98, 0x04, 0xe0, 0x29, 0x99, 0x04, 0xa8, 0x00, 0xf0, 0x0a, 0xf8, - 0x0d, 0x98, 0x2a, 0x99, 0x08, 0x60, 0x01, 0xe0, 0x4f, 0xf0, 0x05, 0x0a, - 0x50, 0x46, 0x1f, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf0, 0x43, - 0x00, 0xf1, 0x18, 0x04, 0x05, 0x46, 0x00, 0x6a, 0x0f, 0xf2, 0x20, 0x29, - 0x48, 0x71, 0xce, 0x1c, 0x88, 0x46, 0x00, 0x27, 0x09, 0xeb, 0xc7, 0x00, - 0x22, 0x68, 0x41, 0x68, 0x91, 0x42, 0x38, 0xbf, 0x0f, 0x20, 0x0d, 0xd3, - 0x59, 0xf8, 0x37, 0x10, 0x91, 0x42, 0x28, 0xbf, 0x00, 0x20, 0x07, 0xd2, - 0x40, 0x68, 0x41, 0x0c, 0xc0, 0x03, 0x00, 0xf0, 0x2e, 0xf8, 0xc0, 0xf5, - 0x04, 0x20, 0xc0, 0x0b, 0x24, 0x1d, 0x7f, 0x1c, 0x02, 0x2f, 0x06, 0xf8, - 0x01, 0x0b, 0xe3, 0xd3, 0x00, 0x24, 0x0f, 0xf2, 0xac, 0x16, 0x06, 0xeb, - 0x04, 0x1e, 0xd5, 0xe9, 0x00, 0x23, 0xde, 0xe9, 0x02, 0x01, 0x8b, 0x42, - 0x03, 0xd8, 0x2c, 0xbf, 0x82, 0x42, 0x0f, 0x20, 0x0c, 0xd3, 0x06, 0xeb, - 0x04, 0x1c, 0xdc, 0xe9, 0x00, 0x01, 0x8b, 0x42, 0x04, 0xd3, 0x01, 0xd8, - 0x82, 0x42, 0x01, 0xd3, 0x00, 0x20, 0x01, 0xe0, 0xf9, 0xf7, 0x3a, 0xff, - 0x08, 0x35, 0x64, 0x1c, 0x03, 0x2c, 0x08, 0xf8, 0x01, 0x0b, 0xe0, 0xd3, - 0xbd, 0xe8, 0xf0, 0x83, 0x22, 0x46, 0x00, 0x23, 0xf9, 0xf7, 0x2e, 0xbf, - 0x68, 0xee, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x48, 0xf3, 0x00, 0x20, - 0x7c, 0xdf, 0x00, 0x20, 0x80, 0x96, 0x98, 0x00, 0x00, 0xf0, 0xff, 0x00, - 0x00, 0xf8, 0x7f, 0x00, 0x00, 0xf2, 0x05, 0x2a, 0x00, 0x5e, 0xd0, 0xb2, - 0x4c, 0x29, 0x00, 0x20, 0x80, 0x18, 0x42, 0xfd, 0x81, 0xb5, 0xd8, 0x68, - 0x01, 0x9d, 0x96, 0x6b, 0x46, 0x03, 0x00, 0x46, 0x78, 0xf3, 0x00, 0x20, - 0xc7, 0x02, 0x00, 0x46, 0x57, 0x03, 0x00, 0x46, 0x57, 0x02, 0x00, 0x46, - 0x7e, 0x48, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0f, 0x0f, 0x0f, - 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0e, 0x0d, 0x0c, 0x0c, 0x0c, 0x0c, - 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0d, 0x0c, 0x0c, 0x0d, 0x0c, 0x0c, - 0x0c, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0c, 0x0c, 0x0c, 0x0b, 0x0b, 0x0c, - 0x0b, 0x0b, 0x0b, 0x0c, 0x0d, 0x0f, 0x0f, 0x0f, 0x0e, 0x0e, 0x0e, 0x0e, - 0x0e, 0x00, 0x00, 0x00, 0x48, 0x56, 0xc0, 0x00, 0x08, 0xd8, 0xba, 0x00, - 0xd0, 0xab, 0xb5, 0x00, 0xa0, 0xd1, 0xb0, 0x00, 0xc0, 0x3d, 0xac, 0x00, - 0x18, 0xf4, 0xa7, 0x00, 0xf0, 0xe8, 0xa3, 0x00, 0x60, 0x18, 0xa0, 0x00, - 0x50, 0x86, 0x9c, 0x00, 0x20, 0x23, 0x99, 0x00, 0xd8, 0xf5, 0x95, 0x00, - 0x7c, 0xf5, 0x92, 0x00, 0xb4, 0x1f, 0x90, 0x00, 0x28, 0x72, 0x8d, 0x00, - 0xf0, 0xe8, 0x8a, 0x00, 0x7c, 0x82, 0x88, 0x00, 0x48, 0x3b, 0x86, 0x00, - 0xc4, 0x11, 0x84, 0x00, 0x98, 0x03, 0x82, 0x00, 0x6c, 0x0e, 0x80, 0x00, - 0x4c, 0x30, 0x7e, 0x00, 0x0c, 0x68, 0x7c, 0x00, 0xb8, 0xb3, 0x7a, 0x00, - 0xc0, 0x11, 0x79, 0x00, 0xf8, 0x80, 0x77, 0x00, 0xd0, 0xff, 0x75, 0x00, - 0x80, 0x8d, 0x74, 0x00, 0xdc, 0x28, 0x73, 0x00, 0xb8, 0xd0, 0x71, 0x00, - 0xb0, 0x84, 0x70, 0x00, 0xfc, 0x43, 0x6f, 0x00, 0x70, 0x0d, 0x6e, 0x00, - 0x0c, 0xe1, 0x6c, 0x00, 0x08, 0xbe, 0x6b, 0x00, 0x9c, 0xa3, 0x6a, 0x00, - 0xc8, 0x91, 0x69, 0x00, 0x28, 0x88, 0x68, 0x00, 0x58, 0x86, 0x67, 0x00, - 0xf4, 0x8b, 0x66, 0x00, 0x98, 0x98, 0x65, 0x00, 0xa8, 0xac, 0x64, 0x00, - 0xc0, 0xc7, 0x63, 0x00, 0x7c, 0xe9, 0x62, 0x00, 0x78, 0x11, 0x62, 0x00, - 0x18, 0x40, 0x61, 0x00, 0xf8, 0x74, 0x60, 0x00, 0xb4, 0xaf, 0x5f, 0x00, - 0xb0, 0xf0, 0x5e, 0x00, 0x24, 0x37, 0x5e, 0x00, 0x10, 0x83, 0x5d, 0x00, - 0x10, 0xd4, 0x5c, 0x00, 0x24, 0x2a, 0x5c, 0x00, 0x84, 0x84, 0x5b, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x05, 0x09, 0x02, 0x00, 0x00, 0x00, - 0x00, 0x95, 0x8d, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xaf, 0x2b, - 0x78, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xba, 0x82, 0x07, 0x00, 0x00, 0x00, - 0x00, 0x80, 0xf1, 0x42, 0x4f, 0x00, 0x00, 0x00, 0x00, 0x18, 0x2f, 0xf4, - 0x04, 0x00, 0x00, 0x00, 0x1c, 0x02, 0x00, 0x00, 0xdb, 0x21, 0x00, 0x00, - 0xae, 0x00, 0x00, 0x00, 0xe2, 0x0a, 0x00, 0x00, 0x6e, 0x46, 0xb6, 0x3f, - 0xee, 0x39, 0xf8, 0x34, 0xac, 0x30, 0xe2, 0x2c, 0x90, 0x29, 0x9d, 0x26, - 0xff, 0x23, 0xa8, 0x21, 0x8e, 0x1f, 0xa9, 0x1d, 0xf3, 0x1b, 0x65, 0x1a, - 0xfb, 0x18, 0xb0, 0x17, 0xa8, 0x17, 0x83, 0x16, 0x75, 0x15, 0x7c, 0x14, - 0x95, 0x13, 0xbf, 0x12, 0xf8, 0x11, 0x2d, 0x12, 0x77, 0x11, 0xc2, 0x11, - 0x18, 0x11, 0x79, 0x10, 0xe4, 0x0f, 0xa7, 0x13, 0xfd, 0x12, 0x5c, 0x12, - 0xc3, 0x11, 0x33, 0x11, 0x02, 0x0d, 0x60, 0x0d, 0xfa, 0x0c, 0x99, 0x0c, - 0x3c, 0x0c, 0x38, 0x10, 0xc6, 0x0f, 0x58, 0x0f, 0xf0, 0x0e, 0x8d, 0x0f, - 0x27, 0x0f, 0xc6, 0x0e, 0x69, 0x0e, 0x0f, 0x0e, 0xbe, 0x0e, 0x66, 0x0e, - 0x11, 0x0e, 0xc0, 0x0d, 0x72, 0x0d, 0x00, 0x00, 0x1e, 0x0b, 0x50, 0x0a, - 0x78, 0x0a, 0xa0, 0x05, 0xb0, 0xb3, 0x00, 0x00, 0x36, 0x6e, 0x01, 0x00, - 0x6c, 0xdc, 0x02, 0x00, 0xd8, 0xb8, 0x05, 0x00, 0xb0, 0x71, 0x0b, 0x00, - 0x60, 0xe3, 0x16, 0x00, 0xc0, 0xc6, 0x2d, 0x00, 0x20, 0x14, 0x5d, 0x00, - 0x10, 0x17, 0x19, 0x23, 0x27, 0x2b, 0x30, 0x00, 0x0a, 0x00, 0x09, 0x00, - 0x12, 0x00, 0x08, 0x00, 0x15, 0x00, 0x21, 0x00, 0x20, 0x70, 0x0b, 0x00, - 0x0e, 0x00, 0x0f, 0x00, 0x10, 0x00, 0x0d, 0x84, 0x03, 0x00, 0x04, 0x00, - 0x05, 0x00, 0x00, 0x00, 0x1d, 0x00, 0x1d, 0x2b, 0x1c, 0x0f, 0x1d, 0x6b, - 0x1d, 0x2a, 0x1c, 0x0f, 0x1d, 0x6a, 0x1d, 0x29, 0x1c, 0x0f, 0x1d, 0x69, - 0x1d, 0x28, 0x1c, 0x00, 0x1d, 0x68, 0x1d, 0x27, 0x1c, 0x00, 0x1d, 0x67, - 0x1d, 0x26, 0x1c, 0x00, 0x1d, 0x66, 0x1d, 0x20, 0x32, 0x00, 0x32, 0x00, - 0xf4, 0x01, 0xf4, 0x01, 0xee, 0x02, 0xee, 0x02, 0xee, 0x02, 0xee, 0x02, - 0x03, 0x03, 0x03, 0x03, 0x0f, 0x0f, 0x0f, 0x0f, 0x05, 0x02, 0x05, 0x01, - 0x04, 0x04, 0x04, 0x01, 0x04, 0x03, 0x03, 0x02, 0x03, 0x02, 0x00, 0x00, - 0x03, 0x49, 0x09, 0x68, 0xc1, 0x40, 0xc8, 0x07, 0x01, 0xd4, 0x01, 0x21, - 0x03, 0xe0, 0x70, 0x47, 0x84, 0xf3, 0x00, 0x20, 0x00, 0x21, 0x40, 0xf6, - 0x01, 0x50, 0xf5, 0xf7, 0x9b, 0xbb, 0x00, 0x00, 0x70, 0xb5, 0x00, 0x20, - 0x0f, 0xf2, 0x74, 0x21, 0x11, 0xf8, 0x10, 0x30, 0x7b, 0x4c, 0x63, 0x43, - 0x7b, 0x4c, 0x24, 0x68, 0xa3, 0x42, 0x24, 0xbf, 0x01, 0xeb, 0x40, 0x02, - 0x52, 0x78, 0x40, 0x1c, 0x04, 0x28, 0xf1, 0xd3, 0xd2, 0xb2, 0x03, 0x21, - 0x4f, 0xf4, 0xbb, 0x70, 0xf5, 0xf7, 0x8c, 0xfb, 0x00, 0x24, 0x0f, 0xf2, - 0x50, 0x25, 0x0f, 0xf2, 0x60, 0x26, 0xa1, 0x5d, 0x35, 0xf8, 0x14, 0x00, - 0xf5, 0xf7, 0x78, 0xfb, 0x64, 0x1c, 0x09, 0x2c, 0xf7, 0xd3, 0x01, 0x20, - 0x70, 0xbd, 0x30, 0xb5, 0x14, 0x46, 0x6c, 0x4a, 0x0f, 0xf2, 0x18, 0x23, - 0x12, 0x78, 0x0f, 0xf2, 0x48, 0x25, 0xe3, 0x5c, 0x02, 0xf0, 0x03, 0x02, - 0x52, 0x5d, 0xd2, 0x18, 0x52, 0xb2, 0x00, 0x2a, 0x02, 0xd4, 0xf9, 0xf7, - 0x99, 0xfc, 0x02, 0xe0, 0x52, 0x42, 0xf5, 0xf7, 0x63, 0xfd, 0x07, 0x2c, - 0x08, 0xbf, 0x03, 0x22, 0x02, 0xd0, 0x08, 0x2c, 0x05, 0xd1, 0x05, 0x22, - 0xbd, 0xe8, 0x30, 0x40, 0x00, 0x23, 0xf9, 0xf7, 0x7f, 0xbd, 0x30, 0xbd, - 0x23, 0x29, 0x05, 0xd3, 0x02, 0xd8, 0xb0, 0xf1, 0xf1, 0x4f, 0x01, 0xd3, - 0x3f, 0x20, 0x0d, 0xe0, 0x40, 0x0b, 0x40, 0xea, 0xc1, 0x40, 0x50, 0x21, - 0x48, 0x43, 0x40, 0xf2, 0xcb, 0x21, 0xb0, 0xfb, 0xf1, 0xf0, 0x00, 0xf5, - 0x80, 0x40, 0xc0, 0x0b, 0x18, 0xbf, 0x40, 0x1e, 0xc0, 0xb2, 0x70, 0x47, - 0xf8, 0xb5, 0x06, 0x46, 0x4d, 0x48, 0x14, 0x46, 0x02, 0x68, 0x1d, 0x46, - 0xa2, 0xfb, 0x04, 0x01, 0x02, 0xfb, 0x05, 0x11, 0x00, 0x0f, 0x40, 0xea, - 0x01, 0x10, 0x09, 0x0f, 0x00, 0xf0, 0x98, 0xf8, 0x07, 0x00, 0x01, 0xd5, - 0x00, 0x20, 0xf2, 0xbd, 0x3a, 0x46, 0x20, 0x46, 0x29, 0x46, 0xff, 0xf7, - 0xac, 0xff, 0x05, 0x2e, 0x04, 0x46, 0x0d, 0x46, 0x03, 0xda, 0x0f, 0xf2, - 0xa8, 0x10, 0x31, 0x5c, 0x09, 0xb9, 0x40, 0x48, 0x01, 0x78, 0x40, 0xf2, - 0x0b, 0x20, 0xf5, 0xf7, 0x11, 0xfb, 0x0f, 0xf2, 0x50, 0x10, 0x39, 0x5c, - 0x40, 0xf2, 0x81, 0x10, 0xf5, 0xf7, 0x0a, 0xfb, 0x20, 0x46, 0x29, 0x46, - 0xff, 0xf7, 0xb6, 0xff, 0x02, 0x46, 0x3f, 0x21, 0x40, 0xf2, 0x77, 0x10, - 0xf5, 0xf7, 0x0a, 0xfb, 0x22, 0x0f, 0x42, 0xea, 0x05, 0x12, 0xd1, 0xb2, - 0x40, 0xf2, 0x75, 0x10, 0xf5, 0xf7, 0xf8, 0xfa, 0x6f, 0xf0, 0x70, 0x40, - 0x20, 0x40, 0x4f, 0xf4, 0xff, 0x12, 0xa2, 0xfb, 0x00, 0x45, 0x24, 0x0f, - 0x44, 0xea, 0x05, 0x14, 0xe1, 0xb2, 0x4f, 0xf4, 0xba, 0x70, 0x2d, 0x0f, - 0xf5, 0xf7, 0xe8, 0xfa, 0x24, 0x0a, 0x44, 0xea, 0x05, 0x64, 0xe1, 0xb2, - 0x40, 0xf2, 0x73, 0x10, 0xf5, 0xf7, 0xe0, 0xfa, 0x21, 0x0a, 0x4f, 0xf4, - 0xb9, 0x70, 0xf5, 0xf7, 0xdb, 0xfa, 0x01, 0x21, 0x40, 0xf2, 0x7f, 0x10, - 0xf5, 0xf7, 0xd6, 0xfa, 0x01, 0x20, 0xf2, 0xbd, 0x10, 0xb5, 0x05, 0x21, - 0x4f, 0xf4, 0xb8, 0x70, 0xf5, 0xf7, 0xce, 0xfa, 0x01, 0x21, 0x4f, 0xf4, - 0xb8, 0x70, 0xf5, 0xf7, 0xc9, 0xfa, 0x1a, 0x49, 0x01, 0x20, 0xf8, 0xf7, - 0x5d, 0xff, 0xf6, 0xf7, 0x98, 0xfd, 0x50, 0xb9, 0x17, 0x48, 0x00, 0x78, - 0x00, 0x06, 0x01, 0xd5, 0x01, 0x24, 0x05, 0xe0, 0x01, 0x20, 0xf8, 0xf7, - 0x69, 0xff, 0x00, 0x28, 0xf1, 0xd0, 0x00, 0x24, 0x01, 0x20, 0xf8, 0xf7, - 0xdb, 0xfe, 0x20, 0x46, 0x10, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x00, 0x20, - 0x10, 0x2b, 0x0e, 0xd2, 0x1b, 0x07, 0x43, 0xea, 0x12, 0x11, 0x10, 0x07, - 0x06, 0x4a, 0x12, 0x68, 0x00, 0x23, 0xf9, 0xf7, 0xd1, 0xfc, 0x02, 0x46, - 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x0b, 0x46, 0x64, 0xe7, 0x10, 0xbd, - 0x80, 0x96, 0x98, 0x00, 0x78, 0x29, 0x00, 0x20, 0x76, 0x01, 0x00, 0x46, - 0x0b, 0x02, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, 0x7f, 0x01, 0x00, 0x46, - 0x10, 0xb5, 0x4f, 0xf4, 0x7a, 0x72, 0x00, 0x23, 0xf9, 0xf7, 0xb8, 0xfc, - 0x4f, 0xf0, 0xff, 0x34, 0x00, 0x21, 0x0f, 0xf2, 0x18, 0x02, 0x52, 0xf8, - 0x21, 0x30, 0x83, 0x42, 0x01, 0xd3, 0x0c, 0x46, 0x02, 0xe0, 0x49, 0x1c, - 0x09, 0x29, 0xf6, 0xd3, 0x20, 0x46, 0x10, 0xbd, 0xf4, 0xef, 0x02, 0x00, - 0xe8, 0xdf, 0x05, 0x00, 0xd0, 0xbf, 0x0b, 0x00, 0xa0, 0x7f, 0x17, 0x00, - 0x98, 0x9e, 0x19, 0x00, 0x38, 0x07, 0x20, 0x00, 0x80, 0xb9, 0x2a, 0x00, - 0xe0, 0x7e, 0x46, 0x00, 0x60, 0x56, 0x6c, 0x00, 0x00, 0x01, 0x02, 0x03, - 0x04, 0x14, 0x24, 0x05, 0x05, 0x00, 0x00, 0x00, 0x03, 0x02, 0x01, 0x00, - 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x03, 0x08, 0x00, - 0x10, 0x01, 0x64, 0x02, 0x7d, 0x01, 0x7e, 0x01, 0x7e, 0x01, 0x7e, 0x01, - 0x79, 0x01, 0x7a, 0x01, 0x7b, 0x01, 0x7c, 0x01, 0x7f, 0x01, 0x00, 0x00, - 0x86, 0x08, 0x01, 0x05, 0xe5, 0x5b, 0x35, 0x80, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0xff, 0x00, 0x54, 0x2c, 0x04, 0xf8, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x0d, 0xd2, 0x01, 0x0e, 0x7f, 0x39, 0x0a, 0xd4, 0xd1, 0xf1, - 0x1f, 0x01, 0x04, 0xd4, 0xc0, 0x01, 0x40, 0xf0, 0x00, 0x40, 0xc8, 0x40, - 0x70, 0x47, 0x7f, 0xf0, 0x00, 0x00, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, - 0x03, 0x48, 0x00, 0x78, 0x18, 0xb9, 0x03, 0x48, 0x00, 0x78, 0x00, 0xf0, - 0x07, 0x00, 0x70, 0x47, 0x88, 0x02, 0x00, 0x20, 0x04, 0x00, 0x00, 0x46, - 0x2d, 0xe9, 0xf8, 0x43, 0x88, 0x4c, 0x4f, 0xf4, 0x94, 0x71, 0x04, 0xf1, - 0x44, 0x00, 0xf9, 0xf7, 0x89, 0xff, 0x00, 0x25, 0x85, 0x4e, 0x0f, 0xf2, - 0x2c, 0x28, 0x85, 0x4f, 0x4f, 0xf4, 0xd4, 0x79, 0x84, 0x48, 0x09, 0xfb, - 0x05, 0x00, 0x49, 0x46, 0x88, 0x30, 0xf5, 0xf7, 0xcf, 0xf9, 0x94, 0x20, - 0x00, 0xfb, 0x05, 0x40, 0x4f, 0xf4, 0x7a, 0x71, 0x01, 0x65, 0x79, 0x69, - 0x41, 0x65, 0x39, 0x6c, 0x81, 0x65, 0x00, 0x20, 0x58, 0xf8, 0x25, 0x10, - 0x08, 0x60, 0x04, 0x20, 0xa8, 0x55, 0x6d, 0x1c, 0x02, 0x2d, 0xe5, 0xd3, - 0xbd, 0xe8, 0xf1, 0x83, 0x2d, 0xe9, 0xf8, 0x43, 0x74, 0x48, 0xdf, 0xf8, - 0xc8, 0x81, 0x80, 0x7a, 0x0c, 0x46, 0x00, 0x25, 0x00, 0xf0, 0x03, 0x09, - 0x00, 0x27, 0x29, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x35, 0xd5, 0x08, 0xf5, - 0xb6, 0x70, 0x60, 0x60, 0x4f, 0xf4, 0xd4, 0x71, 0x6c, 0x48, 0x27, 0x61, - 0x01, 0xfb, 0x07, 0x00, 0xc4, 0xf8, 0x08, 0x80, 0x88, 0x30, 0x20, 0x60, - 0x94, 0x21, 0x08, 0xf1, 0x44, 0x00, 0x01, 0xfb, 0x07, 0x00, 0xe0, 0x60, - 0xf4, 0xf7, 0x74, 0xf8, 0xe0, 0x68, 0x00, 0x21, 0x41, 0x60, 0x01, 0x60, - 0x81, 0x60, 0xc1, 0x62, 0x4f, 0xf4, 0x7a, 0x71, 0xc1, 0x60, 0xf4, 0xf7, - 0x7e, 0xf8, 0x20, 0x46, 0xfc, 0xf7, 0xd7, 0xfa, 0x06, 0x00, 0x04, 0xd1, - 0x01, 0x21, 0x20, 0x46, 0xfe, 0xf7, 0x80, 0xfd, 0x06, 0x46, 0x20, 0x46, - 0xfc, 0xf7, 0xe7, 0xfa, 0xe0, 0x68, 0x16, 0xb9, 0x01, 0x21, 0xc1, 0x83, - 0x03, 0xe0, 0x00, 0x21, 0xc1, 0x83, 0x06, 0x60, 0x35, 0x46, 0x7f, 0x1c, - 0x02, 0x2f, 0xc2, 0xd3, 0x28, 0x46, 0xbd, 0xe8, 0xf2, 0x83, 0x70, 0x47, - 0x00, 0x28, 0x0c, 0xbf, 0x50, 0x49, 0x51, 0x49, 0x00, 0x22, 0x08, 0x68, - 0x0a, 0x60, 0x70, 0x47, 0x00, 0x28, 0x0c, 0xbf, 0x4c, 0x48, 0x4d, 0x48, - 0x01, 0x60, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x47, 0x48, 0x4e, 0xdf, 0xf8, - 0x14, 0xa1, 0x0c, 0x46, 0x80, 0x46, 0x44, 0x20, 0x00, 0xfb, 0x08, 0xf5, - 0xa8, 0x19, 0xa0, 0x60, 0xc4, 0xf8, 0x10, 0x80, 0x4f, 0xf4, 0xd4, 0x70, - 0x00, 0xfb, 0x08, 0x60, 0x88, 0x30, 0x20, 0x60, 0x91, 0x46, 0x94, 0x20, - 0x00, 0xfb, 0x08, 0xa0, 0x44, 0x30, 0xe0, 0x60, 0x01, 0x27, 0xf4, 0xf7, - 0x21, 0xf8, 0xa8, 0x19, 0x51, 0x46, 0x44, 0x22, 0xfb, 0xf7, 0xb4, 0xff, - 0x20, 0x68, 0x90, 0xf8, 0xa1, 0x11, 0x40, 0x46, 0xfc, 0xf7, 0xce, 0xfb, - 0xe0, 0x68, 0x21, 0x68, 0x40, 0x8b, 0x08, 0x70, 0xe0, 0x68, 0x21, 0x68, - 0x00, 0x8b, 0x48, 0x70, 0xf4, 0xf7, 0x21, 0xf8, 0xfc, 0xf7, 0xac, 0xf8, - 0x48, 0xb9, 0x0b, 0x25, 0x29, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0xab, 0xf8, - 0xe0, 0x68, 0x05, 0x60, 0x28, 0x46, 0xbd, 0xe8, 0xf0, 0x87, 0xe0, 0x68, - 0x80, 0x8b, 0x10, 0xb9, 0x03, 0x25, 0xf1, 0xe7, 0x7f, 0x1c, 0x20, 0x46, - 0xfc, 0xf7, 0x67, 0xfa, 0x05, 0x00, 0x06, 0xd0, 0x20, 0x46, 0xfc, 0xf7, - 0x7c, 0xfa, 0x15, 0x2d, 0xe6, 0xd3, 0x00, 0x25, 0xe8, 0xe7, 0x20, 0x68, - 0x01, 0x78, 0x40, 0x46, 0xfc, 0xf7, 0x99, 0xf9, 0x20, 0x46, 0xfe, 0xf7, - 0xbd, 0xf8, 0x05, 0x46, 0xe0, 0x68, 0xc1, 0x6a, 0x49, 0x1c, 0x00, 0x2d, - 0xc1, 0x62, 0xec, 0xd1, 0x81, 0x68, 0x49, 0x1c, 0xb9, 0xf1, 0x00, 0x0f, - 0x81, 0x60, 0xcf, 0xd0, 0xa1, 0x68, 0x09, 0x8b, 0x8f, 0x42, 0xd9, 0xd3, - 0xc0, 0x68, 0xf8, 0xf7, 0x51, 0xfe, 0x21, 0x68, 0xc1, 0xf8, 0x98, 0x01, - 0xc4, 0xe7, 0x10, 0xb5, 0x4f, 0xf4, 0xd4, 0x74, 0x12, 0x49, 0xc8, 0x22, - 0x02, 0xfb, 0x00, 0x12, 0x0a, 0x49, 0x10, 0x61, 0x01, 0xf5, 0xb6, 0x73, - 0x53, 0x60, 0x91, 0x60, 0x0a, 0x4b, 0x04, 0xfb, 0x00, 0x33, 0x88, 0x33, - 0x13, 0x60, 0x94, 0x23, 0x03, 0xfb, 0x00, 0x10, 0x44, 0x30, 0xd0, 0x60, - 0x00, 0x21, 0xbd, 0xe8, 0x10, 0x40, 0x10, 0x46, 0xfe, 0xf7, 0xd0, 0xbc, - 0x30, 0x27, 0x00, 0x20, 0x98, 0xf3, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, - 0x88, 0xb1, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, - 0x74, 0xe8, 0x00, 0x20, 0x00, 0x00, 0x40, 0x59, 0x00, 0x00, 0x50, 0x59, - 0x2d, 0xe9, 0xf0, 0x41, 0xf9, 0xf7, 0xf2, 0xfe, 0xf8, 0xf7, 0x6a, 0xfd, - 0xf5, 0xf7, 0xf8, 0xf9, 0x01, 0xf0, 0x54, 0xff, 0xf6, 0xf7, 0x68, 0xfe, - 0xf7, 0xf7, 0xf1, 0xfd, 0xff, 0xf7, 0x54, 0xfd, 0xfe, 0xf7, 0xd4, 0xfd, - 0xfa, 0xf7, 0x7e, 0xfa, 0xfa, 0xf7, 0x6d, 0xfa, 0x00, 0x24, 0x0f, 0xf2, - 0x54, 0x15, 0x0f, 0xf2, 0x48, 0x16, 0x36, 0xf8, 0x24, 0x00, 0x93, 0x21, - 0xf5, 0xf7, 0xde, 0xf8, 0x06, 0xeb, 0x84, 0x00, 0x82, 0x21, 0x00, 0xf0, - 0x5d, 0xf8, 0x00, 0xbf, 0x00, 0xbf, 0x00, 0xbf, 0x02, 0x21, 0x00, 0xf0, - 0x58, 0xf8, 0x35, 0xf8, 0x24, 0x00, 0x8c, 0x21, 0xf5, 0xf7, 0xce, 0xf8, - 0x05, 0xeb, 0x84, 0x00, 0x80, 0x21, 0x00, 0xf0, 0x4d, 0xf8, 0x00, 0xbf, - 0x00, 0xbf, 0x00, 0xbf, 0x00, 0x21, 0x00, 0xf0, 0x48, 0xf8, 0x64, 0x1c, - 0x02, 0x2c, 0xdc, 0xd3, 0x0f, 0xf2, 0xe4, 0x06, 0xf7, 0xf7, 0x5c, 0xfc, - 0x00, 0x24, 0x4f, 0xf0, 0x0c, 0x08, 0x00, 0x27, 0x08, 0xfb, 0x04, 0xf5, - 0x09, 0xe0, 0xa8, 0x19, 0x40, 0x68, 0x08, 0xfb, 0x07, 0x00, 0x18, 0xb1, - 0x00, 0x68, 0x01, 0x00, 0x18, 0xbf, 0x80, 0x47, 0x7f, 0x1c, 0xa8, 0x5d, - 0x87, 0x42, 0xf2, 0xd3, 0x64, 0x1c, 0x02, 0x2c, 0xeb, 0xd3, 0x12, 0x48, - 0x12, 0x4a, 0x40, 0x89, 0x10, 0xf0, 0x03, 0x01, 0x18, 0xbf, 0x01, 0x21, - 0x91, 0x60, 0xc0, 0xf3, 0x81, 0x01, 0x01, 0xb1, 0x4e, 0x21, 0x93, 0x68, - 0x19, 0x43, 0x91, 0x60, 0xc0, 0xf3, 0x01, 0x13, 0x03, 0xb1, 0x4e, 0x23, - 0x19, 0x43, 0x91, 0x60, 0xc0, 0xf3, 0x82, 0x10, 0x00, 0xb1, 0x08, 0x20, - 0x08, 0x43, 0x90, 0x60, 0x00, 0x22, 0x70, 0x21, 0x40, 0xf6, 0x8a, 0x50, - 0xf5, 0xf7, 0x8e, 0xf8, 0xbd, 0xe8, 0xf0, 0x41, 0xfb, 0xf7, 0x40, 0xbd, - 0x78, 0x29, 0x00, 0x20, 0xe8, 0xf2, 0x00, 0x20, 0x47, 0x88, 0x38, 0x46, - 0xf5, 0xf7, 0x78, 0xb8, 0x70, 0xb5, 0x04, 0x46, 0x15, 0x46, 0x0e, 0x46, - 0x28, 0x04, 0x48, 0xbf, 0xf3, 0xf7, 0x10, 0xff, 0x26, 0x60, 0x28, 0x06, - 0x44, 0xbf, 0x05, 0xf0, 0x7f, 0x00, 0x60, 0x60, 0xe8, 0x05, 0x48, 0xbf, - 0x00, 0x20, 0x03, 0xd4, 0xa8, 0x05, 0x02, 0xd5, 0xe0, 0x68, 0x40, 0x1c, - 0xe0, 0x60, 0x68, 0x05, 0x48, 0xbf, 0x00, 0x20, 0x03, 0xd4, 0x28, 0x05, - 0x02, 0xd5, 0x20, 0x69, 0x40, 0x1c, 0x20, 0x61, 0xe8, 0x04, 0x44, 0xbf, - 0x00, 0x20, 0xa0, 0x60, 0x28, 0x04, 0x44, 0xbf, 0xbd, 0xe8, 0x70, 0x40, - 0xf3, 0xf7, 0x03, 0xbf, 0x70, 0xbd, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, - 0x24, 0x9a, 0x00, 0x01, 0x60, 0xb5, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, - 0x08, 0x6f, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0xe6, 0x06, 0xe7, 0x06, - 0xe8, 0x06, 0xe9, 0x06, 0xe0, 0x08, 0xe1, 0x08, 0xe2, 0x08, 0xe3, 0x08, - 0x2d, 0xe9, 0xf1, 0x41, 0xc0, 0xf3, 0xc7, 0x50, 0xff, 0x28, 0x81, 0xb0, - 0x0c, 0x46, 0x09, 0xd1, 0x01, 0x98, 0x00, 0x26, 0x40, 0x02, 0x02, 0xd1, - 0x01, 0x98, 0x00, 0x28, 0x18, 0xd4, 0x01, 0x98, 0xbd, 0xe8, 0xf6, 0x81, - 0x01, 0x28, 0x0b, 0xda, 0x01, 0xa8, 0x00, 0xf0, 0x0f, 0xff, 0x01, 0x28, - 0x06, 0xdb, 0x00, 0xf0, 0x45, 0xff, 0x22, 0x21, 0x01, 0x60, 0x5a, 0x48, - 0xbd, 0xe8, 0xf6, 0x81, 0x01, 0x99, 0x21, 0xf0, 0xff, 0x41, 0x41, 0xf0, - 0x7c, 0x51, 0x01, 0x91, 0xa0, 0xf1, 0x7e, 0x06, 0x01, 0x98, 0x00, 0x28, - 0x07, 0xd5, 0x00, 0xf0, 0x33, 0xff, 0x21, 0x21, 0x01, 0x60, 0x6f, 0xf0, - 0x00, 0x40, 0xbd, 0xe8, 0xf6, 0x81, 0x50, 0x49, 0xf8, 0xf7, 0xae, 0xfe, - 0x06, 0xd2, 0x01, 0x46, 0x4f, 0xf0, 0x80, 0x40, 0xf8, 0xf7, 0xba, 0xfe, - 0x01, 0x90, 0x76, 0x1e, 0x01, 0x99, 0x4b, 0x48, 0xf8, 0xf7, 0x18, 0xfe, - 0x05, 0x46, 0x01, 0x99, 0x4f, 0xf0, 0x7e, 0x50, 0xf8, 0xf7, 0x12, 0xfe, - 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x1c, 0xfd, 0x07, 0x46, 0x39, 0x46, - 0xf8, 0xf7, 0xa6, 0xfe, 0x80, 0x46, 0x43, 0x48, 0x41, 0x46, 0xf8, 0xf7, - 0xa1, 0xfe, 0x42, 0x49, 0xf8, 0xf7, 0x02, 0xfe, 0x41, 0x46, 0xf8, 0xf7, - 0x9b, 0xfe, 0x40, 0x49, 0xf8, 0xf7, 0xfc, 0xfd, 0x41, 0x46, 0xf8, 0xf7, - 0x95, 0xfe, 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x81, 0xfd, 0x39, 0x46, - 0xf8, 0xf7, 0x8e, 0xfe, 0x07, 0x46, 0x30, 0xb2, 0xf8, 0xf7, 0xe2, 0xfc, - 0x06, 0x46, 0x84, 0xb9, 0x37, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x84, 0xfe, - 0x39, 0x46, 0xf8, 0xf7, 0x71, 0xfd, 0x29, 0x46, 0xf8, 0xf7, 0xe2, 0xfd, - 0x04, 0x46, 0x33, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x79, 0xfe, 0x21, 0x46, - 0x3c, 0xe0, 0x01, 0x2c, 0x23, 0xdb, 0x30, 0x48, 0x29, 0x46, 0xf8, 0xf7, - 0x71, 0xfe, 0x04, 0x46, 0x2e, 0x48, 0x29, 0x46, 0xf8, 0xf7, 0x6c, 0xfe, - 0x05, 0x46, 0x2d, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x67, 0xfe, 0x80, 0x46, - 0x2b, 0x48, 0x39, 0x46, 0xf8, 0xf7, 0x62, 0xfe, 0x01, 0x46, 0x40, 0x46, - 0xf8, 0xf7, 0x4e, 0xfd, 0x29, 0x46, 0xf8, 0xf7, 0xbf, 0xfd, 0x21, 0x46, - 0xf8, 0xf7, 0xbc, 0xfd, 0x04, 0x46, 0x25, 0x48, 0x31, 0x46, 0xf8, 0xf7, - 0x53, 0xfe, 0x21, 0x46, 0x16, 0xe0, 0x23, 0x4c, 0x28, 0x46, 0x21, 0x46, - 0xf8, 0xf7, 0x4c, 0xfe, 0x80, 0x46, 0x21, 0x48, 0x29, 0x46, 0xf8, 0xf7, - 0x47, 0xfe, 0x05, 0x46, 0x38, 0x46, 0x21, 0x46, 0xf8, 0xf7, 0x42, 0xfe, - 0x01, 0x46, 0x28, 0x46, 0xf8, 0xf7, 0x2e, 0xfd, 0x41, 0x46, 0xf8, 0xf7, - 0x9f, 0xfd, 0x31, 0x46, 0xf8, 0xf7, 0x9c, 0xfd, 0xbd, 0xe8, 0xf6, 0x81, - 0x10, 0xb5, 0x04, 0x46, 0x0a, 0x48, 0x21, 0x46, 0xf8, 0xf7, 0x30, 0xfe, - 0x09, 0x49, 0xf8, 0xf7, 0x91, 0xfd, 0x21, 0x46, 0xf8, 0xf7, 0x2a, 0xfe, - 0xbd, 0xe8, 0x10, 0x40, 0x06, 0x49, 0xf8, 0xf7, 0x89, 0xbd, 0x00, 0x00, - 0x00, 0x00, 0x80, 0xff, 0xf3, 0x04, 0x35, 0x3f, 0x00, 0x00, 0x80, 0xbf, - 0x15, 0x02, 0x99, 0x3e, 0x11, 0xae, 0xcc, 0x3e, 0xc0, 0xaa, 0x2a, 0x3f, - 0xe8, 0xe8, 0xfb, 0x33, 0x16, 0x72, 0x31, 0x3f, 0xd8, 0x5b, 0xde, 0x3e, - 0x28, 0x37, 0xa9, 0x32, 0xf4, 0x3e, 0xa1, 0x33, 0xd9, 0x5b, 0xde, 0x3e, - 0x98, 0x20, 0x9a, 0x3e, 0x3b, 0xaa, 0xb8, 0x3f, 0x60, 0x70, 0xa5, 0x32, - 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, - 0x80, 0xb5, 0xff, 0xf7, 0xf7, 0xff, 0xdf, 0xf8, 0x9c, 0x1a, 0xdf, 0xf8, - 0x9c, 0x3a, 0x09, 0x68, 0x4f, 0xf0, 0x00, 0x42, 0x1a, 0x60, 0x04, 0xbd, - 0xdf, 0xf8, 0x88, 0x3a, 0x01, 0xf0, 0x00, 0x42, 0x1a, 0x60, 0x80, 0xf3, - 0x11, 0x88, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, 0xdf, 0xf8, 0x7c, 0x6a, - 0xdf, 0xf8, 0x7c, 0x4a, 0xdf, 0xf8, 0x7c, 0x5a, 0x82, 0xb0, 0x70, 0x89, - 0xc0, 0xf3, 0x01, 0x10, 0x00, 0x28, 0x41, 0xd0, 0x07, 0x21, 0x05, 0xf1, - 0x32, 0x00, 0x00, 0xf0, 0xa3, 0xfc, 0x00, 0x21, 0x05, 0xf1, 0x34, 0x00, - 0x00, 0xf0, 0xa3, 0xfc, 0x30, 0x6c, 0xdf, 0xf8, 0x5c, 0x8a, 0x00, 0x90, - 0x23, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x36, 0x01, 0x05, 0xf1, 0x38, 0x00, - 0x00, 0xf0, 0x1b, 0xfc, 0x00, 0x20, 0x00, 0x90, 0x4f, 0xf4, 0x00, 0x63, - 0x32, 0x6c, 0x05, 0xf1, 0x36, 0x01, 0x05, 0xf1, 0x38, 0x00, 0x00, 0xf0, - 0x45, 0xfc, 0x33, 0x6c, 0x22, 0x46, 0x0a, 0x21, 0x05, 0xf1, 0x3a, 0x00, - 0x00, 0xf0, 0x21, 0xfc, 0x02, 0x27, 0x0c, 0x20, 0xc0, 0x21, 0x00, 0xfb, - 0x07, 0x80, 0x01, 0xfb, 0x07, 0x81, 0x01, 0xf5, 0x2c, 0x71, 0x01, 0x60, - 0x07, 0xeb, 0x47, 0x01, 0x41, 0x44, 0x01, 0xf2, 0xba, 0x51, 0x41, 0x60, - 0x7f, 0x1c, 0x18, 0x21, 0x01, 0x72, 0x2f, 0x21, 0x41, 0x72, 0x18, 0x21, - 0x00, 0xf0, 0x73, 0xfc, 0x04, 0x2f, 0xe6, 0xd3, 0x70, 0x89, 0xc0, 0xf3, - 0x82, 0x10, 0xd0, 0xb1, 0x07, 0x21, 0x05, 0xf1, 0x40, 0x00, 0x00, 0xf0, - 0x5d, 0xfc, 0x00, 0x21, 0x05, 0xf1, 0x42, 0x00, 0x00, 0xf0, 0x5d, 0xfc, - 0x70, 0x6d, 0x00, 0x90, 0x23, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x44, 0x01, - 0x05, 0xf1, 0x46, 0x00, 0x00, 0xf0, 0xd7, 0xfb, 0x73, 0x6d, 0x22, 0x46, - 0x0a, 0x21, 0x05, 0xf1, 0x48, 0x00, 0x00, 0xf0, 0xe8, 0xfb, 0xbd, 0xe8, - 0xf3, 0x41, 0x00, 0xe0, 0x00, 0xbf, 0xf8, 0xb5, 0xdf, 0xf8, 0xa8, 0x49, - 0xdf, 0xf8, 0x9c, 0x59, 0x0e, 0x22, 0x05, 0xf1, 0x2e, 0x01, 0x20, 0x46, - 0xfb, 0xf7, 0xd8, 0xfc, 0x0e, 0x22, 0x05, 0xf1, 0x3c, 0x01, 0x04, 0xf1, - 0x10, 0x00, 0xfb, 0xf7, 0xe1, 0xfc, 0xa5, 0x88, 0x4f, 0xf6, 0xfe, 0x70, - 0x00, 0xea, 0x05, 0x06, 0x20, 0x78, 0x01, 0x06, 0x45, 0xf0, 0x01, 0x07, - 0x07, 0xd5, 0x00, 0xf0, 0x7f, 0x00, 0x65, 0x84, 0xa5, 0x84, 0x65, 0x85, - 0xa5, 0x85, 0x20, 0x70, 0x1b, 0xe0, 0x02, 0x20, 0xf6, 0xf7, 0xe2, 0xf9, - 0x00, 0x28, 0x14, 0xbf, 0x67, 0x84, 0x66, 0x84, 0x03, 0x20, 0xf6, 0xf7, - 0xdb, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0xa7, 0x84, 0xa6, 0x84, 0x10, 0x20, - 0xf6, 0xf7, 0xd4, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0x67, 0x85, 0x66, 0x85, - 0x11, 0x20, 0xf6, 0xf7, 0xcd, 0xf9, 0x00, 0x28, 0x14, 0xbf, 0xa7, 0x85, - 0xa6, 0x85, 0x20, 0x7c, 0x01, 0x06, 0x04, 0xd5, 0x00, 0xf0, 0x7f, 0x00, - 0x25, 0x85, 0x20, 0x74, 0x06, 0xe0, 0x12, 0x20, 0xf6, 0xf7, 0xbe, 0xf9, - 0x00, 0x28, 0x14, 0xbf, 0x27, 0x85, 0x26, 0x85, 0x21, 0x78, 0x60, 0x88, - 0x00, 0x29, 0x0e, 0xbf, 0x40, 0xf0, 0x10, 0x00, 0x4f, 0xf6, 0xef, 0x71, - 0x08, 0x40, 0x60, 0x80, 0x21, 0x7c, 0x60, 0x8a, 0x00, 0x29, 0x0e, 0xbf, - 0x40, 0xf0, 0x10, 0x00, 0x4f, 0xf6, 0xef, 0x71, 0x08, 0x40, 0x60, 0x82, - 0xf1, 0xbd, 0x30, 0xb5, 0x0f, 0xf6, 0x50, 0x11, 0x0f, 0xf6, 0x2c, 0x12, - 0x51, 0xf8, 0x20, 0x30, 0xdf, 0xf8, 0xd4, 0x18, 0x0f, 0xf6, 0x60, 0x14, - 0xdf, 0xf8, 0xd0, 0x58, 0x0b, 0x63, 0x52, 0xf8, 0x20, 0x20, 0x34, 0xf8, - 0x10, 0x40, 0x2c, 0x80, 0x01, 0xeb, 0x40, 0x00, 0x00, 0x24, 0x1c, 0x70, - 0xdf, 0xf8, 0xbc, 0x38, 0xd4, 0x88, 0x5c, 0x80, 0x14, 0x89, 0x9c, 0x80, - 0x54, 0x89, 0xdc, 0x80, 0x94, 0x89, 0x1c, 0x81, 0x0c, 0x6b, 0xdf, 0xf8, - 0xac, 0x18, 0xa5, 0x89, 0x1d, 0x82, 0xe5, 0x89, 0x5d, 0x82, 0x25, 0x8a, - 0x9d, 0x82, 0x64, 0x8a, 0xdc, 0x82, 0x00, 0x24, 0x1c, 0x80, 0x00, 0x8c, - 0x18, 0x80, 0x50, 0x88, 0x08, 0x80, 0x30, 0xbd, 0xdf, 0xf8, 0x84, 0x08, - 0x4f, 0xf4, 0xc0, 0x41, 0x01, 0x80, 0xdf, 0xf8, 0x74, 0x18, 0x0a, 0x6b, - 0x7a, 0xb1, 0xb0, 0xf9, 0x10, 0x30, 0x93, 0x81, 0xb0, 0xf9, 0x12, 0x30, - 0xd3, 0x81, 0xb0, 0xf9, 0x14, 0x30, 0x13, 0x82, 0xb0, 0xf9, 0x16, 0x00, - 0x50, 0x82, 0x01, 0x20, 0x10, 0x70, 0x00, 0x20, 0x08, 0x63, 0x70, 0x47, - 0xf8, 0xb5, 0x04, 0x46, 0x0f, 0xf6, 0xb4, 0x00, 0xdf, 0xf8, 0x40, 0x78, - 0x50, 0xf8, 0x24, 0x50, 0x0f, 0xf6, 0x88, 0x00, 0x50, 0xf8, 0x24, 0x60, - 0x0f, 0xf6, 0xc0, 0x00, 0x30, 0xf8, 0x14, 0x10, 0xdf, 0xf8, 0x2c, 0x08, - 0xf7, 0xf7, 0x00, 0xf8, 0xf1, 0x88, 0xdf, 0xf8, 0x30, 0x08, 0xf6, 0xf7, - 0xfb, 0xff, 0x31, 0x89, 0xdf, 0xf8, 0x28, 0x08, 0xf6, 0xf7, 0xf6, 0xff, - 0x71, 0x89, 0xdf, 0xf8, 0x24, 0x08, 0xf6, 0xf7, 0xf1, 0xff, 0xb1, 0x89, - 0xdf, 0xf8, 0x1c, 0x08, 0xf6, 0xf7, 0xec, 0xff, 0xa9, 0x89, 0xdf, 0xf8, - 0x18, 0x08, 0xf6, 0xf7, 0xe7, 0xff, 0xe9, 0x89, 0xdf, 0xf8, 0x10, 0x08, - 0xf6, 0xf7, 0xe2, 0xff, 0x29, 0x8a, 0xdf, 0xf8, 0x0c, 0x08, 0xf6, 0xf7, - 0xdd, 0xff, 0x69, 0x8a, 0xdf, 0xf8, 0x04, 0x08, 0xf6, 0xf7, 0xd8, 0xff, - 0x29, 0x46, 0x07, 0xf1, 0x30, 0x00, 0xf6, 0xf7, 0xfb, 0xff, 0x00, 0x21, - 0x28, 0x46, 0xf6, 0xf7, 0xbf, 0xff, 0xdf, 0xf8, 0xc8, 0x57, 0x00, 0x21, - 0x28, 0x46, 0xf6, 0xf7, 0xc9, 0xff, 0x07, 0xeb, 0x44, 0x00, 0x01, 0x8c, - 0x28, 0x46, 0xf6, 0xf7, 0xc3, 0xff, 0x71, 0x88, 0xdf, 0xf8, 0xb0, 0x07, - 0xbd, 0xe8, 0xf4, 0x40, 0xf6, 0xf7, 0xbc, 0xbf, 0x70, 0xb5, 0xdf, 0xf8, - 0xa0, 0x47, 0x4f, 0xf4, 0xc0, 0x41, 0x20, 0x46, 0xf6, 0xf7, 0xb4, 0xff, - 0xdf, 0xf8, 0x88, 0x57, 0x2e, 0x6b, 0xf6, 0xb1, 0x21, 0x8a, 0x06, 0xf1, - 0x0c, 0x00, 0xf6, 0xf7, 0xab, 0xff, 0x61, 0x8a, 0x06, 0xf1, 0x0e, 0x00, - 0xf6, 0xf7, 0xa6, 0xff, 0xa1, 0x8a, 0x06, 0xf1, 0x10, 0x00, 0xf6, 0xf7, - 0xa1, 0xff, 0xe1, 0x8a, 0x06, 0xf1, 0x12, 0x00, 0xf6, 0xf7, 0x9c, 0xff, - 0x01, 0x21, 0x30, 0x46, 0xf6, 0xf7, 0x88, 0xff, 0x05, 0xf1, 0x30, 0x00, - 0xbd, 0xe8, 0x70, 0x40, 0x00, 0x21, 0xf6, 0xf7, 0xb9, 0xbf, 0x70, 0xbd, - 0xdf, 0xf8, 0x38, 0x17, 0xdf, 0xf8, 0x50, 0x07, 0xca, 0x8e, 0x4f, 0xf6, - 0xe0, 0x73, 0x1a, 0x40, 0x02, 0x80, 0x09, 0x8f, 0xc8, 0xe0, 0xdf, 0xf8, - 0x24, 0x17, 0xdf, 0xf8, 0x3c, 0x07, 0xca, 0x8e, 0x02, 0x80, 0x09, 0x8f, - 0x41, 0x80, 0x70, 0x47, 0x70, 0xb5, 0xdf, 0xf8, 0x48, 0x17, 0x82, 0xb0, - 0x00, 0x20, 0x88, 0x61, 0xdf, 0xf8, 0xfc, 0x46, 0x60, 0x89, 0xc0, 0xf3, - 0x81, 0x00, 0xb8, 0xb3, 0xdf, 0xf8, 0xf8, 0x56, 0x07, 0x21, 0x05, 0xf1, - 0x24, 0x00, 0x00, 0xf0, 0xe7, 0xfa, 0x0c, 0x21, 0x05, 0xf1, 0x26, 0x00, - 0x00, 0xf0, 0xe7, 0xfa, 0xe0, 0x6a, 0xdf, 0xf8, 0xdc, 0x66, 0x00, 0x90, - 0x33, 0x46, 0x13, 0x22, 0x05, 0xf1, 0x28, 0x01, 0x05, 0xf1, 0x2a, 0x00, - 0x00, 0xf0, 0x5f, 0xfa, 0xe3, 0x6a, 0x32, 0x46, 0x0a, 0x21, 0x05, 0xf1, - 0x2c, 0x00, 0x00, 0xf0, 0x70, 0xfa, 0x00, 0x24, 0xdf, 0xf8, 0xbc, 0x56, - 0x0c, 0x20, 0x00, 0xfb, 0x04, 0x50, 0x05, 0xeb, 0x44, 0x21, 0x30, 0x31, - 0x01, 0x60, 0x05, 0xeb, 0xc4, 0x01, 0x01, 0xf5, 0xb6, 0x61, 0x41, 0x60, - 0x64, 0x1c, 0xc0, 0x21, 0x01, 0x72, 0xff, 0x21, 0x41, 0x72, 0x40, 0x21, - 0x00, 0xf0, 0xc3, 0xfa, 0x02, 0x2c, 0xe9, 0xd3, 0x73, 0xbd, 0x10, 0xb5, - 0xdf, 0xf8, 0xbc, 0x46, 0xdf, 0xf8, 0xbc, 0x16, 0x0e, 0x22, 0x20, 0x46, - 0xfb, 0xf7, 0x5c, 0xfb, 0x20, 0x78, 0x01, 0x06, 0x03, 0xd5, 0x00, 0xf0, - 0x7f, 0x00, 0x20, 0x70, 0x17, 0xe0, 0x00, 0x20, 0xf6, 0xf7, 0x68, 0xf8, - 0xa1, 0x88, 0x00, 0x28, 0x12, 0xbf, 0x41, 0xf0, 0x01, 0x00, 0x4f, 0xf6, - 0xfe, 0x70, 0x08, 0x40, 0xa0, 0x80, 0x01, 0x20, 0xf6, 0xf7, 0x5c, 0xf8, - 0x00, 0x28, 0xa0, 0x88, 0x12, 0xbf, 0x40, 0xf0, 0x02, 0x00, 0x4f, 0xf6, - 0xfd, 0x71, 0x08, 0x40, 0xa0, 0x80, 0x00, 0x20, 0x20, 0x61, 0x06, 0x21, - 0x4f, 0xf0, 0xff, 0x30, 0xa0, 0x82, 0x02, 0x20, 0xf9, 0xf7, 0x75, 0xfc, - 0xdf, 0xf8, 0x64, 0x06, 0x4f, 0xf6, 0xff, 0x71, 0x01, 0x80, 0x4f, 0xf6, - 0xff, 0x61, 0x41, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x4f, 0xfc, 0x02, 0x20, - 0xf9, 0xf7, 0x52, 0xfc, 0x61, 0x88, 0x23, 0x78, 0xdf, 0xf8, 0x48, 0x06, - 0xdf, 0xf8, 0x48, 0x26, 0x33, 0xb9, 0x00, 0xf0, 0x11, 0xf8, 0x01, 0x20, - 0xa0, 0x61, 0xbd, 0xe8, 0x10, 0x40, 0x39, 0xe0, 0x4e, 0xf6, 0xef, 0x73, - 0x19, 0x40, 0x00, 0xf0, 0x07, 0xf8, 0x00, 0x21, 0x01, 0x82, 0x41, 0x82, - 0x01, 0x83, 0x41, 0x83, 0xa1, 0x61, 0x10, 0xbd, 0x11, 0x80, 0x4f, 0xf6, - 0xfc, 0x72, 0xa1, 0x88, 0x11, 0x40, 0x01, 0x80, 0x70, 0x47, 0xdf, 0xf8, - 0x00, 0x06, 0x00, 0x21, 0x81, 0x61, 0x4f, 0xf6, 0xfc, 0x72, 0x4f, 0xf0, - 0xff, 0x31, 0x81, 0x82, 0xdf, 0xf8, 0xf8, 0x05, 0x01, 0x88, 0x11, 0x40, - 0x01, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x29, 0xbc, 0xdf, 0xf8, 0xdc, 0x15, - 0xdf, 0xf8, 0xec, 0x05, 0x0a, 0x89, 0x4f, 0xf6, 0xe0, 0x73, 0x1a, 0x40, - 0x02, 0x80, 0x49, 0x89, 0x19, 0x40, 0x41, 0x80, 0x70, 0x47, 0xdf, 0xf8, - 0xc4, 0x15, 0xdf, 0xf8, 0xd4, 0x05, 0x0a, 0x89, 0x02, 0x80, 0x49, 0x89, - 0x41, 0x80, 0x70, 0x47, 0xf8, 0xb5, 0xdf, 0xf8, 0xb0, 0x45, 0xa0, 0x69, - 0x00, 0x28, 0x5d, 0xd0, 0xdf, 0xf8, 0xb0, 0x55, 0x28, 0x88, 0x4f, 0xf6, - 0xfc, 0x71, 0x08, 0x40, 0x28, 0x80, 0x00, 0xf0, 0x9f, 0xfa, 0x20, 0x79, - 0x00, 0x27, 0xc0, 0x07, 0x4f, 0xf0, 0xff, 0x36, 0x05, 0xd5, 0x00, 0x20, - 0x00, 0xf0, 0x84, 0xfd, 0x08, 0xb9, 0x26, 0x8a, 0x01, 0x27, 0x20, 0x79, - 0x80, 0x07, 0x09, 0xd5, 0x01, 0x20, 0x00, 0xf0, 0x7b, 0xfd, 0x28, 0xb9, - 0x60, 0x8a, 0x86, 0x42, 0x47, 0xf0, 0x02, 0x07, 0x28, 0xbf, 0x06, 0x46, - 0x22, 0x8a, 0xdf, 0xf8, 0x28, 0x05, 0x0a, 0x21, 0x96, 0x42, 0x01, 0xfb, - 0x06, 0x01, 0x06, 0xd2, 0x91, 0xf8, 0x5a, 0x20, 0xd2, 0x07, 0x5c, 0xbf, - 0x4f, 0xf6, 0xfe, 0x72, 0x17, 0x40, 0x62, 0x8a, 0x96, 0x42, 0x06, 0xd2, - 0x91, 0xf8, 0x5a, 0x20, 0x92, 0x07, 0x5c, 0xbf, 0x4f, 0xf6, 0xfd, 0x72, - 0x17, 0x40, 0xbf, 0xb1, 0xb0, 0xf8, 0x58, 0x00, 0x86, 0x42, 0x32, 0xbf, - 0x01, 0xf1, 0x5a, 0x00, 0x06, 0x46, 0x20, 0x1d, 0x41, 0x88, 0x69, 0x80, - 0x81, 0x88, 0xa9, 0x80, 0xc1, 0x88, 0xe9, 0x80, 0x01, 0x89, 0x29, 0x81, - 0x4f, 0xf6, 0xfc, 0x71, 0x00, 0x88, 0x08, 0x40, 0x38, 0x43, 0x28, 0x80, - 0x30, 0x46, 0x01, 0xe0, 0x4f, 0xf0, 0xff, 0x30, 0x47, 0xea, 0x06, 0x11, - 0xa0, 0x82, 0x3d, 0x20, 0xbd, 0xe8, 0xf4, 0x40, 0xf9, 0xf7, 0x3e, 0xbc, - 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xf5, 0xfc, 0xdf, 0xf8, - 0xe0, 0x14, 0x05, 0x46, 0x01, 0xeb, 0x44, 0x01, 0x00, 0x20, 0x08, 0x82, - 0x00, 0x22, 0x00, 0x21, 0x20, 0x46, 0x00, 0xf0, 0x03, 0xf8, 0x85, 0xf3, - 0x11, 0x88, 0x31, 0xbd, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, - 0xff, 0xf7, 0xe0, 0xfc, 0x07, 0x46, 0xdf, 0xf8, 0xc0, 0x04, 0x01, 0x88, - 0x4f, 0xf6, 0xfc, 0x72, 0x11, 0x40, 0x01, 0x80, 0x14, 0xb9, 0x05, 0x82, - 0x46, 0x82, 0x03, 0xe0, 0x01, 0x2c, 0x04, 0xbf, 0x05, 0x83, 0x46, 0x83, - 0xff, 0xf7, 0x70, 0xff, 0x87, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0x2d, 0xe9, - 0xf8, 0x43, 0x80, 0x46, 0x0f, 0xf2, 0xc4, 0x40, 0x50, 0xf8, 0x28, 0x50, - 0x0e, 0x46, 0x17, 0x46, 0xff, 0xf7, 0xc6, 0xfc, 0x04, 0x46, 0x89, 0x46, - 0xf9, 0xf7, 0x7e, 0xfd, 0x40, 0x45, 0x0a, 0xd1, 0xdf, 0xf8, 0x40, 0x04, - 0x01, 0x88, 0x4f, 0xf6, 0xfe, 0x72, 0x0a, 0x40, 0x02, 0x80, 0x06, 0x82, - 0x47, 0x82, 0x01, 0x80, 0x03, 0xe0, 0xae, 0x81, 0xef, 0x81, 0x01, 0x20, - 0x28, 0x70, 0x20, 0x46, 0x49, 0x46, 0xbd, 0xe8, 0xf4, 0x43, 0xb7, 0xe4, - 0x00, 0x28, 0xdf, 0xf8, 0x40, 0x14, 0x0c, 0xbf, 0x01, 0x20, 0x02, 0x20, - 0x89, 0x88, 0x08, 0x40, 0x70, 0x47, 0xdf, 0xf8, 0x00, 0x14, 0x01, 0xeb, - 0x40, 0x00, 0x90, 0xf8, 0x20, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x70, 0x47, - 0xdf, 0xf8, 0x1c, 0x24, 0x02, 0xeb, 0x40, 0x00, 0x00, 0x21, 0x01, 0x82, - 0x2e, 0xe7, 0x2d, 0xe9, 0xfc, 0x47, 0x06, 0x46, 0xdf, 0xf8, 0xd4, 0x93, - 0x0c, 0x20, 0x88, 0x46, 0x17, 0x46, 0x00, 0xfb, 0x06, 0x9a, 0x39, 0x46, - 0x50, 0x46, 0x00, 0xf0, 0x6a, 0xf9, 0x00, 0x25, 0x20, 0xb1, 0x39, 0x46, - 0x50, 0x46, 0x00, 0xf0, 0x58, 0xf9, 0x05, 0x46, 0xdf, 0xf8, 0xf0, 0x73, - 0xdf, 0xf8, 0xe0, 0x43, 0x38, 0x88, 0x4f, 0xf6, 0xfc, 0x71, 0x08, 0x40, - 0x38, 0x80, 0x06, 0xbb, 0xb7, 0xf9, 0x10, 0x00, 0xad, 0xf8, 0x00, 0x00, - 0x6a, 0x46, 0xb7, 0xf9, 0x12, 0x00, 0xad, 0xf8, 0x02, 0x00, 0x41, 0x46, - 0xb7, 0xf9, 0x14, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb7, 0xf9, 0x16, 0x00, - 0xad, 0xf8, 0x06, 0x00, 0x48, 0x46, 0x00, 0xf0, 0x59, 0xf9, 0x3d, 0xb1, - 0x28, 0x88, 0x38, 0x82, 0x68, 0x88, 0x78, 0x82, 0xa8, 0x88, 0xb8, 0x82, - 0xe8, 0x88, 0xf8, 0x82, 0x00, 0x20, 0x20, 0x82, 0x21, 0xe0, 0x01, 0x2e, - 0x1f, 0xd1, 0xb7, 0xf9, 0x18, 0x00, 0xad, 0xf8, 0x00, 0x00, 0x6a, 0x46, - 0xb7, 0xf9, 0x1a, 0x00, 0xad, 0xf8, 0x02, 0x00, 0x41, 0x46, 0xb7, 0xf9, - 0x1c, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb7, 0xf9, 0x1e, 0x00, 0xad, 0xf8, - 0x06, 0x00, 0x50, 0x46, 0x00, 0xf0, 0x36, 0xf9, 0x3d, 0xb1, 0x28, 0x88, - 0x38, 0x83, 0x68, 0x88, 0x78, 0x83, 0xa8, 0x88, 0xb8, 0x83, 0xe8, 0x88, - 0xf8, 0x83, 0x00, 0x20, 0x60, 0x82, 0xff, 0xf7, 0xcb, 0xfe, 0xbd, 0xe8, - 0xf3, 0x87, 0x2d, 0xe9, 0xfc, 0x47, 0x06, 0x46, 0x04, 0x2e, 0x8a, 0x46, - 0x14, 0x46, 0x57, 0xda, 0xc0, 0x48, 0x0c, 0x21, 0x01, 0xfb, 0x06, 0x08, - 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0x03, 0xf9, 0x00, 0x25, 0x20, 0xb1, - 0x21, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xf1, 0xf8, 0x05, 0x46, 0xff, 0xf7, - 0x15, 0xfc, 0x02, 0x2e, 0x04, 0x46, 0x89, 0x46, 0x02, 0xd1, 0xf5, 0xf7, - 0xec, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, 0xfd, 0xf8, 0x06, 0x46, 0xf9, 0xf7, - 0xc5, 0xfc, 0xb0, 0x42, 0x25, 0xd1, 0xb4, 0x4e, 0x37, 0x88, 0x4f, 0xf6, - 0xfe, 0x70, 0x38, 0x40, 0x30, 0x80, 0x6a, 0x46, 0xb6, 0xf9, 0x10, 0x00, - 0xad, 0xf8, 0x00, 0x00, 0x51, 0x46, 0xb6, 0xf9, 0x12, 0x00, 0xad, 0xf8, - 0x02, 0x00, 0xb6, 0xf9, 0x14, 0x00, 0xad, 0xf8, 0x04, 0x00, 0xb6, 0xf9, - 0x16, 0x00, 0xad, 0xf8, 0x06, 0x00, 0x40, 0x46, 0x00, 0xf0, 0xe6, 0xf8, - 0x3d, 0xb1, 0x28, 0x88, 0x30, 0x82, 0x68, 0x88, 0x70, 0x82, 0xa8, 0x88, - 0xb0, 0x82, 0xe8, 0x88, 0xf0, 0x82, 0x37, 0x80, 0x0e, 0xe0, 0x6d, 0xb1, - 0x0f, 0xf2, 0xe8, 0x20, 0x50, 0xf8, 0x26, 0x00, 0x29, 0x88, 0x81, 0x81, - 0x69, 0x88, 0xc1, 0x81, 0xa9, 0x88, 0x01, 0x82, 0xe9, 0x88, 0x41, 0x82, - 0x01, 0x21, 0x01, 0x70, 0x20, 0x46, 0x49, 0x46, 0xff, 0xf7, 0xda, 0xfb, - 0xbd, 0xe8, 0xf3, 0x87, 0x10, 0xf1, 0x14, 0x0f, 0xb8, 0xbf, 0x1f, 0x20, - 0x04, 0xdb, 0x0a, 0x28, 0xac, 0xbf, 0x00, 0x20, 0xc0, 0xf1, 0x0a, 0x00, - 0x80, 0xb2, 0x70, 0x47, 0x10, 0xb5, 0x91, 0x42, 0x04, 0x46, 0x05, 0xd2, - 0xb2, 0xfb, 0xf1, 0xf0, 0xf9, 0xf7, 0x4f, 0xfa, 0x24, 0x1a, 0x06, 0xe0, - 0x8a, 0x42, 0x04, 0xd2, 0xb1, 0xfb, 0xf2, 0xf0, 0xf9, 0xf7, 0x47, 0xfa, - 0x04, 0x19, 0x20, 0x46, 0x10, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x1f, 0x2a, - 0xac, 0xbf, 0x6f, 0xf0, 0x14, 0x00, 0xc2, 0xf1, 0x0a, 0x00, 0x0d, 0x46, - 0x04, 0x9a, 0x19, 0x46, 0xff, 0xf7, 0xe0, 0xff, 0xff, 0xf7, 0xd2, 0xff, - 0x21, 0x88, 0x4e, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x21, - 0x21, 0x80, 0x29, 0x88, 0x17, 0xe0, 0x38, 0xb5, 0x05, 0x46, 0x0f, 0x29, - 0x14, 0x46, 0xac, 0xbf, 0x6f, 0xf0, 0x0e, 0x00, 0x48, 0x42, 0x1a, 0x46, - 0x21, 0x46, 0xff, 0xf7, 0xc9, 0xff, 0x00, 0x28, 0x58, 0xbf, 0x00, 0x20, - 0x04, 0xd5, 0x10, 0xf1, 0x0e, 0x0f, 0xb4, 0xbf, 0x0f, 0x20, 0x40, 0x42, - 0x29, 0x88, 0x4f, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x20, - 0x28, 0x80, 0x31, 0xbd, 0xf8, 0xb5, 0x05, 0x46, 0x0c, 0x46, 0x10, 0x46, - 0x1e, 0x46, 0xf7, 0xf7, 0xd3, 0xff, 0x79, 0x49, 0xf8, 0xf7, 0x6e, 0xf9, - 0x07, 0x46, 0x30, 0x46, 0xf7, 0xf7, 0xcc, 0xff, 0x01, 0x46, 0x38, 0x46, - 0xf7, 0xf7, 0xd8, 0xff, 0xff, 0xf7, 0x64, 0xf8, 0x06, 0x99, 0x46, 0x1a, - 0x30, 0x00, 0x18, 0xbf, 0x01, 0x20, 0xc0, 0xb2, 0xf9, 0xf7, 0xb7, 0xf9, - 0x30, 0x46, 0xf7, 0xf7, 0xbb, 0xff, 0x4f, 0xf0, 0xff, 0x37, 0x39, 0x46, - 0xff, 0xf7, 0x5e, 0xfa, 0x01, 0x46, 0x6b, 0x48, 0xf8, 0xf7, 0x40, 0xf8, - 0xf8, 0xf7, 0xba, 0xf9, 0xff, 0xf7, 0x80, 0xff, 0x2a, 0x88, 0x01, 0x02, - 0xc2, 0xf3, 0x04, 0x23, 0x98, 0x42, 0x04, 0xd2, 0x4e, 0xf2, 0xff, 0x03, - 0x1a, 0x40, 0x0a, 0x43, 0x2a, 0x80, 0x22, 0x88, 0xc2, 0xf3, 0x04, 0x23, - 0x98, 0x42, 0x04, 0xd2, 0x4e, 0xf2, 0xff, 0x00, 0x10, 0x40, 0x08, 0x43, - 0x20, 0x80, 0xf1, 0xbd, 0x02, 0x88, 0x61, 0xf3, 0x0a, 0x22, 0x02, 0x80, - 0x70, 0x47, 0x02, 0x88, 0x02, 0xf4, 0x7f, 0x42, 0x11, 0x43, 0x01, 0x80, - 0x70, 0x47, 0x40, 0x68, 0xc9, 0x08, 0xf4, 0xf7, 0x2b, 0xba, 0x38, 0xb5, - 0x04, 0x46, 0x00, 0xf0, 0x3e, 0xf8, 0x00, 0x25, 0x00, 0x28, 0x5c, 0xbf, - 0x21, 0x68, 0x01, 0xeb, 0xc0, 0x05, 0x28, 0x46, 0x32, 0xbd, 0x38, 0xb5, - 0x05, 0x46, 0x00, 0xf0, 0x32, 0xf8, 0x00, 0x24, 0x00, 0x28, 0x0b, 0xd4, - 0x69, 0x68, 0xc2, 0x10, 0x00, 0xf0, 0x07, 0x00, 0x51, 0x5c, 0x01, 0x22, - 0x02, 0xfa, 0x00, 0xf0, 0x08, 0x40, 0x01, 0x28, 0xa8, 0xbf, 0x01, 0x24, - 0x20, 0x46, 0x32, 0xbd, 0x70, 0xb5, 0x04, 0x46, 0x15, 0x46, 0x00, 0xf0, - 0x1c, 0xf8, 0x00, 0x28, 0x18, 0xd4, 0x00, 0xf0, 0x07, 0x02, 0x01, 0x23, - 0x03, 0xfa, 0x02, 0xf2, 0x63, 0x68, 0xc1, 0x10, 0xce, 0x5c, 0x96, 0x43, - 0xce, 0x54, 0x23, 0x68, 0x03, 0xeb, 0xc0, 0x00, 0x2b, 0x88, 0x03, 0x80, - 0x6b, 0x88, 0x43, 0x80, 0xab, 0x88, 0x83, 0x80, 0xeb, 0x88, 0xc3, 0x80, - 0x60, 0x68, 0x0b, 0x5c, 0x1a, 0x43, 0x0a, 0x54, 0x70, 0xbd, 0x03, 0x7a, - 0x4f, 0xf0, 0xff, 0x32, 0x99, 0x42, 0x22, 0xbf, 0x40, 0x7a, 0x88, 0x42, - 0xca, 0x1a, 0x10, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x3c, 0x20, 0xf9, 0xf7, - 0xf6, 0xf9, 0x29, 0x48, 0x04, 0x88, 0x4f, 0xf6, 0xfc, 0x71, 0x21, 0x40, - 0x01, 0x80, 0x00, 0xf0, 0x19, 0xf8, 0x22, 0x48, 0xb0, 0xf9, 0x14, 0x10, - 0x00, 0x29, 0x10, 0xd4, 0x00, 0x22, 0x0f, 0xf2, 0xec, 0x03, 0x33, 0xf8, - 0x12, 0x50, 0x2c, 0x42, 0x06, 0xd0, 0x00, 0xeb, 0x42, 0x05, 0x2e, 0x8a, - 0xb1, 0x42, 0xa4, 0xbf, 0x76, 0x1c, 0x2e, 0x82, 0x52, 0x1c, 0x02, 0x2a, - 0xf1, 0xd3, 0xbd, 0xe8, 0x70, 0x40, 0x51, 0xe5, 0x4f, 0xf4, 0x80, 0x70, - 0x16, 0x49, 0x08, 0x80, 0x02, 0x20, 0xf9, 0xf7, 0x4f, 0xb9, 0x00, 0x00, - 0x00, 0xe1, 0x00, 0xe0, 0x80, 0xe1, 0x00, 0xe0, 0x78, 0x29, 0x00, 0x20, - 0x00, 0x00, 0xa6, 0x0e, 0x4c, 0x1f, 0x00, 0x20, 0x80, 0xa2, 0x00, 0x20, - 0x14, 0xc8, 0x00, 0x20, 0x02, 0x08, 0x00, 0x41, 0x20, 0x01, 0x00, 0x41, - 0xfe, 0x01, 0x00, 0x41, 0x22, 0x01, 0x00, 0x41, 0x24, 0x01, 0x00, 0x41, - 0x26, 0x01, 0x00, 0x41, 0x28, 0x01, 0x00, 0x41, 0x30, 0x01, 0x00, 0x41, - 0x32, 0x01, 0x00, 0x41, 0x34, 0x01, 0x00, 0x41, 0x36, 0x01, 0x00, 0x41, - 0xcc, 0xf2, 0x00, 0x20, 0x6c, 0x1f, 0x00, 0x20, 0x08, 0x08, 0x00, 0x41, - 0x00, 0x01, 0x00, 0x41, 0xfc, 0x01, 0x00, 0x41, 0x04, 0x01, 0x00, 0x41, - 0x34, 0x80, 0x37, 0x3a, 0x48, 0xe1, 0x9a, 0xbf, 0x00, 0x00, 0x00, 0x00, - 0x14, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x24, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, 0x14, 0xc8, 0x00, 0x20, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0x20, 0x00, 0x20, - 0x78, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x20, 0x00, 0x20, - 0xa0, 0x20, 0x00, 0x20, 0xb4, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x1f, 0xb5, 0x00, 0xf0, - 0xb7, 0xf8, 0x21, 0x21, 0x01, 0x60, 0x1f, 0xbd, 0xf8, 0xb5, 0x0c, 0x46, - 0x2b, 0x49, 0xf8, 0xf7, 0x4d, 0xf9, 0x05, 0x46, 0x12, 0xd8, 0x2a, 0x4e, - 0x31, 0x46, 0xf8, 0xf7, 0x3f, 0xf8, 0x29, 0x49, 0xf7, 0xf7, 0xa0, 0xff, - 0x07, 0x46, 0x28, 0x46, 0x31, 0x46, 0xf7, 0xf7, 0x9b, 0xff, 0x01, 0x46, - 0x38, 0x46, 0xf7, 0xf7, 0xa5, 0xfe, 0x05, 0x46, 0x44, 0xf0, 0x01, 0x04, - 0x28, 0x46, 0x22, 0x49, 0xf8, 0xf7, 0x1a, 0xf8, 0x03, 0xd3, 0x21, 0x49, - 0xf8, 0xf7, 0x30, 0xf9, 0x21, 0xd8, 0x29, 0x46, 0xf8, 0xf7, 0x24, 0xf8, - 0x06, 0x46, 0x28, 0x46, 0x31, 0x46, 0xf8, 0xf7, 0x1f, 0xf8, 0x1c, 0x49, - 0xf8, 0xf7, 0x1c, 0xf8, 0x29, 0x46, 0xf7, 0xf7, 0x7d, 0xff, 0x05, 0x46, - 0x19, 0x48, 0x31, 0x46, 0xf8, 0xf7, 0x14, 0xf8, 0x18, 0x49, 0xf7, 0xf7, - 0x75, 0xff, 0x31, 0x46, 0xf8, 0xf7, 0x0e, 0xf8, 0x4f, 0xf0, 0x7e, 0x51, - 0xf7, 0xf7, 0x6e, 0xff, 0x01, 0x46, 0x28, 0x46, 0xf7, 0xf7, 0x78, 0xfe, - 0x05, 0x46, 0xa0, 0x07, 0x48, 0xbf, 0x85, 0xf0, 0x00, 0x45, 0x14, 0xf0, - 0x07, 0x00, 0x07, 0xd0, 0x0f, 0xf2, 0x38, 0x01, 0x51, 0xf8, 0x20, 0x00, - 0x29, 0x46, 0xf7, 0xf7, 0x5b, 0xff, 0x05, 0x46, 0x20, 0x07, 0x48, 0xbf, - 0x85, 0xf0, 0x00, 0x45, 0x28, 0x46, 0xf2, 0xbd, 0xa4, 0x30, 0x89, 0x3e, - 0xd7, 0xb3, 0xdd, 0x3f, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x80, 0xb9, - 0x01, 0x00, 0x80, 0x39, 0x6a, 0xd5, 0x03, 0x3f, 0x2b, 0x94, 0xa9, 0x3d, - 0xb8, 0x2a, 0x59, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x92, 0x0a, 0x06, 0x3f, - 0xdb, 0x0f, 0xc9, 0x3f, 0x92, 0x0a, 0x86, 0x3f, 0xdb, 0x0f, 0xc9, 0x3f, - 0x92, 0x0a, 0x06, 0x40, 0xdb, 0x0f, 0x49, 0x40, 0x36, 0x8d, 0x27, 0x40, - 0x02, 0x68, 0x02, 0xf0, 0x00, 0x43, 0x01, 0x21, 0x52, 0x02, 0x52, 0x0a, - 0x02, 0xd1, 0x06, 0xe0, 0x52, 0x00, 0x49, 0x1e, 0x5f, 0xea, 0x02, 0x2c, - 0xfa, 0xd5, 0x52, 0x02, 0x52, 0x0a, 0x1a, 0x43, 0x02, 0x60, 0x08, 0x46, - 0x70, 0x47, 0x02, 0x68, 0xc2, 0xf3, 0xc7, 0x52, 0xff, 0x2a, 0x05, 0xd1, - 0x00, 0x68, 0x40, 0x02, 0x0c, 0xbf, 0x01, 0x20, 0x02, 0x20, 0x70, 0x47, - 0x03, 0x68, 0x5b, 0x00, 0x16, 0xd0, 0xc2, 0xf1, 0x96, 0x02, 0x52, 0x1a, - 0x01, 0x2a, 0x11, 0xdb, 0x18, 0x2a, 0x04, 0xdb, 0x01, 0x68, 0x01, 0xf0, - 0x00, 0x41, 0x01, 0x60, 0x07, 0xe0, 0x01, 0x21, 0x91, 0x40, 0x02, 0x68, - 0x49, 0x1e, 0x11, 0x40, 0x4a, 0x40, 0x02, 0x60, 0x11, 0xb1, 0x4f, 0xf0, - 0xff, 0x30, 0x70, 0x47, 0x00, 0x20, 0x70, 0x47, 0x01, 0x48, 0xf1, 0xf7, - 0x86, 0xb9, 0x00, 0x00, 0x1c, 0xbd, 0x00, 0x20, 0x2d, 0xe9, 0xf0, 0x4d, - 0x04, 0x46, 0x0d, 0x46, 0x27, 0x68, 0xc7, 0xf3, 0xc7, 0x51, 0xff, 0x29, - 0x16, 0x46, 0x09, 0xd0, 0x11, 0xb1, 0x4f, 0xf0, 0xff, 0x30, 0x09, 0xe0, - 0x78, 0x02, 0x0c, 0xbf, 0x00, 0x20, 0x6f, 0xf0, 0x01, 0x00, 0x03, 0xe0, - 0x78, 0x02, 0x14, 0xbf, 0x02, 0x20, 0x01, 0x20, 0xc5, 0xf3, 0xc7, 0x52, - 0xff, 0x2a, 0x09, 0xd0, 0x12, 0xb1, 0x4f, 0xf0, 0xff, 0x31, 0x09, 0xe0, - 0x69, 0x02, 0x0c, 0xbf, 0x00, 0x21, 0x6f, 0xf0, 0x01, 0x01, 0x03, 0xe0, - 0x69, 0x02, 0x14, 0xbf, 0x02, 0x21, 0x01, 0x21, 0x02, 0x00, 0x48, 0xbf, - 0x00, 0x29, 0x3e, 0xd4, 0x02, 0x28, 0x00, 0xf0, 0xc6, 0x80, 0x02, 0x29, - 0x08, 0xbf, 0x25, 0x60, 0x18, 0xd0, 0x39, 0xb9, 0x38, 0x46, 0x4f, 0xf0, - 0xff, 0x41, 0xf7, 0xf7, 0x35, 0xff, 0x0a, 0xd0, 0x25, 0x60, 0x38, 0xe0, - 0x01, 0x29, 0x10, 0xd1, 0x38, 0x46, 0x5c, 0x49, 0xf7, 0xf7, 0x2c, 0xff, - 0x18, 0xbf, 0x25, 0x60, 0x40, 0xd1, 0xff, 0xf7, 0xb1, 0xff, 0x21, 0x21, - 0x01, 0x60, 0x6f, 0xf0, 0x00, 0x40, 0x20, 0x60, 0x02, 0x20, 0xbd, 0xe8, - 0xf0, 0x8d, 0x70, 0xb9, 0x25, 0x60, 0x31, 0x46, 0x20, 0x46, 0x00, 0xf0, - 0x61, 0xff, 0x04, 0x00, 0x18, 0xbf, 0x01, 0x2c, 0x40, 0xf0, 0x9a, 0x80, - 0xff, 0xf7, 0x9c, 0xff, 0x22, 0x21, 0x01, 0x60, 0x94, 0xe0, 0x38, 0x46, - 0x4f, 0xf0, 0xff, 0x41, 0xf7, 0xf7, 0x0a, 0xff, 0x0a, 0xd1, 0x08, 0x46, - 0x29, 0x46, 0xf7, 0xf7, 0x25, 0xff, 0x20, 0x60, 0x1a, 0xe0, 0x38, 0x46, - 0x46, 0x49, 0xf7, 0xf7, 0x0d, 0xff, 0x07, 0xd2, 0x00, 0x20, 0x29, 0x46, - 0xf7, 0xf7, 0x1a, 0xff, 0x20, 0x60, 0x00, 0x20, 0xbd, 0xe8, 0xf0, 0x8d, - 0x41, 0x49, 0xf8, 0xf7, 0x1b, 0xf8, 0x0c, 0xd8, 0x4f, 0xf0, 0xff, 0x40, - 0x29, 0x46, 0xf7, 0xf7, 0x0d, 0xff, 0x20, 0x60, 0xff, 0xf7, 0x74, 0xff, - 0x22, 0x21, 0x01, 0x60, 0x01, 0x20, 0xbd, 0xe8, 0xf0, 0x8d, 0x3a, 0x48, - 0x39, 0x46, 0xf7, 0xf7, 0x01, 0xff, 0x00, 0x21, 0xf7, 0xf7, 0xec, 0xfe, - 0x34, 0xbf, 0x4f, 0xf0, 0x3f, 0x41, 0x4f, 0xf0, 0x7c, 0x51, 0xf7, 0xf7, - 0x5b, 0xfe, 0xf7, 0xf7, 0x61, 0xff, 0x80, 0x46, 0xf7, 0xf7, 0x4a, 0xfd, - 0x82, 0x46, 0x31, 0x48, 0x51, 0x46, 0xf7, 0xf7, 0xed, 0xfe, 0x01, 0x46, - 0x38, 0x46, 0xf7, 0xf7, 0xd9, 0xfd, 0x07, 0x46, 0x2d, 0x48, 0x51, 0x46, - 0xf7, 0xf7, 0xe4, 0xfe, 0x01, 0x46, 0x38, 0x46, 0xf7, 0xf7, 0xd0, 0xfd, - 0x4f, 0xf0, 0x33, 0x41, 0xf7, 0xf7, 0xe4, 0xff, 0x82, 0x46, 0x03, 0xd8, - 0x27, 0x49, 0xf7, 0xf7, 0xc5, 0xfe, 0x2d, 0xd3, 0x51, 0x46, 0xf7, 0xf7, - 0xd3, 0xfe, 0x83, 0x46, 0x24, 0x48, 0x59, 0x46, 0xf7, 0xf7, 0xce, 0xfe, - 0x07, 0x46, 0x23, 0x48, 0x59, 0x46, 0xf7, 0xf7, 0xc9, 0xfe, 0x4f, 0xf0, - 0x7c, 0x51, 0xf7, 0xf7, 0x29, 0xfe, 0x51, 0x46, 0xf7, 0xf7, 0xc2, 0xfe, - 0x82, 0x46, 0x38, 0x46, 0x51, 0x46, 0xf7, 0xf7, 0x21, 0xfe, 0x4f, 0xf0, - 0x7e, 0x51, 0xf7, 0xf7, 0x1d, 0xfe, 0x83, 0x46, 0x38, 0x46, 0x51, 0x46, - 0xf7, 0xf7, 0xa4, 0xfd, 0x4f, 0xf0, 0x7e, 0x51, 0xf7, 0xf7, 0x14, 0xfe, - 0x01, 0x46, 0x58, 0x46, 0xf7, 0xf7, 0x1e, 0xfd, 0x29, 0x46, 0xf7, 0xf7, - 0xa9, 0xfe, 0x05, 0x46, 0x25, 0x60, 0x06, 0xeb, 0x08, 0x01, 0x20, 0x46, - 0x00, 0xf0, 0xca, 0xfe, 0x04, 0x00, 0x18, 0xbf, 0x01, 0x2c, 0x03, 0xd1, - 0xff, 0xf7, 0x06, 0xff, 0x22, 0x21, 0x01, 0x60, 0x20, 0x46, 0xbd, 0xe8, - 0xf0, 0x8d, 0x00, 0xbf, 0x00, 0x00, 0x80, 0xff, 0x00, 0x00, 0x65, 0xc3, - 0x01, 0x00, 0x65, 0x43, 0x3b, 0xaa, 0xb8, 0x3f, 0x00, 0x60, 0x31, 0x3f, - 0xbf, 0xbf, 0x90, 0x39, 0x01, 0x00, 0x00, 0x33, 0x9e, 0xbf, 0xcc, 0x3d, - 0x13, 0x54, 0x08, 0x3c, 0x70, 0x47, 0x00, 0x00, 0xd2, 0xb2, 0x20, 0x3a, - 0x22, 0xbf, 0x41, 0xfa, 0x02, 0xf0, 0xc9, 0x17, 0x70, 0x47, 0x20, 0x32, - 0xd1, 0x41, 0xd0, 0x40, 0x48, 0x40, 0x91, 0x40, 0xd1, 0x40, 0x48, 0x40, - 0x91, 0x40, 0x11, 0x41, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47, 0x00, 0xf0, - 0xad, 0xb9, 0x70, 0x47, 0x80, 0xb5, 0xf5, 0xf7, 0x0c, 0xfa, 0xbd, 0xe8, - 0x01, 0x40, 0x00, 0xf0, 0xa5, 0xb9, 0x70, 0x47, 0x00, 0xf0, 0xa1, 0xb8, - 0x00, 0xb5, 0x00, 0xbf, 0x13, 0x00, 0x96, 0x46, 0x94, 0x46, 0x10, 0x39, - 0x28, 0xbf, 0xa0, 0xe8, 0x0c, 0x50, 0xfa, 0xd8, 0x5f, 0xea, 0x41, 0x7c, - 0x28, 0xbf, 0x0c, 0xc0, 0x48, 0xbf, 0x40, 0xf8, 0x04, 0x2b, 0xc9, 0x07, - 0x28, 0xbf, 0x20, 0xf8, 0x02, 0x2b, 0x48, 0xbf, 0x00, 0xf8, 0x01, 0x2b, - 0x00, 0xbd, 0x00, 0x00, 0x80, 0xb5, 0x4f, 0xf0, 0x92, 0x41, 0x00, 0x20, - 0x08, 0x60, 0x06, 0x21, 0x0f, 0x20, 0xf8, 0xf7, 0xfa, 0xfe, 0xbd, 0xe8, - 0x02, 0x40, 0x02, 0xe0, 0x0c, 0x49, 0x08, 0x60, 0x70, 0x47, 0x0f, 0x20, - 0xf8, 0xf7, 0xdc, 0xbe, 0x1c, 0xb5, 0x4f, 0xf0, 0x92, 0x44, 0x08, 0x49, - 0x20, 0x68, 0x00, 0x90, 0x60, 0x68, 0x09, 0x68, 0x01, 0x90, 0x00, 0x98, - 0x00, 0xf0, 0x3f, 0x00, 0x00, 0x90, 0x68, 0x46, 0x88, 0x47, 0x00, 0x20, - 0x20, 0x60, 0x13, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x6c, 0xf3, 0x00, 0x20, - 0x10, 0xb5, 0x93, 0x48, 0x93, 0x4c, 0x4f, 0xf4, 0xf0, 0x01, 0x01, 0x62, - 0xc2, 0x6a, 0x42, 0xf4, 0xf0, 0x02, 0xc2, 0x62, 0x02, 0x6b, 0x42, 0xf4, - 0xf0, 0x02, 0x02, 0x63, 0x01, 0x60, 0x11, 0x20, 0xf8, 0xf7, 0xc3, 0xfe, - 0x06, 0x21, 0x11, 0x20, 0xf8, 0xf7, 0xc5, 0xfe, 0x11, 0x20, 0xf8, 0xf7, - 0xad, 0xfe, 0x4f, 0xf4, 0x40, 0x30, 0xe0, 0x62, 0xa1, 0x6b, 0x41, 0xf4, - 0x40, 0x31, 0xa1, 0x63, 0xe1, 0x6b, 0x41, 0xf4, 0x40, 0x31, 0xe1, 0x63, - 0x20, 0x60, 0x21, 0x20, 0xf8, 0xf7, 0xad, 0xfe, 0x06, 0x21, 0x21, 0x20, - 0xf8, 0xf7, 0xaf, 0xfe, 0x21, 0x20, 0xf8, 0xf7, 0x97, 0xfe, 0x00, 0x20, - 0x60, 0x60, 0x22, 0x20, 0xf8, 0xf7, 0xa1, 0xfe, 0x06, 0x21, 0x22, 0x20, - 0xf8, 0xf7, 0xa3, 0xfe, 0x22, 0x20, 0xf8, 0xf7, 0x8b, 0xfe, 0x00, 0x20, - 0xa0, 0x60, 0x23, 0x20, 0xf8, 0xf7, 0x95, 0xfe, 0x06, 0x21, 0x23, 0x20, - 0xf8, 0xf7, 0x97, 0xfe, 0xbd, 0xe8, 0x10, 0x40, 0x23, 0x20, 0xf8, 0xf7, - 0x7d, 0xbe, 0x80, 0xb5, 0x11, 0x20, 0xf8, 0xf7, 0x82, 0xfe, 0x21, 0x20, - 0xf8, 0xf7, 0x7f, 0xfe, 0x22, 0x20, 0xf8, 0xf7, 0x7c, 0xfe, 0xbd, 0xe8, - 0x02, 0x40, 0x23, 0x20, 0xf8, 0xf7, 0x77, 0xbe, 0x69, 0x49, 0x51, 0xf8, - 0x20, 0x00, 0x00, 0xb1, 0x01, 0x20, 0xc0, 0xb2, 0x70, 0x47, 0x80, 0xb5, - 0x22, 0x20, 0xf8, 0xf7, 0x72, 0xfe, 0xbd, 0xe8, 0x02, 0x40, 0x23, 0x20, - 0xf8, 0xf7, 0x6d, 0xbe, 0xf8, 0xb5, 0x00, 0x24, 0x0f, 0xf2, 0x88, 0x15, - 0x5d, 0x4e, 0x5f, 0x4f, 0x57, 0xf8, 0x24, 0x00, 0x38, 0xb1, 0x30, 0x68, - 0x55, 0xf8, 0x24, 0x10, 0x08, 0x43, 0x30, 0x60, 0x11, 0x20, 0xf8, 0xf7, - 0x5c, 0xfe, 0x07, 0xeb, 0x84, 0x01, 0x64, 0x1c, 0x00, 0x20, 0x02, 0x2c, - 0xc8, 0x60, 0xed, 0xd3, 0xf1, 0xbd, 0x10, 0xb5, 0x54, 0x4c, 0xa0, 0x68, - 0x30, 0xb1, 0x52, 0x49, 0x4f, 0xf4, 0x40, 0x30, 0x08, 0x60, 0x21, 0x20, - 0xf8, 0xf7, 0x49, 0xfe, 0x00, 0x20, 0x60, 0x61, 0x10, 0xbd, 0x2d, 0xe9, - 0xf8, 0x4f, 0x01, 0x21, 0x36, 0x20, 0xf8, 0xf7, 0xba, 0xfe, 0x00, 0x24, - 0x48, 0x4d, 0xdf, 0xf8, 0x2c, 0x81, 0x0f, 0xf2, 0x44, 0x1b, 0x48, 0x4e, - 0x0f, 0xf2, 0x24, 0x19, 0x0f, 0xf2, 0x2c, 0x1a, 0x5a, 0xf8, 0x24, 0x00, - 0x59, 0xf8, 0x24, 0x70, 0x01, 0x68, 0x39, 0x40, 0x29, 0xd0, 0x01, 0x60, - 0xf0, 0x69, 0xa0, 0x42, 0x05, 0xd1, 0x01, 0x20, 0xb0, 0x61, 0x01, 0x21, - 0x3b, 0x20, 0xf8, 0xf7, 0x9e, 0xfe, 0x5b, 0xf8, 0x24, 0x00, 0x00, 0x68, - 0x06, 0xeb, 0x84, 0x01, 0x38, 0x40, 0xca, 0x68, 0x46, 0xf8, 0x24, 0x00, - 0x52, 0x1c, 0xca, 0x60, 0x30, 0xb1, 0xb8, 0xf8, 0x56, 0x00, 0x90, 0x42, - 0x02, 0xd2, 0x28, 0x68, 0xb8, 0x43, 0x28, 0x60, 0x20, 0x46, 0xff, 0xf7, - 0xbf, 0xfa, 0x56, 0xf8, 0x24, 0x10, 0x01, 0xb1, 0x01, 0x21, 0x04, 0xf1, - 0x38, 0x00, 0xc9, 0xb2, 0xc0, 0xb2, 0xf8, 0xf7, 0x7e, 0xfe, 0x64, 0x1c, - 0x02, 0x2c, 0xcb, 0xd3, 0xbd, 0xe8, 0xf4, 0x4f, 0x00, 0x21, 0x36, 0x20, - 0xf8, 0xf7, 0x75, 0xbe, 0x38, 0xb5, 0x01, 0x21, 0x37, 0x20, 0xf8, 0xf7, - 0x70, 0xfe, 0x25, 0x4c, 0x25, 0x4d, 0xe0, 0x6a, 0x00, 0xf4, 0x40, 0x30, - 0xe0, 0x62, 0xe9, 0x69, 0x02, 0x29, 0x06, 0xd1, 0x28, 0xb1, 0x01, 0x20, - 0xa8, 0x61, 0x01, 0x21, 0x3b, 0x20, 0xf8, 0xf7, 0x60, 0xfe, 0x20, 0x6b, - 0x69, 0x69, 0x00, 0xf4, 0x40, 0x30, 0x49, 0x1c, 0xa8, 0x60, 0x69, 0x61, - 0x50, 0xb1, 0x1b, 0x48, 0xb0, 0xf8, 0x56, 0x00, 0x88, 0x42, 0x3c, 0xbf, - 0x00, 0x20, 0x20, 0x60, 0xa9, 0x68, 0x11, 0xb1, 0x01, 0x21, 0x00, 0xe0, - 0x00, 0x21, 0xc9, 0xb2, 0x3a, 0x20, 0xf8, 0xf7, 0x48, 0xfe, 0xbd, 0xe8, - 0x34, 0x40, 0x00, 0x21, 0x37, 0x20, 0xf8, 0xf7, 0x42, 0xbe, 0x0f, 0x49, - 0x0f, 0xf2, 0x58, 0x02, 0x0f, 0xf2, 0x3c, 0x03, 0xc8, 0x61, 0x52, 0xf8, - 0x20, 0x20, 0x12, 0x68, 0x53, 0xf8, 0x20, 0x00, 0x10, 0x40, 0x88, 0x61, - 0x01, 0x00, 0x18, 0xbf, 0x01, 0x21, 0xc9, 0xb2, 0x3b, 0x20, 0xf8, 0xf7, - 0x2e, 0xbe, 0x05, 0x49, 0x89, 0x69, 0x00, 0x20, 0x01, 0xb1, 0x01, 0x20, - 0x70, 0x47, 0x00, 0x00, 0x20, 0x00, 0x00, 0x50, 0x14, 0x00, 0x00, 0x58, - 0xac, 0xf2, 0x00, 0x20, 0x4c, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x50, 0x00, - 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x50, - 0x40, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, 0x44, 0x00, 0x00, 0x50, - 0x44, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, 0x58, 0x80, 0xb5, 0x00, 0xf0, - 0x13, 0xf8, 0x19, 0x20, 0xf8, 0xf7, 0x78, 0xfd, 0x4f, 0xf0, 0xa4, 0x41, - 0x15, 0x48, 0x08, 0x60, 0x00, 0x21, 0x19, 0x20, 0xf8, 0xf7, 0x8b, 0xfd, - 0xbd, 0xe8, 0x01, 0x40, 0x12, 0x49, 0x01, 0x20, 0x08, 0x60, 0x19, 0x20, - 0xf8, 0xf7, 0x6e, 0xbd, 0x80, 0xb5, 0x19, 0x20, 0xf8, 0xf7, 0x73, 0xfd, - 0x0d, 0x49, 0x00, 0x20, 0x08, 0x60, 0x01, 0xbd, 0xef, 0xf3, 0x11, 0x80, - 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x09, 0x49, 0x0a, 0x68, 0x42, 0xf0, - 0x02, 0x03, 0x0b, 0x60, 0x22, 0xf0, 0x02, 0x02, 0x0a, 0x60, 0x80, 0xf3, - 0x11, 0x88, 0x70, 0x47, 0x03, 0x48, 0x00, 0x68, 0x00, 0xf0, 0x01, 0x00, - 0x70, 0x47, 0x00, 0x00, 0x00, 0x70, 0x17, 0x00, 0x04, 0x00, 0x00, 0x52, - 0x00, 0x20, 0xf8, 0xf7, 0xfe, 0xbc, 0x00, 0x00, 0x09, 0x42, 0x40, 0xf1, - 0x0d, 0x80, 0xf4, 0x46, 0x49, 0x42, 0x40, 0x42, 0x71, 0xf1, 0x00, 0x01, - 0x00, 0xf0, 0x06, 0xf8, 0x51, 0xf0, 0x00, 0x41, 0x60, 0x47, 0x00, 0x00, - 0x09, 0x42, 0x00, 0xbf, 0x08, 0xbf, 0x00, 0xf0, 0x15, 0xbd, 0x02, 0x46, - 0x08, 0x46, 0xb0, 0xfa, 0x80, 0xf1, 0x50, 0x40, 0x8a, 0x40, 0xc1, 0xf1, - 0x20, 0x01, 0xc8, 0x41, 0x50, 0x40, 0xc9, 0x1e, 0x01, 0xf5, 0x84, 0x61, - 0x09, 0x05, 0x01, 0xeb, 0xd0, 0x21, 0x40, 0x05, 0x40, 0xea, 0xd2, 0x20, - 0x52, 0x05, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xf1, - 0x00, 0x01, 0x70, 0x47, 0xf0, 0xb4, 0x4f, 0xf0, 0x00, 0x45, 0x91, 0xea, - 0x03, 0x0c, 0x44, 0xbf, 0x6b, 0x40, 0x00, 0xf0, 0xbf, 0xb9, 0x00, 0xbf, - 0x84, 0x1a, 0x71, 0xeb, 0x03, 0x06, 0x03, 0xd2, 0x00, 0x1b, 0xb1, 0x41, - 0x12, 0x19, 0x73, 0x41, 0x4f, 0xf4, 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, - 0x34, 0xbf, 0x7c, 0xeb, 0x43, 0x04, 0x43, 0xe0, 0x0c, 0x0d, 0xa4, 0xeb, - 0x13, 0x56, 0x35, 0x2e, 0x50, 0xdc, 0x45, 0xea, 0xc3, 0x23, 0xdb, 0x0a, - 0x45, 0xea, 0xc1, 0x21, 0xc9, 0x12, 0xb6, 0xf1, 0x20, 0x05, 0x0d, 0xdd, - 0x63, 0xfa, 0x05, 0xf6, 0xeb, 0x40, 0x86, 0xea, 0x03, 0x05, 0x12, 0x42, - 0x18, 0xbf, 0x45, 0xf0, 0x01, 0x05, 0xc0, 0x18, 0x51, 0xf1, 0x00, 0x01, - 0x0c, 0xd2, 0x13, 0xe0, 0x62, 0xfa, 0x06, 0xf5, 0xf2, 0x40, 0x55, 0x40, - 0xf3, 0x41, 0x5a, 0x40, 0xb3, 0x40, 0xf3, 0x40, 0x5a, 0x40, 0x80, 0x18, - 0x59, 0x41, 0x07, 0xd3, 0x49, 0x08, 0x5f, 0xea, 0x30, 0x00, 0x5f, 0xea, - 0x35, 0x05, 0x28, 0xbf, 0x45, 0xf0, 0x01, 0x05, 0x01, 0xf5, 0x80, 0x11, - 0x42, 0x08, 0x75, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xeb, - 0x04, 0x51, 0xf0, 0xbc, 0x4f, 0xf4, 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, - 0x38, 0xbf, 0x70, 0x47, 0x00, 0x20, 0x09, 0x0d, 0x09, 0x05, 0x70, 0x47, - 0x1c, 0xeb, 0x41, 0x0f, 0x10, 0xd2, 0x52, 0xea, 0x43, 0x06, 0x0b, 0xd0, - 0xbc, 0xeb, 0x41, 0x0f, 0x05, 0xd8, 0x0c, 0x0d, 0xab, 0x43, 0x66, 0x1e, - 0x34, 0x2e, 0xb5, 0xdd, 0x02, 0xe0, 0xab, 0x43, 0x80, 0x18, 0x59, 0x41, - 0xf0, 0xbc, 0x70, 0x47, 0xf0, 0xbc, 0x70, 0x47, 0xb0, 0xb5, 0x81, 0xea, - 0x03, 0x0c, 0x0c, 0xf0, 0x00, 0x4c, 0x40, 0xf2, 0xff, 0x75, 0x15, 0xea, - 0x11, 0x54, 0x1d, 0xbf, 0x15, 0xea, 0x13, 0x57, 0xac, 0x42, 0xaf, 0x42, - 0x39, 0xe0, 0xe4, 0x19, 0x23, 0xea, 0x45, 0x53, 0x43, 0xf4, 0x80, 0x13, - 0xc9, 0x02, 0x41, 0xf0, 0x00, 0x41, 0x41, 0xea, 0x50, 0x5e, 0xc7, 0x02, - 0x11, 0x00, 0xa7, 0xfb, 0x02, 0x02, 0x00, 0x28, 0x4f, 0xf0, 0x00, 0x00, - 0xee, 0xfb, 0x01, 0x20, 0x4f, 0xf0, 0x00, 0x01, 0xe3, 0xfb, 0x07, 0x21, - 0x18, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0x40, 0x18, 0x00, 0x21, 0x49, 0x41, - 0xe3, 0xfb, 0x0e, 0x01, 0xa4, 0xf5, 0x80, 0x64, 0x0f, 0x03, 0x02, 0xd2, - 0x52, 0x00, 0x40, 0x41, 0x49, 0x41, 0x54, 0xf1, 0x01, 0x04, 0x6c, 0xdd, - 0x47, 0x08, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, 0x51, 0xeb, - 0x04, 0x51, 0xa1, 0xf5, 0x80, 0x11, 0x5c, 0xbf, 0x41, 0xea, 0x0c, 0x01, - 0xb0, 0xbd, 0x4c, 0xea, 0x05, 0x51, 0x00, 0x20, 0xb0, 0xbd, 0x05, 0xea, - 0x13, 0x57, 0xac, 0x42, 0x14, 0xbf, 0xaf, 0x42, 0x41, 0xe0, 0x50, 0xea, - 0x41, 0x0e, 0x1c, 0xbf, 0x52, 0xea, 0x43, 0x0e, 0x02, 0xe0, 0x61, 0x46, - 0x00, 0x20, 0xb0, 0xbd, 0x24, 0x42, 0x3c, 0x44, 0x1b, 0xd1, 0x5f, 0xea, - 0x07, 0x0e, 0xf6, 0xd0, 0x09, 0x03, 0x02, 0xbf, 0x01, 0x46, 0x00, 0x20, - 0xae, 0xf1, 0x14, 0x0e, 0xb1, 0xfa, 0x81, 0xf7, 0xae, 0xeb, 0x07, 0x04, - 0x01, 0xfa, 0x07, 0xfe, 0x0c, 0x37, 0xc7, 0xf1, 0x20, 0x01, 0x00, 0xfa, - 0x07, 0xf7, 0xc8, 0x40, 0x4e, 0xea, 0x00, 0x0e, 0x23, 0xea, 0x45, 0x53, - 0x43, 0xf4, 0x80, 0x13, 0xa2, 0xe7, 0x33, 0xf0, 0x00, 0x43, 0xb3, 0xfa, - 0x83, 0xf7, 0x04, 0xbf, 0xb2, 0xfa, 0x82, 0xfe, 0x77, 0x44, 0x0b, 0x3f, - 0xe4, 0x1b, 0xb7, 0xf1, 0x20, 0x0e, 0x2f, 0xbf, 0x02, 0xfa, 0x0e, 0xf3, - 0xbb, 0x40, 0xc7, 0xf1, 0x20, 0x0e, 0x22, 0xfa, 0x0e, 0xfe, 0x38, 0xbf, - 0x43, 0xea, 0x0e, 0x03, 0xba, 0x40, 0x64, 0x1c, 0x82, 0xe7, 0x50, 0xea, - 0x41, 0x0e, 0x14, 0xbf, 0x52, 0xea, 0x43, 0x0e, 0x6f, 0xf0, 0x00, 0x01, - 0x4f, 0xf4, 0x00, 0x17, 0x17, 0xeb, 0x43, 0x0f, 0x8a, 0xbf, 0x19, 0x46, - 0x17, 0xeb, 0x41, 0x0f, 0xb5, 0xe7, 0x4c, 0xea, 0x05, 0x51, 0x00, 0x20, - 0xb0, 0xbd, 0xd4, 0xf1, 0x01, 0x04, 0xb4, 0xf1, 0x20, 0x07, 0x0f, 0xda, - 0xc4, 0xf1, 0x20, 0x07, 0x52, 0x08, 0x28, 0xbf, 0x42, 0xf0, 0x01, 0x02, - 0x10, 0xfa, 0x07, 0xf5, 0x01, 0xfa, 0x07, 0xf7, 0xe1, 0xbf, 0x2a, 0x43, - 0xe0, 0x40, 0x38, 0x43, 0xe1, 0x40, 0x0f, 0xe0, 0x35, 0x2c, 0x98, 0xdc, - 0xc7, 0xf1, 0x20, 0x04, 0x52, 0xea, 0x40, 0x02, 0x20, 0xfa, 0x07, 0xf2, - 0x18, 0xbf, 0x42, 0xf0, 0x01, 0x02, 0x31, 0xfa, 0x07, 0xf0, 0xa1, 0x40, - 0x0a, 0x43, 0x00, 0x21, 0x72, 0xf1, 0x00, 0x42, 0x50, 0xf1, 0x00, 0x00, - 0x51, 0xeb, 0x0c, 0x01, 0xb0, 0xbd, 0x00, 0x00, 0x40, 0xf2, 0xff, 0x7c, - 0x0b, 0x0d, 0x4d, 0xd0, 0x63, 0x45, 0x66, 0xd2, 0x30, 0xb4, 0x21, 0xea, - 0x03, 0x51, 0x41, 0xf4, 0x80, 0x11, 0x03, 0xf2, 0xfd, 0x3c, 0x5f, 0xea, - 0x5c, 0x0c, 0x01, 0xd3, 0x00, 0x18, 0x49, 0x41, 0x89, 0x00, 0x41, 0xea, - 0x90, 0x71, 0x80, 0x00, 0x4f, 0xf4, 0x40, 0x14, 0x00, 0x23, 0xe2, 0x02, - 0xd5, 0x0a, 0xb1, 0xf5, 0x10, 0x01, 0x07, 0xd4, 0x6d, 0x08, 0x1d, 0xd2, - 0x09, 0x1b, 0x64, 0x19, 0x00, 0x18, 0x49, 0x41, 0x49, 0x1b, 0xf7, 0xd5, - 0x6d, 0x08, 0x0a, 0xd2, 0x09, 0x19, 0x64, 0x1b, 0x00, 0x18, 0x49, 0x41, - 0x49, 0x1b, 0xef, 0xd5, 0x6d, 0x08, 0xf7, 0xd3, 0x01, 0xe0, 0x52, 0x08, - 0x17, 0xd0, 0xc0, 0x18, 0x61, 0x41, 0x9b, 0x1a, 0xac, 0x41, 0x00, 0x18, - 0x49, 0x41, 0x80, 0x1a, 0xa9, 0x41, 0xf4, 0xd4, 0x52, 0x08, 0x0a, 0xd0, - 0xc0, 0x1a, 0xa1, 0x41, 0x9b, 0x18, 0x6c, 0x41, 0x00, 0x18, 0x49, 0x41, - 0x80, 0x1a, 0xa9, 0x41, 0xe9, 0xd4, 0x52, 0x08, 0xf4, 0xd1, 0x5b, 0x1c, - 0x6c, 0x41, 0x61, 0x08, 0x4f, 0xea, 0x33, 0x00, 0x01, 0xeb, 0x0c, 0x51, - 0x30, 0xbc, 0x70, 0x47, 0x50, 0xea, 0x01, 0x03, 0xfb, 0xd0, 0x30, 0xb4, - 0xb1, 0xfa, 0x81, 0xf3, 0x11, 0xb9, 0xb0, 0xfa, 0x80, 0xf4, 0x1b, 0x19, - 0x0b, 0x3b, 0xb3, 0xf1, 0x20, 0x04, 0x2f, 0xbf, 0x00, 0xfa, 0x04, 0xf1, - 0x99, 0x40, 0xc3, 0xf1, 0x20, 0x04, 0x20, 0xfa, 0x04, 0xf4, 0x38, 0xbf, - 0x21, 0x43, 0x98, 0x40, 0xd3, 0xf1, 0x01, 0x03, 0x9d, 0xe7, 0x63, 0x45, - 0xe1, 0xd0, 0x11, 0xf5, 0x80, 0x1f, 0xde, 0xd8, 0x50, 0xea, 0x41, 0x01, - 0xdb, 0xd0, 0xd9, 0x43, 0xff, 0xf7, 0x66, 0xba, 0xf0, 0xb4, 0x4f, 0xf0, - 0x00, 0x45, 0x91, 0xea, 0x03, 0x0f, 0x44, 0xbf, 0x6b, 0x40, 0xff, 0xf7, - 0x43, 0xbe, 0x00, 0xbf, 0x84, 0x1a, 0x71, 0xeb, 0x03, 0x06, 0x04, 0xd2, - 0x6e, 0x40, 0x00, 0x1b, 0xb1, 0x41, 0x12, 0x19, 0x73, 0x41, 0x4f, 0xf4, - 0x00, 0x1c, 0x1c, 0xeb, 0x41, 0x0f, 0x34, 0xbf, 0x7c, 0xeb, 0x43, 0x06, - 0x84, 0xe0, 0x0c, 0x0d, 0xa4, 0xeb, 0x13, 0x56, 0x36, 0x2e, 0x7d, 0xdc, - 0x01, 0x2e, 0x43, 0xdc, 0x45, 0xea, 0xc3, 0x23, 0x43, 0xea, 0x52, 0x53, - 0x12, 0xbf, 0xd2, 0x02, 0x92, 0x02, 0x5b, 0x08, 0x24, 0x05, 0x45, 0xea, - 0xc1, 0x21, 0x41, 0xea, 0x50, 0x51, 0xd2, 0xeb, 0xc0, 0x20, 0x99, 0x41, - 0x25, 0xd4, 0x07, 0xd1, 0xb0, 0xfa, 0x80, 0xf6, 0x10, 0xfa, 0x06, 0xf1, - 0x64, 0xd0, 0x00, 0x20, 0x20, 0x36, 0x08, 0xe0, 0xb1, 0xfa, 0x81, 0xf6, - 0xb1, 0x40, 0xc6, 0xf1, 0x20, 0x02, 0x20, 0xfa, 0x02, 0xf2, 0x11, 0x43, - 0xb0, 0x40, 0x4f, 0xea, 0xf4, 0x74, 0xb4, 0xeb, 0x46, 0x54, 0x34, 0xf0, - 0x01, 0x06, 0x4f, 0xea, 0x74, 0x04, 0x0a, 0xd8, 0xd6, 0xf5, 0x00, 0x16, - 0x76, 0x0d, 0x04, 0xf0, 0x00, 0x44, 0xf0, 0x40, 0x61, 0xfa, 0x06, 0xf2, - 0x50, 0x40, 0xf1, 0x40, 0x48, 0x40, 0xc0, 0x0a, 0x40, 0xea, 0x41, 0x50, - 0x21, 0xf0, 0x00, 0x41, 0x28, 0xbf, 0x5f, 0xea, 0x50, 0x05, 0x50, 0xf1, - 0x00, 0x00, 0x44, 0xeb, 0xd1, 0x21, 0x37, 0xe0, 0x45, 0xea, 0xc3, 0x23, - 0xdb, 0x0a, 0x45, 0xea, 0xc1, 0x21, 0xc9, 0x0a, 0xb6, 0xf1, 0x20, 0x05, - 0x0e, 0xdd, 0x42, 0xea, 0x02, 0x42, 0x12, 0x0c, 0xc5, 0xf1, 0x20, 0x06, - 0x03, 0xfa, 0x06, 0xf6, 0xeb, 0x40, 0x42, 0xea, 0x06, 0x05, 0x6d, 0x42, - 0x98, 0x41, 0x61, 0xf1, 0x00, 0x01, 0x0d, 0xe0, 0x62, 0xfa, 0x06, 0xf5, - 0xf2, 0x40, 0x55, 0x40, 0x63, 0xfa, 0x06, 0xfc, 0x82, 0xea, 0x0c, 0x02, - 0xf3, 0x40, 0x5a, 0x40, 0x6d, 0x42, 0x90, 0x41, 0x61, 0xeb, 0x03, 0x01, - 0x11, 0xf4, 0x80, 0x1f, 0x05, 0xd1, 0x64, 0x1e, 0x62, 0x05, 0x02, 0xd0, - 0x6d, 0x00, 0x40, 0x41, 0x49, 0x41, 0x21, 0xf4, 0x80, 0x11, 0x43, 0x08, - 0x75, 0xf1, 0x00, 0x43, 0x50, 0xf1, 0x00, 0x00, 0x41, 0xeb, 0x04, 0x51, - 0xf0, 0xbc, 0x70, 0x47, 0x1c, 0xeb, 0x41, 0x0f, 0x15, 0xd2, 0x23, 0xf0, - 0x00, 0x43, 0x52, 0xea, 0x43, 0x06, 0x0b, 0xd0, 0x4f, 0xea, 0x4c, 0x0c, - 0xbc, 0xeb, 0x41, 0x0f, 0x04, 0xd8, 0x0c, 0x0d, 0x66, 0x1e, 0x34, 0x2e, - 0xb7, 0xdd, 0xeb, 0xe7, 0x80, 0x1a, 0x99, 0x41, 0x50, 0xea, 0x41, 0x06, - 0x08, 0xbf, 0x00, 0x21, 0xe4, 0xe7, 0x08, 0xbf, 0x1c, 0xeb, 0x43, 0x0f, - 0x28, 0xbf, 0x6f, 0xf0, 0x00, 0x01, 0xdd, 0xe7, 0x4f, 0xea, 0xf1, 0x7c, - 0xbc, 0xf1, 0xe0, 0x4c, 0x2c, 0xbf, 0xbc, 0xf5, 0x00, 0x1f, 0x11, 0xe0, - 0x5f, 0xea, 0x4c, 0x0c, 0x34, 0xbf, 0xbc, 0xf1, 0x7f, 0x5f, 0x2e, 0xe0, - 0x5f, 0xea, 0x9c, 0x0c, 0x4f, 0xea, 0x0c, 0x1c, 0x4f, 0xea, 0x3c, 0x0c, - 0xc1, 0x00, 0x71, 0xf1, 0x00, 0x41, 0x4c, 0xeb, 0x50, 0x70, 0x70, 0x47, - 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, 0xc0, 0x02, 0x18, 0xbf, 0x41, 0xf0, - 0x01, 0x01, 0x41, 0xf0, 0x00, 0x41, 0x4f, 0xea, 0x6c, 0x50, 0xc0, 0xf1, - 0x09, 0x00, 0x21, 0x28, 0x10, 0xd2, 0x40, 0xea, 0xcc, 0x7c, 0xcc, 0xf1, - 0x20, 0x0c, 0x11, 0xfa, 0x0c, 0xf0, 0x70, 0xf1, 0x00, 0x40, 0xcc, 0xf1, - 0x20, 0x0c, 0x21, 0xfa, 0x0c, 0xf0, 0x0c, 0xf0, 0x00, 0x4c, 0x40, 0xeb, - 0x0c, 0x00, 0x70, 0x47, 0x4f, 0xea, 0xcc, 0x70, 0x70, 0x47, 0x49, 0x00, - 0x11, 0xf5, 0x00, 0x1f, 0x04, 0xd8, 0x4f, 0xea, 0xcc, 0x10, 0xff, 0x30, - 0xc0, 0x05, 0x70, 0x47, 0xc8, 0x17, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x41, - 0x40, 0xf2, 0xff, 0x75, 0x81, 0xea, 0x03, 0x0c, 0x0c, 0xf0, 0x00, 0x4c, - 0x15, 0xea, 0x11, 0x54, 0x1d, 0xbf, 0x15, 0xea, 0x13, 0x57, 0xac, 0x42, - 0xaf, 0x42, 0xe9, 0xe0, 0xbc, 0x41, 0xc1, 0xf3, 0x13, 0x01, 0xc3, 0xf3, - 0x13, 0x03, 0x80, 0x1a, 0x99, 0x41, 0x43, 0xf4, 0x80, 0x13, 0x04, 0xd2, - 0x64, 0x1e, 0x40, 0x00, 0x49, 0x41, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, - 0x41, 0xea, 0x50, 0x51, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, - 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x02, 0xd2, - 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, - 0xb1, 0xfb, 0xf3, 0xfe, 0x03, 0xfb, 0x1e, 0x11, 0xa2, 0xfb, 0x0e, 0x75, - 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x03, 0xd2, 0xae, 0xf1, 0x01, 0x0e, - 0x80, 0x18, 0x59, 0x41, 0x89, 0x02, 0x41, 0xea, 0x90, 0x51, 0x76, 0x05, - 0x46, 0xea, 0x8e, 0x2e, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, - 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0x80, 0x20, 0xa9, 0x41, 0x02, 0xd2, - 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, - 0x4e, 0xea, 0x06, 0x0e, 0xb1, 0xfb, 0xf3, 0xf6, 0x03, 0xfb, 0x16, 0x11, - 0xa2, 0xfb, 0x06, 0x75, 0xd7, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x02, 0xd2, - 0x76, 0x1e, 0x80, 0x18, 0x59, 0x41, 0xc9, 0x02, 0x41, 0xea, 0x50, 0x51, - 0xb1, 0xfb, 0xf3, 0xf7, 0x03, 0xfb, 0x17, 0x11, 0xa2, 0xfb, 0x07, 0x35, - 0xd3, 0xeb, 0xc0, 0x20, 0xa9, 0x41, 0x67, 0xf1, 0x00, 0x07, 0x0c, 0xbf, - 0x00, 0x42, 0x47, 0xf0, 0x01, 0x07, 0x66, 0xf3, 0xd5, 0x27, 0x4f, 0xea, - 0x1e, 0x31, 0xb8, 0x08, 0x14, 0xf5, 0x80, 0x64, 0x14, 0xdd, 0xbd, 0x07, - 0x75, 0xf1, 0x00, 0x42, 0x50, 0xeb, 0x0e, 0x50, 0x51, 0xeb, 0x04, 0x51, - 0x11, 0xf5, 0x80, 0x1f, 0x5c, 0xbf, 0x41, 0xea, 0x0c, 0x01, 0xbd, 0xe8, - 0xf0, 0x81, 0x4c, 0xf0, 0x7f, 0x61, 0x41, 0xf0, 0xe0, 0x41, 0x00, 0x20, - 0xbd, 0xe8, 0xf0, 0x81, 0xbd, 0x07, 0x6d, 0x08, 0x40, 0xea, 0x0e, 0x50, - 0x41, 0xf4, 0x80, 0x11, 0xd4, 0xf1, 0x01, 0x04, 0xb4, 0xf1, 0x20, 0x06, - 0x0a, 0xda, 0xc4, 0xf1, 0x20, 0x06, 0x02, 0x00, 0xe0, 0x40, 0x01, 0xfa, - 0x06, 0xf3, 0xe1, 0x40, 0x18, 0x43, 0xb2, 0x40, 0x15, 0x43, 0x0e, 0xe0, - 0x34, 0x2c, 0x14, 0xdc, 0xc6, 0xf1, 0x20, 0x04, 0x45, 0xea, 0x40, 0x05, - 0x6d, 0x08, 0x20, 0xfa, 0x06, 0xf2, 0x15, 0x43, 0x21, 0xfa, 0x06, 0xf0, - 0xa1, 0x40, 0x0d, 0x43, 0x00, 0x21, 0x75, 0xf1, 0x00, 0x42, 0x50, 0xf1, - 0x00, 0x00, 0x51, 0xeb, 0x0c, 0x01, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x20, - 0x5f, 0xea, 0x0c, 0x01, 0xbd, 0xe8, 0xf0, 0x81, 0xcf, 0xb9, 0x92, 0x18, - 0x5b, 0x41, 0xb3, 0xfa, 0x83, 0xf7, 0x04, 0xbf, 0xb2, 0xfa, 0x82, 0xf6, - 0xbf, 0x19, 0x0b, 0x3f, 0xb7, 0xf1, 0x20, 0x06, 0x2f, 0xbf, 0x02, 0xfa, - 0x06, 0xf3, 0xbb, 0x40, 0xc7, 0xf1, 0x20, 0x06, 0x22, 0xfa, 0x06, 0xf6, - 0x38, 0xbf, 0x33, 0x43, 0xba, 0x40, 0x1c, 0xb1, 0xe4, 0x19, 0x64, 0x1e, - 0x2f, 0xe7, 0x7f, 0x42, 0x31, 0xf0, 0x00, 0x41, 0xb1, 0xfa, 0x81, 0xf4, - 0x04, 0xbf, 0xb0, 0xfa, 0x80, 0xf6, 0xa4, 0x19, 0x0b, 0x3c, 0xb4, 0xf1, - 0x20, 0x06, 0x2f, 0xbf, 0x00, 0xfa, 0x06, 0xf1, 0xa1, 0x40, 0xc4, 0xf1, - 0x20, 0x06, 0x20, 0xfa, 0x06, 0xf6, 0x38, 0xbf, 0x31, 0x43, 0xa0, 0x40, - 0x3c, 0x1b, 0x16, 0xe7, 0xac, 0x42, 0x1a, 0xbf, 0x05, 0xea, 0x13, 0x57, - 0xaf, 0x42, 0x14, 0xe0, 0x50, 0xea, 0x41, 0x06, 0x1c, 0xbf, 0x52, 0xea, - 0x43, 0x06, 0xbf, 0xe7, 0x50, 0xea, 0x41, 0x07, 0x30, 0x46, 0x61, 0x46, - 0x1c, 0xbf, 0x41, 0xea, 0x05, 0x51, 0xbd, 0xe8, 0xf0, 0x81, 0x52, 0xea, - 0x43, 0x0c, 0x08, 0xbf, 0xc1, 0x43, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x20, - 0x4f, 0xf4, 0x00, 0x16, 0x16, 0xeb, 0x41, 0x0f, 0x98, 0xbf, 0x16, 0xeb, - 0x43, 0x0f, 0x08, 0xbf, 0x16, 0xeb, 0x41, 0x0f, 0x24, 0xbf, 0xc1, 0x43, - 0x05, 0xe0, 0x16, 0xeb, 0x43, 0x0f, 0x0c, 0xbf, 0x61, 0x46, 0x4c, 0xea, - 0x05, 0x51, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, 0x41, 0x00, 0x1d, 0xd2, - 0x09, 0x0e, 0x7f, 0x39, 0x1a, 0xd4, 0x20, 0x29, 0x08, 0xda, 0xc1, 0xf1, - 0x1f, 0x0c, 0x01, 0x02, 0x41, 0xf0, 0x00, 0x41, 0x21, 0xfa, 0x0c, 0xf0, - 0x00, 0x21, 0x70, 0x47, 0xd1, 0xf1, 0x3f, 0x0c, 0x08, 0xd4, 0x01, 0x02, - 0x41, 0xf0, 0x00, 0x41, 0x61, 0xfa, 0x0c, 0xf0, 0x21, 0xfa, 0x0c, 0xf1, - 0x48, 0x40, 0x70, 0x47, 0x6f, 0xf0, 0x00, 0x00, 0x01, 0x00, 0x70, 0x47, - 0x00, 0x20, 0x00, 0x21, 0x70, 0x47, 0x00, 0x00, 0x80, 0xb5, 0x01, 0x20, - 0xf8, 0xf7, 0xb5, 0xf8, 0x01, 0x20, 0xf8, 0xf7, 0xb2, 0xf8, 0x4f, 0xf0, - 0xa0, 0x40, 0x03, 0x21, 0x01, 0x64, 0x01, 0x60, 0x09, 0x20, 0x06, 0x21, - 0xf8, 0xf7, 0x09, 0xf9, 0x09, 0x20, 0xf8, 0xf7, 0x00, 0xf9, 0x09, 0x20, - 0xf8, 0xf7, 0xee, 0xf8, 0x4f, 0xf0, 0xb0, 0x40, 0x4f, 0xf0, 0x00, 0x71, - 0x01, 0x64, 0x01, 0x60, 0x1c, 0x20, 0x06, 0x21, 0xf8, 0xf7, 0xf9, 0xf8, - 0x1c, 0x20, 0xf8, 0xf7, 0xf0, 0xf8, 0xff, 0xe7, 0xbd, 0xe8, 0x02, 0x40, - 0x1c, 0x20, 0xf8, 0xf7, 0xdb, 0xb8, 0x05, 0x28, 0xba, 0xbf, 0x27, 0x49, - 0x40, 0x5c, 0x00, 0x20, 0x70, 0x47, 0x38, 0xb5, 0x25, 0x49, 0x24, 0x4d, - 0x03, 0x20, 0x08, 0x60, 0x00, 0x20, 0xf3, 0xf7, 0xdf, 0xf9, 0x29, 0x78, - 0x04, 0x46, 0x8c, 0x42, 0x0a, 0xd0, 0x22, 0x46, 0x00, 0x20, 0xfe, 0xf7, - 0x8c, 0xfd, 0x00, 0x20, 0x00, 0xf0, 0x77, 0xf9, 0x18, 0x20, 0xf8, 0xf7, - 0x38, 0xf9, 0x2c, 0x70, 0x01, 0x20, 0xf3, 0xf7, 0xcd, 0xf9, 0x69, 0x78, - 0x04, 0x46, 0x8c, 0x42, 0x0a, 0xd0, 0x22, 0x46, 0x01, 0x20, 0xfe, 0xf7, - 0x7a, 0xfd, 0x01, 0x20, 0x00, 0xf0, 0x65, 0xf9, 0x19, 0x20, 0xf8, 0xf7, - 0x26, 0xf9, 0x6c, 0x70, 0x31, 0xbd, 0xf8, 0xb5, 0x11, 0x49, 0x0f, 0x4d, - 0x0f, 0xf2, 0x44, 0x06, 0x4f, 0xf0, 0x00, 0x70, 0x08, 0x60, 0x02, 0x24, - 0x36, 0xf8, 0x14, 0x00, 0x00, 0xf1, 0x8c, 0x40, 0x07, 0x78, 0x61, 0x5d, - 0x8f, 0x42, 0x0a, 0xd0, 0x3a, 0x46, 0xe0, 0xb2, 0xfe, 0xf7, 0xc3, 0xfd, - 0xe0, 0xb2, 0x00, 0xf0, 0x48, 0xf9, 0x1a, 0x20, 0xf8, 0xf7, 0x09, 0xf9, - 0x67, 0x55, 0x64, 0x1c, 0x05, 0x2c, 0xe9, 0xd3, 0xf1, 0xbd, 0x00, 0x00, - 0x50, 0xf3, 0x00, 0x20, 0x40, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, - 0xb0, 0x04, 0xb3, 0x04, 0x5b, 0x04, 0x5c, 0x04, 0x5d, 0x04, 0x00, 0x00, - 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x20, 0x68, 0x40, 0x00, 0x00, 0x0e, - 0xff, 0x28, 0x04, 0xd1, 0x20, 0x68, 0x40, 0x02, 0x14, 0xd0, 0x02, 0x20, - 0x32, 0xbd, 0x20, 0xb9, 0x20, 0x46, 0xfe, 0xf7, 0xf7, 0xff, 0x01, 0x28, - 0x46, 0xda, 0x01, 0x2d, 0x0c, 0xdb, 0xc0, 0xf1, 0xff, 0x01, 0x8d, 0x42, - 0x08, 0xd3, 0x20, 0x68, 0x00, 0x28, 0x4c, 0xbf, 0x1f, 0x48, 0x4f, 0xf0, - 0xff, 0x40, 0x20, 0x60, 0x01, 0x20, 0x32, 0xbd, 0x41, 0x42, 0xa9, 0x42, - 0x21, 0x68, 0x06, 0xda, 0x21, 0xf0, 0xff, 0x41, 0x40, 0x19, 0x41, 0xea, - 0xc0, 0x50, 0x20, 0x60, 0x26, 0xe0, 0x22, 0x68, 0x52, 0x02, 0x40, 0x1e, - 0x52, 0x0a, 0x45, 0x19, 0x42, 0xf4, 0x00, 0x02, 0x05, 0xf1, 0x18, 0x00, - 0x01, 0xf0, 0x00, 0x41, 0x22, 0x60, 0x18, 0x28, 0x28, 0xbf, 0x21, 0x60, - 0x1c, 0xd2, 0x00, 0x20, 0x6a, 0x42, 0x06, 0xd0, 0x20, 0x68, 0xc2, 0xf1, - 0x20, 0x03, 0x98, 0x40, 0x23, 0x68, 0xd3, 0x40, 0x23, 0x60, 0x22, 0x68, - 0x0a, 0x43, 0xb0, 0xf1, 0x00, 0x4f, 0x22, 0x60, 0x03, 0xd8, 0x08, 0xd1, - 0x20, 0x78, 0xc0, 0x07, 0x05, 0xd5, 0x20, 0x68, 0x40, 0x1c, 0x20, 0x60, - 0x4f, 0xf0, 0xff, 0x30, 0x32, 0xbd, 0x20, 0x68, 0x88, 0x42, 0xf9, 0xd1, - 0x00, 0x20, 0x32, 0xbd, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0xbf, - 0x09, 0xd0, 0xb0, 0xfa, 0x80, 0xf1, 0x88, 0x40, 0xc9, 0x1c, 0xc1, 0xf5, - 0x84, 0x61, 0x09, 0x05, 0x01, 0xeb, 0xd0, 0x21, 0x40, 0x05, 0x70, 0x47, - 0x70, 0xb5, 0x00, 0x24, 0x67, 0x4d, 0x0f, 0xf2, 0xbc, 0x16, 0x56, 0xf8, - 0x24, 0x10, 0x4f, 0xf4, 0x7c, 0x70, 0x00, 0xfb, 0x04, 0x50, 0x00, 0xf0, - 0xf2, 0xf8, 0x64, 0x1c, 0x04, 0x2c, 0xf4, 0xd3, 0x61, 0x4e, 0x62, 0x4d, - 0xf4, 0xf7, 0x0c, 0xfe, 0xf1, 0x6a, 0x04, 0x46, 0x00, 0xf0, 0x43, 0xf8, - 0xa5, 0xf8, 0x4a, 0x00, 0x20, 0x46, 0x31, 0x6c, 0x00, 0xf0, 0x3d, 0xf8, - 0xa5, 0xf8, 0x5a, 0x01, 0x70, 0xbd, 0x0f, 0xf2, 0x80, 0x11, 0x51, 0xf8, - 0x20, 0x00, 0x00, 0xf0, 0x6a, 0xb9, 0x00, 0xe0, 0x00, 0xbf, 0xf0, 0xb5, - 0x14, 0x46, 0x83, 0xb0, 0x20, 0x70, 0x61, 0x70, 0x05, 0x00, 0x0f, 0xf2, - 0x54, 0x11, 0x51, 0xf8, 0x25, 0x60, 0x4f, 0x49, 0x66, 0x60, 0x4f, 0xf4, - 0x7c, 0x72, 0x02, 0xfb, 0x05, 0x11, 0xa1, 0x60, 0x18, 0xbf, 0x01, 0x2d, - 0x4b, 0x49, 0x07, 0xbf, 0xcf, 0x6a, 0x01, 0x20, 0x0f, 0x6c, 0x03, 0x20, - 0xf4, 0xf7, 0x5a, 0xf9, 0x04, 0xf1, 0x10, 0x01, 0x01, 0x91, 0x06, 0xf1, - 0x48, 0x03, 0x04, 0xf1, 0x0c, 0x01, 0x00, 0x91, 0x3a, 0x46, 0x01, 0x46, - 0x30, 0x46, 0x00, 0xf0, 0x27, 0xf8, 0x0f, 0xf2, 0x20, 0x10, 0x50, 0xf8, - 0x25, 0x10, 0x20, 0x46, 0x03, 0xb0, 0xbd, 0xe8, 0xf0, 0x40, 0x00, 0xf0, - 0x4a, 0xb9, 0x38, 0xb5, 0x0d, 0x46, 0x04, 0x46, 0xb5, 0xf1, 0x00, 0x5f, - 0x80, 0x41, 0xc0, 0x0f, 0xf7, 0xf7, 0x63, 0xff, 0xb4, 0xeb, 0x45, 0x0f, - 0x01, 0xd3, 0x00, 0x20, 0x32, 0xbd, 0x28, 0x09, 0x60, 0x21, 0x48, 0x43, - 0x21, 0x09, 0xb0, 0xfb, 0xf1, 0xf0, 0x30, 0x28, 0x01, 0xd2, 0x01, 0x20, - 0x32, 0xbd, 0x2f, 0x38, 0xff, 0x28, 0x88, 0xbf, 0xff, 0x20, 0x32, 0xbd, - 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x08, 0xf1, 0x48, 0x06, 0x0c, 0x46, - 0x70, 0x88, 0x91, 0x46, 0x1d, 0x46, 0xf5, 0xf7, 0x9f, 0xf8, 0x07, 0x46, - 0x15, 0x2c, 0x2c, 0xbf, 0x14, 0x3c, 0x00, 0x24, 0x48, 0x46, 0xf6, 0xf7, - 0x43, 0xfd, 0x81, 0x46, 0x20, 0x46, 0xf6, 0xf7, 0x3f, 0xfd, 0x49, 0x46, - 0xf6, 0xf7, 0xda, 0xfe, 0x04, 0x46, 0x07, 0xf1, 0x30, 0x00, 0x21, 0x49, - 0x48, 0x43, 0xf6, 0xf7, 0x35, 0xfd, 0x01, 0x46, 0x20, 0x46, 0xf6, 0xf7, - 0x41, 0xfd, 0xfd, 0xf7, 0xcd, 0xfd, 0x08, 0x9f, 0x09, 0x9c, 0xd0, 0xb1, - 0xf7, 0xf7, 0x5f, 0xff, 0x0c, 0x28, 0x28, 0xbf, 0x0c, 0x20, 0x31, 0x88, - 0x4f, 0xf2, 0xff, 0x02, 0x11, 0x40, 0x41, 0xea, 0x00, 0x21, 0x29, 0x80, - 0xc0, 0xf1, 0x0c, 0x00, 0x01, 0x21, 0x01, 0xfa, 0x00, 0xf0, 0x08, 0xf5, - 0x84, 0x71, 0x0a, 0x88, 0x02, 0xb9, 0x02, 0x46, 0x3a, 0x60, 0x49, 0x88, - 0x41, 0xb1, 0x21, 0x60, 0x07, 0xe0, 0x30, 0x88, 0x4f, 0xf2, 0xff, 0x01, - 0x08, 0x40, 0x28, 0x80, 0x00, 0x20, 0x38, 0x60, 0x20, 0x60, 0xbd, 0xe8, - 0xf1, 0x83, 0x04, 0x28, 0x06, 0xda, 0x04, 0x49, 0x4f, 0xf4, 0x7c, 0x72, - 0x02, 0xfb, 0x00, 0x10, 0x00, 0xf0, 0xe3, 0xbc, 0x70, 0x47, 0x00, 0x00, - 0xc0, 0x92, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, 0x98, 0x02, 0x00, 0x20, - 0x40, 0x42, 0x0f, 0x00, 0x98, 0x02, 0x00, 0x20, 0x98, 0x02, 0x00, 0x20, - 0xa8, 0x03, 0x00, 0x20, 0xa8, 0x03, 0x00, 0x20, 0x04, 0xea, 0x00, 0x20, - 0xa0, 0xea, 0x00, 0x20, 0x3c, 0xeb, 0x00, 0x20, 0xd8, 0xeb, 0x00, 0x20, - 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, - 0x01, 0x68, 0x11, 0xf1, 0x01, 0x0f, 0x1c, 0xbf, 0x49, 0x1c, 0x01, 0x60, - 0x70, 0x47, 0x01, 0x88, 0x4f, 0xf6, 0xff, 0x72, 0x91, 0x42, 0x1c, 0xbf, - 0x49, 0x1c, 0x01, 0x80, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, 0x00, 0x20, - 0x20, 0x80, 0x60, 0x80, 0x60, 0x60, 0x0d, 0x46, 0xc0, 0x21, 0x04, 0xf1, - 0x08, 0x00, 0xf7, 0xf7, 0x11, 0xfd, 0x4f, 0xf0, 0x80, 0x40, 0xa0, 0x66, - 0x00, 0x21, 0x04, 0xf1, 0xd0, 0x00, 0x01, 0x70, 0x4f, 0xf0, 0x7e, 0x51, - 0x41, 0x60, 0x00, 0x21, 0x81, 0x60, 0x01, 0x73, 0x04, 0xf1, 0xe0, 0x00, - 0x01, 0xf0, 0xea, 0xfe, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0x58, 0xe0, - 0x38, 0xb5, 0x00, 0x25, 0x05, 0x80, 0x00, 0xf1, 0xe0, 0x04, 0x45, 0x80, - 0xd0, 0x30, 0x65, 0x68, 0x45, 0x60, 0x25, 0x68, 0x85, 0x60, 0x01, 0x25, - 0x05, 0x73, 0x00, 0x25, 0x45, 0x73, 0x05, 0x70, 0x20, 0x46, 0x01, 0xb0, - 0xbd, 0xe8, 0x30, 0x40, 0x01, 0xf0, 0x53, 0xbe, 0x70, 0xb5, 0x0c, 0x46, - 0xc0, 0x21, 0x06, 0x46, 0x00, 0x20, 0x30, 0x80, 0x70, 0x80, 0x70, 0x60, - 0x06, 0xf1, 0xe0, 0x05, 0x06, 0xf1, 0x08, 0x00, 0xf7, 0xf7, 0xd8, 0xfc, - 0x4f, 0xf0, 0x80, 0x40, 0xb0, 0x66, 0x06, 0xf1, 0xd0, 0x01, 0x05, 0xf5, - 0x0a, 0x70, 0x42, 0x68, 0x4a, 0x60, 0x00, 0x68, 0x88, 0x60, 0x01, 0x20, - 0x08, 0x73, 0x00, 0x20, 0x48, 0x73, 0x95, 0xf8, 0xf4, 0x02, 0x08, 0x70, - 0x21, 0x46, 0x28, 0x46, 0xbd, 0xe8, 0x70, 0x40, 0x01, 0xf0, 0xf6, 0xbe, - 0x00, 0x21, 0x01, 0x60, 0x41, 0x60, 0x81, 0x60, 0xc1, 0x60, 0x4f, 0xf0, - 0xff, 0x31, 0x01, 0x61, 0x00, 0x21, 0x41, 0x61, 0x70, 0x47, 0x42, 0x68, - 0x11, 0x43, 0x41, 0x60, 0x08, 0x30, 0x83, 0xe7, 0x02, 0x69, 0x8a, 0x42, - 0x88, 0xbf, 0x0a, 0x46, 0x02, 0x61, 0x42, 0x69, 0x91, 0x42, 0x38, 0xbf, - 0x11, 0x46, 0x41, 0x61, 0x70, 0x47, 0x0c, 0x30, 0x76, 0xe7, 0x10, 0xb5, - 0x04, 0x46, 0x00, 0x20, 0x20, 0x60, 0x28, 0x21, 0x64, 0x20, 0x60, 0x60, - 0x4f, 0xf0, 0xff, 0x30, 0xa0, 0x60, 0x00, 0x20, 0xe0, 0x60, 0x20, 0x61, - 0x04, 0xf1, 0x74, 0x00, 0xf7, 0xf7, 0x92, 0xfc, 0x04, 0xf1, 0x5c, 0x00, - 0xff, 0xf7, 0xce, 0xff, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x10, 0xb5, - 0x04, 0x46, 0x04, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0xc5, 0xff, 0x20, 0x46, - 0xbd, 0xe8, 0x10, 0x40, 0x10, 0xb5, 0x04, 0x46, 0x04, 0xf1, 0x2c, 0x00, - 0xff, 0xf7, 0xbc, 0xff, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x14, 0x30, - 0xb6, 0xe7, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0x0d, 0x46, 0xad, 0xf5, - 0x7c, 0x7d, 0x05, 0xf1, 0x74, 0x00, 0xc4, 0xf8, 0x60, 0x03, 0x00, 0x22, - 0x00, 0x21, 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0xea, 0xfe, 0xff, 0xf7, - 0x33, 0xff, 0x06, 0x46, 0x00, 0x20, 0x28, 0x60, 0x68, 0x60, 0x28, 0x46, - 0xff, 0xf7, 0xdc, 0xff, 0x86, 0xf3, 0x11, 0x88, 0x4f, 0xf4, 0x7c, 0x78, - 0xa1, 0x68, 0x42, 0x46, 0x68, 0x46, 0xf9, 0xf7, 0x1f, 0xfd, 0x00, 0x27, - 0x28, 0x46, 0xff, 0xf7, 0xd8, 0xff, 0x69, 0x46, 0x20, 0x46, 0x00, 0xf0, - 0x98, 0xf8, 0xff, 0xf7, 0x19, 0xff, 0x06, 0x46, 0xa0, 0x68, 0x42, 0x46, - 0x69, 0x46, 0xf9, 0xf7, 0x0f, 0xfd, 0xe8, 0x68, 0x40, 0x1c, 0xe8, 0x60, - 0x60, 0x7f, 0x10, 0xb1, 0x28, 0x69, 0x40, 0x1c, 0x28, 0x61, 0xa0, 0x68, - 0x61, 0x68, 0x40, 0x88, 0x89, 0x8a, 0x90, 0xfb, 0xf1, 0xf0, 0x64, 0x28, - 0x28, 0xbf, 0x63, 0x20, 0x68, 0x60, 0x61, 0x69, 0x09, 0xb3, 0x05, 0xf1, - 0x5c, 0x00, 0xff, 0xf7, 0x78, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x44, 0x00, - 0xff, 0xf7, 0x73, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x2c, 0x00, 0xff, 0xf7, - 0x6e, 0xff, 0x61, 0x69, 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0x69, 0xff, - 0x60, 0x69, 0xc1, 0x06, 0x01, 0xd5, 0x03, 0x20, 0x07, 0xe0, 0x81, 0x07, - 0x02, 0xd5, 0x01, 0x20, 0x28, 0x60, 0x3c, 0xe0, 0xc0, 0x07, 0x3b, 0xd5, - 0x02, 0x20, 0x28, 0x60, 0x37, 0xe0, 0x20, 0x69, 0xa8, 0xb3, 0xa0, 0x7f, - 0x00, 0x28, 0x1c, 0xbf, 0xe0, 0x7f, 0x00, 0x28, 0x30, 0xd0, 0x20, 0x6a, - 0xa8, 0x60, 0x05, 0xf1, 0x14, 0x00, 0x21, 0x6a, 0xff, 0xf7, 0x50, 0xff, - 0x21, 0x6a, 0x05, 0xf1, 0x2c, 0x00, 0xff, 0xf7, 0x4b, 0xff, 0x21, 0x6a, - 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x46, 0xff, 0x21, 0x6a, 0x05, 0xf1, - 0x5c, 0x00, 0xff, 0xf7, 0x41, 0xff, 0x20, 0x78, 0xa9, 0x68, 0x32, 0x30, - 0xc0, 0xb2, 0xf7, 0xf7, 0x79, 0xfe, 0xe0, 0x7f, 0x02, 0x28, 0x10, 0xd1, - 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0x3f, 0xff, 0x05, 0xf1, 0x2c, 0x00, - 0xff, 0xf7, 0x3b, 0xff, 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x37, 0xff, - 0x05, 0xf1, 0x5c, 0x00, 0xff, 0xf7, 0x33, 0xff, 0x00, 0xe0, 0x01, 0x27, - 0x05, 0xf1, 0x14, 0x00, 0xff, 0xf7, 0xa6, 0xfe, 0x05, 0xf1, 0x2c, 0x00, - 0xff, 0xf7, 0xa2, 0xfe, 0x05, 0xf1, 0x44, 0x00, 0xff, 0xf7, 0x9e, 0xfe, - 0x05, 0xf1, 0x5c, 0x00, 0xff, 0xf7, 0x9a, 0xfe, 0x60, 0x78, 0x08, 0xb9, - 0x01, 0x27, 0x00, 0xe0, 0x0f, 0xb1, 0x64, 0x20, 0x68, 0x60, 0x86, 0xf3, - 0x11, 0x88, 0x00, 0x2f, 0x3f, 0xf4, 0x66, 0xaf, 0x28, 0x68, 0x0d, 0xf5, - 0x7c, 0x7d, 0xbd, 0xe8, 0xf0, 0x81, 0xf8, 0xb5, 0x04, 0x46, 0x00, 0x20, - 0x60, 0x61, 0x20, 0x76, 0x60, 0x76, 0xa0, 0x76, 0xe0, 0x76, 0x20, 0x77, - 0x60, 0x77, 0x0d, 0x46, 0x04, 0xf1, 0x24, 0x00, 0x00, 0x21, 0x04, 0xf5, - 0x56, 0x76, 0x01, 0x70, 0x41, 0x60, 0x41, 0x70, 0xb1, 0x61, 0xf1, 0x61, - 0x20, 0x69, 0x88, 0xb1, 0x31, 0x68, 0x00, 0x29, 0x1c, 0xbf, 0x71, 0x79, - 0x01, 0x29, 0x0b, 0xd1, 0x61, 0x68, 0x2a, 0x88, 0x4b, 0x8a, 0x9a, 0x42, - 0x06, 0xd3, 0x6a, 0x88, 0x8b, 0x8a, 0x9a, 0x42, 0x89, 0x41, 0xc9, 0x43, - 0xc9, 0x0f, 0x00, 0xe0, 0x00, 0x21, 0xa1, 0x77, 0xa1, 0x7f, 0x01, 0xb9, - 0xe0, 0x68, 0x30, 0x84, 0x01, 0xf0, 0xfc, 0xfe, 0x30, 0x8c, 0x88, 0xb9, - 0x60, 0x69, 0x40, 0xf0, 0x10, 0x00, 0x60, 0x61, 0x0c, 0xe0, 0x20, 0x7e, - 0x03, 0x28, 0x56, 0xd0, 0x02, 0x28, 0x1c, 0xbf, 0x60, 0x7e, 0x01, 0x28, - 0x04, 0xd1, 0x60, 0x68, 0x80, 0x78, 0x08, 0xb1, 0xf2, 0xf7, 0x68, 0xfb, - 0x60, 0x69, 0x00, 0x28, 0x38, 0xd1, 0xdf, 0xf8, 0x74, 0x75, 0x20, 0x78, - 0x47, 0xf8, 0x20, 0x40, 0x00, 0x20, 0xf0, 0x61, 0x20, 0x76, 0x60, 0x76, - 0xa0, 0x76, 0x00, 0x21, 0xf3, 0xf7, 0x47, 0xf8, 0x20, 0x46, 0x00, 0xf0, - 0x4a, 0xf8, 0x20, 0x46, 0x00, 0xf0, 0xed, 0xf8, 0xf0, 0x69, 0x98, 0xb9, - 0x20, 0x46, 0x00, 0xf0, 0x8d, 0xf8, 0x20, 0x7e, 0x70, 0xb9, 0x20, 0x46, - 0x00, 0xf0, 0xaa, 0xf8, 0x28, 0xb3, 0x00, 0x20, 0x60, 0x76, 0x20, 0x46, - 0x00, 0xf0, 0x05, 0xf9, 0x30, 0x68, 0x31, 0x8c, 0x88, 0x42, 0xeb, 0xd3, - 0x01, 0x20, 0xa0, 0x76, 0x00, 0x20, 0x21, 0x78, 0x47, 0xf8, 0x21, 0x00, - 0x20, 0x46, 0x00, 0xf0, 0x5e, 0xf8, 0x00, 0x20, 0xf3, 0xf7, 0x7e, 0xf8, - 0xb0, 0x69, 0x00, 0x28, 0x04, 0xbf, 0xa0, 0x7e, 0x00, 0x28, 0xb6, 0xd0, - 0xa0, 0x7e, 0x70, 0xb1, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x05, 0xfa, - 0xe0, 0x7e, 0x28, 0xb9, 0x01, 0x20, 0x20, 0x77, 0x07, 0xe0, 0x01, 0x20, - 0x60, 0x76, 0xe1, 0xe7, 0x00, 0x20, 0x20, 0x77, 0xf1, 0xbd, 0x20, 0x7f, - 0x60, 0xb1, 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x79, 0xfa, 0x08, 0xb1, - 0x01, 0x20, 0x04, 0xe0, 0x60, 0x69, 0x40, 0xf0, 0x04, 0x00, 0x60, 0x61, - 0x00, 0x20, 0x60, 0x77, 0xf1, 0xbd, 0x38, 0xb5, 0x04, 0x46, 0x60, 0x68, - 0x18, 0x30, 0xf4, 0xf7, 0xdd, 0xfc, 0x20, 0x78, 0x02, 0x28, 0x18, 0xbf, - 0x03, 0x28, 0x27, 0xd1, 0xf3, 0xf7, 0xdc, 0xfa, 0x03, 0x28, 0x23, 0xd1, - 0x20, 0x78, 0x02, 0x28, 0x02, 0xd1, 0xf3, 0xf7, 0x2c, 0xfb, 0x01, 0xe0, - 0xf3, 0xf7, 0x3d, 0xfb, 0x05, 0x46, 0x04, 0xf5, 0x59, 0x70, 0xf4, 0xf7, - 0xc4, 0xff, 0x20, 0x78, 0x03, 0x28, 0x0c, 0xbf, 0x01, 0x20, 0x00, 0x20, - 0xf4, 0xf7, 0xe5, 0xff, 0x05, 0x2d, 0x18, 0xbf, 0x06, 0x2d, 0x02, 0xd1, - 0xf5, 0xf7, 0x17, 0xf8, 0x01, 0xe0, 0xf5, 0xf7, 0x10, 0xf8, 0xf4, 0xf7, - 0xfb, 0xff, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0xfd, 0xf7, 0x68, 0xbf, - 0x31, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0xf4, 0xf7, 0xf5, 0xfc, 0x20, 0x78, - 0x02, 0x28, 0x18, 0xbf, 0x03, 0x28, 0x0c, 0xd1, 0xf3, 0xf7, 0xaa, 0xfa, - 0x03, 0x28, 0x08, 0xd1, 0xfd, 0xf7, 0xb0, 0xff, 0x04, 0xf5, 0x59, 0x70, - 0xbd, 0xe8, 0x10, 0x40, 0x00, 0x21, 0xf4, 0xf7, 0xa8, 0xbf, 0x10, 0xbd, - 0x10, 0xb5, 0x00, 0xf0, 0x52, 0xf8, 0xfe, 0xf7, 0x00, 0xff, 0x60, 0x68, - 0x23, 0x78, 0xa1, 0x7f, 0x00, 0xf1, 0x18, 0x02, 0x0f, 0xf2, 0xb4, 0x40, - 0x18, 0x5c, 0xf4, 0xf7, 0xdc, 0xfc, 0x01, 0x28, 0x03, 0xd0, 0xa1, 0x68, - 0xd1, 0xf8, 0xec, 0x13, 0x09, 0xb1, 0x01, 0x20, 0x08, 0xe0, 0x02, 0x28, - 0x18, 0xbf, 0x00, 0x28, 0x04, 0xd0, 0x61, 0x69, 0x41, 0xf0, 0x01, 0x01, - 0x03, 0x20, 0x61, 0x61, 0x20, 0x76, 0x10, 0xbd, 0xd0, 0xb5, 0x00, 0xf0, - 0x30, 0xf8, 0xfe, 0xf7, 0xf2, 0xfe, 0x01, 0x28, 0x20, 0xd0, 0x00, 0x26, - 0x00, 0x27, 0x01, 0x22, 0xdf, 0xf8, 0xd4, 0x03, 0x00, 0xf0, 0x1e, 0xf8, - 0xdf, 0xf8, 0xd0, 0x03, 0x00, 0xf0, 0x1a, 0xf8, 0xdf, 0xf8, 0xcc, 0x03, - 0x50, 0xf8, 0x22, 0x00, 0xc1, 0x17, 0x49, 0x00, 0x41, 0xea, 0xd0, 0x71, - 0x16, 0xeb, 0x40, 0x06, 0x4f, 0x41, 0x52, 0x1c, 0x18, 0x2a, 0xe9, 0xd3, - 0x60, 0x68, 0xd0, 0xe9, 0x02, 0x23, 0x9f, 0x42, 0x04, 0xdc, 0x01, 0xdb, - 0x96, 0x42, 0x01, 0xd2, 0x00, 0x20, 0xd0, 0xbd, 0x01, 0x20, 0xd0, 0xbd, - 0x50, 0xf8, 0x22, 0x00, 0x16, 0xeb, 0x00, 0x16, 0x57, 0xeb, 0x10, 0x77, - 0x70, 0x47, 0x04, 0x46, 0x0f, 0xf2, 0x20, 0x40, 0x21, 0x78, 0x08, 0x5c, - 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, 0xa5, 0x7f, 0x05, 0xb1, 0x01, 0x25, - 0x21, 0x78, 0x0f, 0xf2, 0x10, 0x40, 0x08, 0x5c, 0xff, 0xf7, 0x7d, 0xfb, - 0x04, 0xf5, 0x54, 0x76, 0xb1, 0x68, 0x29, 0xb1, 0x31, 0x7b, 0x81, 0x42, - 0x04, 0xbf, 0x71, 0x7b, 0xa9, 0x42, 0x08, 0xd0, 0x01, 0x46, 0x2a, 0x46, - 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0xd5, 0xfc, 0x00, 0x20, 0xc6, 0xe9, - 0x00, 0x00, 0xa1, 0x68, 0x00, 0x20, 0xc1, 0xf8, 0xec, 0x03, 0x70, 0xbd, - 0x00, 0x22, 0x00, 0x21, 0x30, 0x30, 0xf4, 0xf7, 0xc8, 0xbc, 0x10, 0xb5, - 0x04, 0x46, 0x04, 0xf1, 0x30, 0x00, 0xf4, 0xf7, 0x0a, 0xfd, 0xd4, 0xe9, - 0x0c, 0x01, 0xc4, 0xe9, 0x3e, 0x01, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, - 0x04, 0x46, 0xad, 0xf2, 0xfc, 0x5d, 0xe0, 0x68, 0x00, 0xf5, 0x4b, 0x71, - 0x91, 0xf8, 0x00, 0x80, 0x4f, 0x78, 0x01, 0x21, 0x21, 0x77, 0x04, 0xf1, - 0x24, 0x06, 0x00, 0x21, 0x61, 0x77, 0x71, 0x70, 0xa1, 0x68, 0x67, 0x90, - 0x5c, 0x31, 0x66, 0x91, 0x20, 0x68, 0xe0, 0x30, 0x68, 0x90, 0x60, 0x68, - 0x69, 0x90, 0x61, 0x69, 0x20, 0x69, 0x01, 0xf0, 0xf7, 0xfd, 0x6a, 0x90, - 0x20, 0x68, 0x90, 0xf8, 0xd0, 0x10, 0x88, 0x45, 0x03, 0xd1, 0xd0, 0xf8, - 0xf8, 0x12, 0x01, 0x29, 0x06, 0xd1, 0x68, 0x9a, 0x01, 0x21, 0xc2, 0xf8, - 0x10, 0x12, 0x00, 0x21, 0xc0, 0xf8, 0xf8, 0x12, 0x01, 0x2f, 0x1b, 0xd1, - 0x69, 0x46, 0x66, 0xa8, 0x01, 0xf0, 0x8e, 0xfc, 0x60, 0x77, 0x00, 0x20, - 0x27, 0x68, 0x78, 0x80, 0x65, 0x7f, 0x1d, 0xb9, 0x4f, 0xf0, 0xff, 0x30, - 0x20, 0x62, 0x09, 0xe0, 0x00, 0x98, 0xfd, 0xf7, 0x47, 0xfa, 0x02, 0x2d, - 0x20, 0x62, 0x03, 0xd1, 0x41, 0x46, 0x38, 0x46, 0xff, 0xf7, 0x0a, 0xfd, - 0x01, 0x20, 0x70, 0x70, 0x02, 0x20, 0xbd, 0xe0, 0x00, 0x20, 0x00, 0x90, - 0x68, 0x98, 0x00, 0xf5, 0x04, 0x70, 0x01, 0x68, 0x91, 0xb1, 0x69, 0x46, - 0x66, 0xa8, 0x00, 0xf0, 0xdc, 0xf9, 0x68, 0x99, 0x01, 0xf5, 0x04, 0x71, - 0x48, 0x60, 0x48, 0x68, 0x03, 0x28, 0x14, 0xd0, 0x48, 0x68, 0x01, 0x28, - 0x02, 0xd0, 0x00, 0x20, 0x08, 0x60, 0x0e, 0xe0, 0x00, 0x20, 0x0d, 0xe0, - 0x40, 0x68, 0x02, 0x28, 0x69, 0x46, 0x66, 0xa8, 0x02, 0xd1, 0x00, 0xf0, - 0xc6, 0xf9, 0x01, 0xe0, 0x00, 0xf0, 0x6e, 0xf9, 0x68, 0x99, 0xc1, 0xf8, - 0x14, 0x02, 0x01, 0x20, 0x70, 0x70, 0x00, 0x2f, 0x68, 0x98, 0xd0, 0xf8, - 0x14, 0x02, 0x69, 0x99, 0x48, 0x62, 0x40, 0xf0, 0x8e, 0x80, 0x00, 0x20, - 0x00, 0x90, 0x4f, 0xf0, 0x00, 0x09, 0x27, 0x68, 0x07, 0xf1, 0xe0, 0x05, - 0x05, 0xf1, 0xcc, 0x00, 0x29, 0x68, 0x40, 0x68, 0xf6, 0xf7, 0x62, 0xfa, - 0x33, 0x90, 0x33, 0xa8, 0x05, 0xeb, 0x89, 0x0b, 0x00, 0xeb, 0x89, 0x0a, - 0xdb, 0xf8, 0x04, 0x00, 0xd5, 0xf8, 0xcc, 0x10, 0xf6, 0xf7, 0xf2, 0xfa, - 0xca, 0xf8, 0x04, 0x00, 0x09, 0xf1, 0x01, 0x09, 0xdb, 0xf8, 0x68, 0x00, - 0xca, 0xf8, 0x68, 0x00, 0xb9, 0xf1, 0x19, 0x0f, 0xe9, 0xd3, 0x00, 0x25, - 0x33, 0xa8, 0x00, 0xeb, 0x85, 0x09, 0x74, 0x49, 0xd9, 0xf8, 0x04, 0x00, - 0xf6, 0xf7, 0x42, 0xfa, 0x82, 0x46, 0x33, 0x98, 0xd9, 0xf8, 0x68, 0x10, - 0xf6, 0xf7, 0x3c, 0xfa, 0x81, 0x46, 0x50, 0x46, 0x51, 0x46, 0xf6, 0xf7, - 0xd3, 0xfa, 0x82, 0x46, 0x48, 0x46, 0x49, 0x46, 0xf6, 0xf7, 0xce, 0xfa, - 0x51, 0x46, 0xf6, 0xf7, 0x2f, 0xfa, 0x4f, 0xf0, 0x7a, 0x51, 0xf6, 0xf7, - 0xc7, 0xfa, 0x01, 0x46, 0xa0, 0x68, 0xd0, 0xf8, 0x00, 0x01, 0xf6, 0xf7, - 0xaf, 0xfa, 0x08, 0xd2, 0x01, 0x20, 0x30, 0x70, 0x41, 0x46, 0x20, 0x68, - 0xff, 0xf7, 0x84, 0xfc, 0x01, 0x20, 0x70, 0x70, 0x38, 0xe0, 0x6d, 0x1c, - 0x19, 0x2d, 0xcd, 0xd3, 0x07, 0xf1, 0xd4, 0x00, 0x01, 0x7a, 0x49, 0xb9, - 0x34, 0x99, 0x01, 0x60, 0x33, 0x99, 0x41, 0x60, 0x01, 0x21, 0x01, 0x72, - 0x01, 0x20, 0x21, 0x68, 0x81, 0xf8, 0xdd, 0x00, 0x20, 0x68, 0x80, 0xf8, - 0xd0, 0x80, 0x20, 0x68, 0xff, 0xf7, 0x2b, 0xfc, 0x20, 0x68, 0x80, 0x1c, - 0xff, 0xf7, 0x27, 0xfc, 0xa0, 0x69, 0x98, 0xb9, 0x20, 0x68, 0xd4, 0x30, - 0x18, 0x26, 0x41, 0x68, 0x33, 0x91, 0x00, 0x68, 0x34, 0x99, 0xf6, 0xf7, - 0x03, 0xf9, 0x05, 0x46, 0x33, 0xa8, 0x00, 0xeb, 0x86, 0x07, 0x29, 0x46, - 0x78, 0x68, 0xf6, 0xf7, 0x89, 0xfa, 0x76, 0x1e, 0x78, 0x60, 0xf5, 0xd5, - 0x20, 0x68, 0x01, 0x1d, 0x6b, 0x46, 0x01, 0xaa, 0x33, 0xa8, 0x01, 0xf0, - 0x22, 0xfd, 0x00, 0x20, 0x20, 0x77, 0x0d, 0xf2, 0xfc, 0x5d, 0xbd, 0xe8, - 0xf0, 0x8f, 0x70, 0xb5, 0x82, 0xb0, 0x04, 0x46, 0x0e, 0x46, 0x6a, 0x46, - 0x00, 0x21, 0x00, 0x20, 0xf2, 0xf7, 0xb9, 0xff, 0x00, 0x98, 0x30, 0xb9, - 0x01, 0x20, 0xe0, 0x76, 0x60, 0x69, 0x40, 0xf0, 0x08, 0x00, 0x60, 0x61, - 0x73, 0xbd, 0x20, 0x78, 0x01, 0x46, 0x02, 0x29, 0x04, 0xf1, 0x24, 0x05, - 0x08, 0xd0, 0x03, 0x29, 0x09, 0xd1, 0xf3, 0xf7, 0x4e, 0xf9, 0x68, 0x70, - 0x68, 0x78, 0xfd, 0xf7, 0xb6, 0xff, 0x0b, 0xe0, 0xf3, 0xf7, 0x33, 0xf9, - 0xf7, 0xe7, 0x00, 0x28, 0x18, 0xbf, 0x01, 0x29, 0x08, 0xd1, 0x0f, 0xf2, - 0x3c, 0x10, 0x08, 0x5c, 0xfd, 0xf7, 0xa0, 0xff, 0x40, 0x1e, 0x80, 0x41, - 0xc0, 0x0f, 0x68, 0x60, 0x00, 0x98, 0x06, 0x60, 0x00, 0x99, 0xd4, 0xf8, - 0x60, 0x03, 0x48, 0x60, 0x00, 0x99, 0x60, 0x68, 0x88, 0x60, 0x04, 0xf1, - 0x30, 0x00, 0x00, 0x99, 0xc8, 0x60, 0x00, 0x99, 0x68, 0x68, 0x88, 0x61, - 0x21, 0x78, 0x1f, 0x48, 0x01, 0x29, 0x03, 0xd9, 0x89, 0x1e, 0x01, 0x29, - 0x05, 0xd9, 0x09, 0xe0, 0x00, 0x9a, 0x41, 0x6b, 0x11, 0x61, 0xc0, 0x6a, - 0x08, 0xe0, 0x00, 0x9a, 0x81, 0x6c, 0x11, 0x61, 0x00, 0x6c, 0x03, 0xe0, - 0x00, 0x9a, 0xc1, 0x6d, 0x11, 0x61, 0x40, 0x6d, 0x00, 0x99, 0x15, 0x4a, - 0x48, 0x61, 0x00, 0x21, 0x00, 0x20, 0xf2, 0xf7, 0xf0, 0xff, 0x00, 0x98, - 0x90, 0xf8, 0x25, 0x00, 0x10, 0xb1, 0x20, 0x46, 0xff, 0xf7, 0x7a, 0xfe, - 0x00, 0x98, 0x40, 0x7f, 0xe0, 0x77, 0x00, 0x98, 0x50, 0xf8, 0x20, 0x1f, - 0x21, 0x62, 0x00, 0x79, 0x28, 0x70, 0x00, 0x98, 0x00, 0x7f, 0xe0, 0x76, - 0x00, 0x20, 0xf2, 0xf7, 0x96, 0xff, 0x73, 0xbd, 0x00, 0x00, 0x00, 0x00, - 0x18, 0xf3, 0x00, 0x20, 0x80, 0x16, 0x00, 0x41, 0x00, 0x16, 0x00, 0x41, - 0x80, 0x17, 0x00, 0x41, 0x00, 0x00, 0x80, 0xbf, 0x78, 0x29, 0x00, 0x20, - 0x89, 0x06, 0x01, 0x01, 0x2d, 0xe9, 0xf8, 0x43, 0x0d, 0x46, 0x04, 0x46, - 0x0f, 0xf2, 0x78, 0x00, 0x21, 0x78, 0x0f, 0x5c, 0x38, 0x46, 0xf4, 0xf7, - 0x04, 0xfc, 0x80, 0x46, 0xf1, 0xf7, 0xc8, 0xf9, 0x21, 0x78, 0x0f, 0xf2, - 0x70, 0x00, 0x08, 0x5c, 0x40, 0xf0, 0x02, 0x09, 0x29, 0x1d, 0x40, 0x46, - 0xf4, 0xf7, 0x96, 0xfb, 0x00, 0x26, 0x28, 0xb1, 0x49, 0x46, 0x38, 0x46, - 0xf4, 0xf7, 0xfd, 0xfb, 0x00, 0xb1, 0x01, 0x26, 0x95, 0xf8, 0xdd, 0x00, - 0x00, 0x28, 0x04, 0xbf, 0xa0, 0x6a, 0x00, 0x28, 0x0e, 0xd0, 0x02, 0x2f, - 0x06, 0xd3, 0x94, 0xf8, 0x25, 0x00, 0x00, 0x22, 0x00, 0x21, 0xfd, 0xf7, - 0xf4, 0xfe, 0x02, 0xe0, 0x20, 0x78, 0xfd, 0xf7, 0xc2, 0xfe, 0x00, 0x20, - 0x85, 0xf8, 0xdd, 0x00, 0xf1, 0xf7, 0xb3, 0xf9, 0x30, 0x46, 0xbd, 0xe8, - 0xf2, 0x83, 0x00, 0x21, 0x01, 0x80, 0x01, 0x21, 0xc0, 0xf8, 0xec, 0x13, - 0x70, 0x47, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, - 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x04, 0xf8, 0xb5, 0x04, 0x46, - 0x04, 0xf1, 0x14, 0x06, 0x06, 0xf5, 0xd0, 0x77, 0x0d, 0x46, 0x01, 0x20, - 0xb8, 0x62, 0x05, 0x20, 0xe1, 0x68, 0x08, 0x60, 0xa0, 0x68, 0x00, 0xf0, - 0x89, 0xf9, 0x00, 0x22, 0x31, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xcc, 0xf9, - 0x28, 0x68, 0x20, 0xbb, 0x38, 0x68, 0x10, 0xb3, 0x31, 0x46, 0x20, 0x46, - 0x00, 0xf0, 0x1c, 0xf9, 0xe1, 0x68, 0x00, 0x20, 0x08, 0x62, 0x01, 0x22, - 0x20, 0x68, 0x00, 0x78, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0xf0, 0x20, 0xf8, - 0x29, 0x68, 0x00, 0x29, 0x08, 0xbf, 0x00, 0x28, 0x0f, 0xd1, 0xa0, 0x68, - 0x00, 0x68, 0xc6, 0xf8, 0x34, 0x02, 0x02, 0x22, 0x20, 0x68, 0x00, 0x88, - 0xc0, 0xf3, 0x03, 0x20, 0x00, 0xf0, 0x10, 0xf8, 0x29, 0x68, 0x00, 0x29, - 0x08, 0xbf, 0x00, 0x28, 0x01, 0xd0, 0x00, 0x20, 0xf2, 0xbd, 0x20, 0x68, - 0x00, 0x88, 0xc0, 0xf3, 0x03, 0x20, 0xf8, 0x62, 0x03, 0x22, 0x00, 0xf0, - 0x03, 0xf8, 0xf4, 0xe7, 0x40, 0x1c, 0xf8, 0x62, 0x31, 0x46, 0x20, 0x46, - 0x00, 0xf0, 0x26, 0xbc, 0x51, 0x46, 0x70, 0x68, 0xf6, 0xf7, 0x5a, 0xb9, - 0x4f, 0xf0, 0x7e, 0x50, 0x29, 0x46, 0xf6, 0xf7, 0x45, 0xb8, 0x2d, 0xe9, - 0xf0, 0x47, 0x04, 0x46, 0x04, 0xf1, 0x14, 0x05, 0x05, 0xf5, 0xd0, 0x76, - 0x84, 0xb0, 0x01, 0x20, 0xb0, 0x62, 0x0f, 0x46, 0xe0, 0x68, 0x02, 0x21, - 0x01, 0x62, 0x02, 0x22, 0x05, 0x21, 0x01, 0x60, 0x20, 0x46, 0x29, 0x46, - 0x00, 0xf0, 0x76, 0xf9, 0x38, 0x68, 0x08, 0xb9, 0x30, 0x68, 0x38, 0xb9, - 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x00, 0x28, 0x0c, 0xbf, 0x02, 0x20, - 0x03, 0x20, 0x3e, 0xe0, 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x30, 0xb1, - 0x60, 0x68, 0xd0, 0xf8, 0x28, 0x03, 0x40, 0x28, 0xb6, 0x41, 0xf6, 0x0f, - 0x00, 0xe0, 0x00, 0x26, 0x01, 0x20, 0x00, 0x90, 0x02, 0xab, 0x01, 0xaa, - 0x29, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x2e, 0xf8, 0xa7, 0x68, 0x02, 0x98, - 0x39, 0x68, 0xf6, 0xf7, 0x0b, 0xf8, 0x04, 0x46, 0x07, 0xf1, 0xcc, 0x05, - 0x1e, 0xb1, 0x01, 0x98, 0x28, 0x60, 0x6c, 0x60, 0x1c, 0xe0, 0xdf, 0xf8, - 0xdc, 0x9d, 0x28, 0x68, 0xdf, 0xf8, 0xd8, 0x8d, 0x01, 0xf0, 0x02, 0xf8, - 0x82, 0x46, 0x01, 0x98, 0x01, 0xf0, 0x03, 0xf8, 0x51, 0x46, 0xf6, 0xf7, - 0x69, 0xf8, 0x28, 0x60, 0x49, 0x46, 0x68, 0x68, 0xf6, 0xf7, 0x00, 0xf9, - 0x81, 0x46, 0x20, 0x46, 0x00, 0xf0, 0xf7, 0xff, 0x00, 0xf0, 0xbc, 0xfb, - 0x68, 0x60, 0x38, 0x46, 0x00, 0xf0, 0xe4, 0xf8, 0x30, 0x46, 0x04, 0xb0, - 0xbd, 0xe8, 0xf0, 0x87, 0x2d, 0xe9, 0xf1, 0x4f, 0x84, 0xb0, 0x4f, 0xf0, - 0x7e, 0x50, 0x03, 0x90, 0x88, 0x46, 0x0e, 0x9f, 0x00, 0x20, 0x02, 0x90, - 0x00, 0x2f, 0x08, 0xf5, 0x13, 0x75, 0x14, 0xbf, 0x6c, 0x46, 0x03, 0xac, - 0x68, 0x60, 0x91, 0x46, 0x9a, 0x46, 0x28, 0x60, 0x01, 0x26, 0x04, 0x98, - 0x80, 0x68, 0x01, 0x90, 0x00, 0xeb, 0x86, 0x00, 0x40, 0x68, 0x00, 0x90, - 0xd8, 0xf8, 0x90, 0x01, 0xf0, 0x40, 0xc0, 0x07, 0x1a, 0xd5, 0x58, 0xf8, - 0x26, 0x10, 0x20, 0x68, 0x08, 0xeb, 0x86, 0x0b, 0xf6, 0xf7, 0xca, 0xf8, - 0xdb, 0xf8, 0xc8, 0x10, 0xf6, 0xf7, 0xc6, 0xf8, 0x69, 0x68, 0xf6, 0xf7, - 0x27, 0xf8, 0x68, 0x60, 0x21, 0x68, 0x08, 0x46, 0xf6, 0xf7, 0xbe, 0xf8, - 0xdb, 0xf8, 0xc8, 0x10, 0xf6, 0xf7, 0xba, 0xf8, 0x29, 0x68, 0xf6, 0xf7, - 0x1b, 0xf8, 0x28, 0x60, 0x76, 0x1c, 0x18, 0x2e, 0xd5, 0xdb, 0x68, 0x68, - 0x29, 0x68, 0xf5, 0xf7, 0x21, 0xff, 0xc9, 0xf8, 0x00, 0x00, 0x00, 0x2f, - 0x14, 0xbf, 0xe9, 0x46, 0x0d, 0xf1, 0x08, 0x09, 0x00, 0x20, 0x68, 0x60, - 0x28, 0x60, 0x01, 0x27, 0x01, 0x98, 0x00, 0xeb, 0x87, 0x00, 0x80, 0x6e, - 0x00, 0x90, 0xd8, 0xf8, 0x90, 0x01, 0xf8, 0x40, 0xc0, 0x07, 0x1b, 0xd5, - 0x08, 0xeb, 0x87, 0x04, 0x04, 0xf1, 0x64, 0x06, 0xd9, 0xf8, 0x00, 0x10, - 0x00, 0xf0, 0xc5, 0xf8, 0x01, 0x46, 0xd4, 0xf8, 0x2c, 0x01, 0xf5, 0xf7, - 0x7d, 0xff, 0x71, 0x6e, 0xf6, 0xf7, 0x8a, 0xf8, 0x69, 0x68, 0xf5, 0xf7, - 0xeb, 0xff, 0x68, 0x60, 0x70, 0x6e, 0x01, 0x46, 0xf6, 0xf7, 0x82, 0xf8, - 0x29, 0x68, 0xf5, 0xf7, 0xe3, 0xff, 0x28, 0x60, 0x7f, 0x1c, 0x18, 0x2f, - 0xd6, 0xdb, 0x68, 0x68, 0x29, 0x68, 0xf5, 0xf7, 0xe9, 0xfe, 0xca, 0xf8, - 0x00, 0x00, 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x2d, 0xe9, 0xf8, 0x4f, - 0x04, 0x46, 0x00, 0x26, 0x20, 0x69, 0x00, 0x90, 0x0d, 0x46, 0xb3, 0x46, - 0xb0, 0x46, 0xb1, 0x46, 0xb2, 0x46, 0x01, 0x27, 0x01, 0xe0, 0x03, 0x2f, - 0x0b, 0xda, 0x04, 0xeb, 0x87, 0x00, 0x00, 0xf5, 0x34, 0x70, 0x01, 0x68, - 0x40, 0x6e, 0xf5, 0xf7, 0xbf, 0xff, 0x00, 0xf0, 0x1e, 0xfb, 0x06, 0x46, - 0x0e, 0xe0, 0x00, 0xf0, 0x5b, 0xfe, 0x01, 0x46, 0x00, 0x98, 0xb8, 0x42, - 0x04, 0xda, 0x40, 0x46, 0xf5, 0xf7, 0xb2, 0xff, 0x80, 0x46, 0x03, 0xe0, - 0x58, 0x46, 0xf5, 0xf7, 0xad, 0xff, 0x83, 0x46, 0x00, 0xf0, 0x4c, 0xfe, - 0xd5, 0xf8, 0x9c, 0x11, 0xf9, 0x40, 0xc9, 0x07, 0x03, 0xd5, 0x00, 0xf0, - 0x01, 0xfb, 0x81, 0x46, 0x03, 0xe0, 0x51, 0x46, 0xf5, 0xf7, 0x9e, 0xff, - 0x82, 0x46, 0x7f, 0x1c, 0x18, 0x2f, 0xd0, 0xdb, 0x58, 0x46, 0x41, 0x46, - 0xf5, 0xf7, 0x96, 0xff, 0x02, 0x46, 0x50, 0x46, 0x49, 0x46, 0xf6, 0xf7, - 0x1b, 0xf8, 0x10, 0x46, 0x31, 0x46, 0x05, 0xd2, 0xf6, 0xf7, 0x16, 0xf8, - 0x2c, 0xbf, 0x01, 0x20, 0x04, 0x20, 0x0d, 0xe0, 0xf6, 0xf7, 0x10, 0xf8, - 0x38, 0xbf, 0x02, 0x20, 0x08, 0xd3, 0x58, 0x46, 0xf5, 0xf7, 0x80, 0xff, - 0x41, 0x46, 0xf6, 0xf7, 0x07, 0xf8, 0x34, 0xbf, 0x03, 0x20, 0x00, 0x20, - 0xe1, 0x68, 0x08, 0x60, 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, 0xf0, 0x41, - 0x80, 0x46, 0x00, 0x27, 0x08, 0xf5, 0x01, 0x75, 0x08, 0xf1, 0xcc, 0x06, - 0x08, 0xeb, 0x87, 0x04, 0x30, 0x68, 0x61, 0x68, 0xf6, 0xf7, 0x04, 0xf8, - 0x60, 0x60, 0x28, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x05, 0xd5, 0xd4, 0xf8, - 0xd4, 0x10, 0x00, 0xf0, 0x2e, 0xf8, 0xc4, 0xf8, 0xd4, 0x00, 0x7f, 0x1c, - 0x18, 0x2f, 0xeb, 0xdb, 0x4f, 0xf0, 0x7e, 0x50, 0x30, 0x60, 0x00, 0x27, - 0xd8, 0xf8, 0x00, 0x10, 0x70, 0x68, 0xf5, 0xf7, 0x51, 0xff, 0xc8, 0xf8, - 0x00, 0x00, 0x08, 0xeb, 0x87, 0x00, 0x00, 0xf5, 0x9c, 0x74, 0x68, 0x68, - 0xf8, 0x40, 0xc0, 0x07, 0x04, 0xd5, 0x20, 0x68, 0x71, 0x68, 0xf5, 0xf7, - 0xcf, 0xfe, 0x20, 0x60, 0xa8, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x04, 0xd5, - 0x60, 0x6e, 0x71, 0x68, 0xf5, 0xf7, 0xc6, 0xfe, 0x60, 0x66, 0x7f, 0x1c, - 0x18, 0x2f, 0xe6, 0xdb, 0x00, 0x20, 0x70, 0x60, 0xbd, 0xe8, 0xf0, 0x81, - 0xf1, 0x68, 0x30, 0x68, 0xf5, 0xf7, 0xca, 0xbf, 0x2d, 0xe9, 0xf6, 0x4f, - 0x04, 0x46, 0x85, 0xb0, 0x60, 0x68, 0xd0, 0xf8, 0x28, 0x03, 0xf5, 0xf7, - 0x23, 0xfe, 0x05, 0x46, 0x4f, 0xf0, 0x8a, 0x40, 0x00, 0xf0, 0xd1, 0xff, - 0x83, 0x46, 0x82, 0x46, 0x4f, 0xf0, 0x8e, 0x40, 0x00, 0xf0, 0xcb, 0xff, - 0x05, 0x46, 0x06, 0x46, 0x4f, 0xf0, 0x00, 0x08, 0x00, 0xf0, 0x6e, 0xfa, - 0x04, 0xeb, 0x88, 0x07, 0xd2, 0xe9, 0x00, 0x01, 0xf5, 0xf7, 0xde, 0xfd, - 0x59, 0x46, 0x07, 0xf5, 0x34, 0x79, 0xf5, 0xf7, 0x17, 0xfe, 0xc9, 0xf8, - 0x00, 0x00, 0x07, 0xf5, 0x66, 0x77, 0x00, 0xf0, 0x5d, 0xfa, 0xd2, 0xe9, - 0x32, 0x01, 0xf5, 0xf7, 0xcf, 0xfd, 0x51, 0x46, 0xf5, 0xf7, 0x0a, 0xfe, - 0xc9, 0xf8, 0x64, 0x00, 0x00, 0xf0, 0x52, 0xfa, 0xd2, 0xe9, 0x64, 0x01, - 0xf5, 0xf7, 0xb6, 0xfd, 0x29, 0x46, 0xf5, 0xf7, 0xff, 0xfd, 0x38, 0x60, - 0x00, 0xf0, 0x48, 0xfa, 0x08, 0xf1, 0x01, 0x08, 0xd2, 0xe9, 0x96, 0x01, - 0xf5, 0xf7, 0xaa, 0xfd, 0x31, 0x46, 0xf5, 0xf7, 0xf3, 0xfd, 0xb8, 0xf1, - 0x19, 0x0f, 0x78, 0x66, 0xca, 0xd3, 0x62, 0x68, 0x01, 0x25, 0xd2, 0xe9, - 0xc8, 0x01, 0xf5, 0xf7, 0xab, 0xfd, 0x4f, 0xf0, 0x3a, 0x51, 0xf5, 0xf7, - 0x73, 0xff, 0xc4, 0xf8, 0x60, 0x04, 0xd4, 0xf8, 0xd0, 0x02, 0x01, 0x90, - 0x04, 0xeb, 0x85, 0x06, 0x06, 0xf5, 0x34, 0x71, 0x00, 0xf0, 0x72, 0xfd, - 0x07, 0x46, 0xd6, 0xf8, 0x98, 0x03, 0x4f, 0xf0, 0x80, 0x41, 0xf5, 0xf7, - 0x61, 0xff, 0x00, 0xf0, 0x9b, 0xfd, 0x07, 0x46, 0x01, 0x98, 0x39, 0x46, - 0xf5, 0xf7, 0x48, 0xff, 0x38, 0xbf, 0x01, 0x97, 0x6d, 0x1c, 0x15, 0x2d, - 0xe6, 0xd3, 0x01, 0x26, 0x05, 0x98, 0x00, 0xf5, 0xc8, 0x75, 0x00, 0x20, - 0x28, 0x60, 0x68, 0x60, 0xa8, 0x60, 0xe8, 0x60, 0x28, 0x61, 0xa8, 0x61, - 0x68, 0x61, 0xe8, 0x61, 0xe8, 0x62, 0x28, 0x63, 0x28, 0x62, 0x68, 0x62, - 0xa8, 0x62, 0xd4, 0xf8, 0x60, 0x14, 0xdf, 0xf8, 0x40, 0x0a, 0xf5, 0xf7, - 0x3d, 0xff, 0x03, 0x90, 0x04, 0xeb, 0x86, 0x00, 0x00, 0xf5, 0x34, 0x71, - 0x00, 0xf5, 0x66, 0x77, 0xd1, 0xf8, 0x00, 0xa0, 0x49, 0x6e, 0x00, 0x91, - 0x4f, 0xf0, 0x80, 0x41, 0x38, 0x68, 0xf5, 0xf7, 0x2d, 0xff, 0x81, 0x46, - 0x05, 0x98, 0x00, 0xeb, 0x86, 0x08, 0x78, 0x6e, 0xc8, 0xf8, 0x2c, 0x01, - 0x51, 0x46, 0x00, 0x98, 0xf5, 0xf7, 0x86, 0xfe, 0x83, 0x46, 0x00, 0xf0, - 0xe1, 0xf9, 0x02, 0x90, 0x00, 0x21, 0xf5, 0xf7, 0xfb, 0xfe, 0x07, 0x46, - 0x36, 0xd0, 0x58, 0x46, 0x49, 0x46, 0xf5, 0xf7, 0x05, 0xfe, 0x39, 0x46, - 0xf5, 0xf7, 0x84, 0xfd, 0x00, 0x21, 0xf6, 0xf7, 0x17, 0xf8, 0x81, 0x46, - 0x04, 0xd9, 0xdf, 0xf8, 0xdc, 0x09, 0x00, 0xf0, 0xff, 0xfd, 0x81, 0x46, - 0x48, 0x46, 0xf5, 0xf7, 0xab, 0xfe, 0x05, 0x99, 0x41, 0xf8, 0x26, 0x00, - 0x50, 0x46, 0x00, 0x99, 0xf5, 0xf7, 0xee, 0xfd, 0x81, 0x46, 0x4f, 0xf0, - 0x7c, 0x50, 0x49, 0x46, 0x08, 0xf1, 0x64, 0x0a, 0xf5, 0xf7, 0xf6, 0xfe, - 0xca, 0xf8, 0x00, 0x00, 0x39, 0x46, 0x4f, 0xf0, 0x3f, 0x40, 0xf5, 0xf7, - 0xef, 0xfe, 0xca, 0xf8, 0x64, 0x00, 0x00, 0x21, 0xda, 0xf8, 0x00, 0x00, - 0xf5, 0xf7, 0xf0, 0xff, 0x24, 0xbf, 0xdf, 0xf8, 0x90, 0x19, 0xf5, 0xf7, - 0xe3, 0xfe, 0x02, 0xe0, 0x4f, 0xf0, 0x7e, 0x59, 0xd6, 0xe7, 0x29, 0x6b, - 0xf5, 0xf7, 0xca, 0xfe, 0x38, 0xbf, 0x08, 0x46, 0x28, 0x63, 0xda, 0xf8, - 0x64, 0x10, 0xe8, 0x6a, 0xf5, 0xf7, 0xc2, 0xfe, 0x38, 0xbf, 0x01, 0x46, - 0xe9, 0x62, 0x38, 0x46, 0x01, 0x99, 0xd4, 0xf8, 0x00, 0xa0, 0xf5, 0xf7, - 0x3d, 0xfd, 0x0a, 0xf1, 0x08, 0x0b, 0x01, 0x46, 0xdb, 0xf8, 0x04, 0x00, - 0xf5, 0xf7, 0xb2, 0xfe, 0x08, 0xd2, 0xdb, 0xf8, 0x00, 0x00, 0x39, 0x46, - 0xf5, 0xf7, 0xac, 0xfe, 0x38, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x01, 0xd3, - 0x4f, 0xf0, 0x00, 0x0b, 0xa0, 0x68, 0xd0, 0xf8, 0x10, 0x02, 0x10, 0xb9, - 0x06, 0x98, 0x02, 0x28, 0x02, 0xd1, 0xda, 0xf8, 0x8c, 0x00, 0x78, 0xb1, - 0x0a, 0xeb, 0x86, 0x01, 0x03, 0x98, 0x89, 0x6a, 0xf5, 0xf7, 0xa8, 0xfe, - 0x00, 0x90, 0x39, 0x46, 0xdf, 0xf8, 0x10, 0x09, 0xf5, 0xf7, 0xa2, 0xfe, - 0x00, 0x99, 0xf5, 0xf7, 0x8d, 0xfe, 0x29, 0xd3, 0xbb, 0xf1, 0x00, 0x0f, - 0x1c, 0xbf, 0x06, 0x98, 0x01, 0x28, 0x25, 0xd0, 0x05, 0x98, 0xdf, 0xf8, - 0xf0, 0x18, 0x50, 0xf8, 0x26, 0x00, 0xf5, 0xf7, 0xf5, 0xfd, 0x83, 0x46, - 0xd8, 0xf8, 0x2c, 0x01, 0x39, 0x46, 0xf5, 0xf7, 0xfd, 0xfc, 0x80, 0x46, - 0x58, 0x46, 0x00, 0xf0, 0xb1, 0xfc, 0x07, 0x46, 0x40, 0x46, 0x00, 0xf0, - 0x7e, 0xfd, 0x00, 0xf0, 0xbd, 0xfc, 0x4f, 0xf0, 0x7a, 0x51, 0xf5, 0xf7, - 0x7d, 0xfe, 0x0a, 0xf1, 0x8c, 0x01, 0x49, 0x69, 0xf5, 0xf7, 0x66, 0xfe, - 0x38, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x01, 0xd3, 0x4f, 0xf0, 0x00, 0x0b, - 0x28, 0x69, 0x58, 0x44, 0x28, 0x61, 0x0b, 0xfa, 0x06, 0xf1, 0x28, 0x68, - 0x08, 0x43, 0x28, 0x60, 0x48, 0x46, 0x02, 0x99, 0xf5, 0xf7, 0xd8, 0xfc, - 0x01, 0x46, 0x20, 0x68, 0x07, 0x69, 0x38, 0x46, 0xf5, 0xf7, 0x4e, 0xfe, - 0x05, 0xd2, 0x01, 0x20, 0x5f, 0xea, 0x0b, 0x01, 0x0e, 0xd0, 0x01, 0x21, - 0x0c, 0xe0, 0xdf, 0xf8, 0x74, 0x08, 0xf5, 0xf7, 0x55, 0xfe, 0x01, 0x46, - 0x38, 0x46, 0xf5, 0xf7, 0x3f, 0xfe, 0x34, 0xbf, 0x4f, 0xf0, 0xff, 0x30, - 0x00, 0x20, 0x00, 0x21, 0xaa, 0x69, 0x8a, 0x18, 0xaa, 0x61, 0xb1, 0x40, - 0x6a, 0x68, 0x11, 0x43, 0xbb, 0xf1, 0x00, 0x0f, 0x69, 0x60, 0x04, 0xd0, - 0x10, 0xf1, 0x01, 0x0f, 0x08, 0xbf, 0x01, 0x21, 0x00, 0xd0, 0x00, 0x21, - 0x6a, 0x69, 0x8a, 0x18, 0x6a, 0x61, 0xb1, 0x40, 0xaa, 0x68, 0x11, 0x43, - 0xa9, 0x60, 0x40, 0x1e, 0x80, 0x41, 0xe9, 0x69, 0xc0, 0x0f, 0x41, 0x18, - 0xe9, 0x61, 0xb0, 0x40, 0xe9, 0x68, 0x76, 0x1c, 0x08, 0x43, 0x15, 0x2e, - 0xe8, 0x60, 0xff, 0xf4, 0xeb, 0xae, 0x4f, 0xf0, 0x7e, 0x50, 0x05, 0x99, - 0x08, 0x60, 0x00, 0x21, 0x05, 0x98, 0xc8, 0x30, 0x41, 0x66, 0x01, 0x60, - 0x00, 0x20, 0x05, 0x99, 0x48, 0x66, 0x15, 0x26, 0x05, 0x99, 0x4f, 0xf0, - 0x7e, 0x50, 0x41, 0xf8, 0x26, 0x00, 0x00, 0x21, 0x05, 0x98, 0x00, 0xeb, - 0x86, 0x00, 0x76, 0x1c, 0xc0, 0xf8, 0x2c, 0x11, 0x64, 0x30, 0x19, 0x2e, - 0x41, 0x66, 0x01, 0x60, 0xee, 0xd3, 0x06, 0x98, 0x01, 0x28, 0x25, 0xd1, - 0xe9, 0x6a, 0x4f, 0xf0, 0x40, 0x40, 0xf5, 0xf7, 0x01, 0xfe, 0x80, 0x46, - 0x01, 0x26, 0x04, 0xeb, 0x86, 0x07, 0x07, 0xf5, 0x34, 0x71, 0x00, 0xf0, - 0x03, 0xfc, 0x81, 0x46, 0xd7, 0xf8, 0x98, 0x03, 0x4f, 0xf0, 0x80, 0x41, - 0xf5, 0xf7, 0xf2, 0xfd, 0x00, 0xf0, 0xb2, 0xf8, 0x41, 0x46, 0xf5, 0xf7, - 0x5f, 0xfc, 0xdf, 0xf8, 0xa4, 0x17, 0xf5, 0xf7, 0xd7, 0xfd, 0x04, 0xd2, - 0x28, 0x68, 0x01, 0x21, 0xb1, 0x40, 0x88, 0x43, 0x28, 0x60, 0x76, 0x1c, - 0x18, 0x2e, 0xe0, 0xd3, 0x27, 0x68, 0xe9, 0x6a, 0x38, 0x6a, 0xf5, 0xf7, - 0xdb, 0xfd, 0x06, 0x46, 0x29, 0x6b, 0x78, 0x6a, 0xf5, 0xf7, 0xd6, 0xfd, - 0x80, 0x46, 0x01, 0x27, 0x05, 0x98, 0x00, 0xeb, 0x87, 0x00, 0x00, 0xf1, - 0x64, 0x09, 0x28, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x07, 0xd5, 0xd9, 0xf8, - 0x64, 0x00, 0x31, 0x46, 0xf5, 0xf7, 0xb4, 0xfd, 0x38, 0xbf, 0x01, 0x20, - 0x00, 0xd3, 0x00, 0x20, 0x29, 0x6a, 0xb8, 0x40, 0x08, 0x43, 0x28, 0x62, - 0x68, 0x68, 0xf8, 0x40, 0xc0, 0x07, 0x07, 0xd5, 0xd9, 0xf8, 0x00, 0x10, - 0x40, 0x46, 0xf5, 0xf7, 0xa3, 0xfd, 0x38, 0xbf, 0x01, 0x20, 0x00, 0xd3, - 0x00, 0x20, 0x69, 0x6a, 0xb8, 0x40, 0x08, 0x43, 0x68, 0x62, 0xa8, 0x68, - 0xf8, 0x40, 0xc0, 0x07, 0x0b, 0xd5, 0xdf, 0xf8, 0x14, 0x07, 0x00, 0xf0, - 0xa0, 0xfc, 0x01, 0x46, 0xd9, 0xf8, 0x00, 0x00, 0xf5, 0xf7, 0x8e, 0xfd, - 0x38, 0xbf, 0x01, 0x20, 0x00, 0xd3, 0x00, 0x20, 0xa9, 0x6a, 0xb8, 0x40, - 0x7f, 0x1c, 0x08, 0x43, 0x18, 0x2f, 0xa8, 0x62, 0xc0, 0xd3, 0x04, 0xf5, - 0x34, 0x70, 0xd4, 0xf8, 0x9c, 0x63, 0xd4, 0xf8, 0xd0, 0x12, 0x40, 0x68, - 0xf5, 0xf7, 0xf0, 0xfc, 0x04, 0xf5, 0x34, 0x71, 0x4f, 0xf0, 0x02, 0x08, - 0x89, 0x6e, 0xf5, 0xf7, 0xe9, 0xfc, 0x00, 0xf0, 0x48, 0xf8, 0x00, 0xf0, - 0x46, 0xf8, 0x06, 0x46, 0x00, 0x20, 0x04, 0xeb, 0x88, 0x01, 0x01, 0xf5, - 0x34, 0x79, 0xd1, 0xf8, 0x98, 0x73, 0xd9, 0xf8, 0x00, 0x10, 0xf5, 0xf7, - 0xd9, 0xfc, 0xd9, 0xf8, 0x64, 0x10, 0xf5, 0xf7, 0xd5, 0xfc, 0x00, 0xf0, - 0xab, 0xfb, 0x00, 0xf0, 0xa9, 0xfb, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, - 0x18, 0x0f, 0xe8, 0xd3, 0xa7, 0x68, 0xdf, 0xf8, 0x3c, 0x1d, 0xf5, 0xf7, - 0x63, 0xfd, 0x01, 0x46, 0x30, 0x46, 0xf5, 0xf7, 0x4d, 0xfd, 0x34, 0xbf, - 0x01, 0x20, 0x00, 0x20, 0x87, 0xf8, 0x08, 0x03, 0xe1, 0x68, 0x28, 0x68, - 0x48, 0x60, 0xe1, 0x68, 0x68, 0x68, 0x88, 0x60, 0xe1, 0x68, 0xa8, 0x68, - 0xc8, 0x60, 0xe1, 0x68, 0xe8, 0x68, 0x08, 0x61, 0xe1, 0x68, 0x28, 0x6a, - 0x48, 0x61, 0xe1, 0x68, 0x68, 0x6a, 0x88, 0x61, 0xe1, 0x68, 0xa8, 0x6a, - 0xc8, 0x61, 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x60, 0x68, 0x00, 0xeb, - 0xc8, 0x02, 0x70, 0x47, 0x49, 0x46, 0xf5, 0xf7, 0x9f, 0xbc, 0x31, 0x46, - 0xf5, 0xf7, 0x9c, 0xbc, 0x2d, 0xe9, 0xf7, 0x4f, 0x86, 0xb0, 0x80, 0x68, - 0xd0, 0xf8, 0x00, 0x02, 0x40, 0x08, 0x00, 0xf0, 0x01, 0x00, 0x03, 0x90, - 0x07, 0x98, 0x00, 0xf5, 0xc8, 0x74, 0x20, 0x69, 0x00, 0x28, 0x00, 0xf0, - 0xae, 0x81, 0x07, 0x98, 0xdf, 0xf8, 0x0c, 0xb6, 0x00, 0xf5, 0xe8, 0x70, - 0x04, 0x90, 0x64, 0x21, 0xf6, 0xf7, 0xce, 0xfb, 0x07, 0x98, 0x00, 0xf5, - 0x0d, 0x76, 0x14, 0x21, 0x30, 0x46, 0xf6, 0xf7, 0xc7, 0xfb, 0x07, 0x98, - 0x00, 0xf5, 0xe2, 0x70, 0x00, 0x90, 0x4f, 0xf0, 0x7e, 0x58, 0x08, 0x98, - 0x01, 0x28, 0x46, 0xd1, 0x00, 0xf0, 0xdd, 0xfa, 0x0a, 0xe0, 0xf5, 0xf7, - 0x09, 0xfd, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, 0xda, 0xfa, - 0x30, 0x62, 0x6d, 0x1c, 0x00, 0xf0, 0xe9, 0xfa, 0x18, 0x2d, 0x47, 0xd2, - 0x20, 0x68, 0x22, 0x6a, 0x65, 0x63, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, - 0x06, 0x98, 0x81, 0x68, 0xd1, 0xf8, 0x04, 0x02, 0xc6, 0xf8, 0x14, 0x80, - 0xe8, 0x40, 0xea, 0x40, 0xc6, 0xf8, 0x18, 0x80, 0x01, 0x23, 0x00, 0xf0, - 0x01, 0x00, 0x02, 0xf0, 0x01, 0x02, 0xa3, 0x63, 0x4a, 0xb9, 0x28, 0xb1, - 0x00, 0xf0, 0x11, 0xfb, 0x06, 0x99, 0x09, 0x68, 0x49, 0x69, 0xd4, 0xe7, - 0xb9, 0xf1, 0x00, 0x0f, 0x0a, 0xd0, 0x07, 0x98, 0x50, 0xf8, 0x25, 0x00, - 0xf0, 0x61, 0x59, 0x46, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x00, 0xd0, 0xf8, - 0xc8, 0x00, 0xc6, 0xe7, 0x00, 0xf0, 0xfd, 0xfa, 0x01, 0x46, 0x06, 0x98, - 0x03, 0x9a, 0x00, 0x68, 0x00, 0x2a, 0x14, 0xbf, 0x80, 0x69, 0xc0, 0x69, - 0xbb, 0xe7, 0x02, 0x28, 0x72, 0xd1, 0x00, 0xf0, 0x94, 0xfa, 0x0a, 0xe0, - 0xf5, 0xf7, 0xc0, 0xfc, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, - 0x91, 0xfa, 0x30, 0x62, 0x00, 0xf0, 0xa1, 0xfa, 0x6d, 0x1c, 0x18, 0x2d, - 0x80, 0xf0, 0xf4, 0x80, 0x60, 0x68, 0x65, 0x63, 0xe8, 0x40, 0xc0, 0x07, - 0x5d, 0xbf, 0xa0, 0x68, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, 0x4f, 0xf0, - 0x01, 0x09, 0x00, 0xf0, 0x99, 0xfa, 0x29, 0xd4, 0xa1, 0x6a, 0xe9, 0x40, - 0xc9, 0x07, 0x25, 0xd4, 0x6f, 0xb1, 0x00, 0xeb, 0x85, 0x00, 0xc6, 0xf8, - 0x14, 0x80, 0xc6, 0xf8, 0x18, 0xb0, 0xd0, 0xf8, 0x38, 0x01, 0x00, 0xf0, - 0xdd, 0xfa, 0x00, 0xf0, 0xb8, 0xfa, 0x00, 0xf0, 0x7b, 0xfa, 0x01, 0x98, - 0x60, 0xb1, 0x00, 0xf0, 0x52, 0xfa, 0x80, 0x68, 0x00, 0xeb, 0x85, 0x00, - 0xd0, 0xf8, 0x9c, 0x01, 0x00, 0xf0, 0xce, 0xfa, 0x00, 0xf0, 0xa9, 0xfa, - 0x00, 0xf0, 0x6c, 0xfa, 0x01, 0x98, 0x38, 0x43, 0xc0, 0xb2, 0x00, 0x28, - 0xc6, 0xd1, 0xb9, 0xf1, 0x00, 0x0f, 0x12, 0xd0, 0x00, 0xf0, 0x43, 0xfa, - 0x06, 0x98, 0x80, 0x68, 0x49, 0x6e, 0x00, 0xeb, 0x85, 0x00, 0x40, 0x68, - 0xf5, 0xf7, 0x72, 0xfc, 0xb0, 0x61, 0xd9, 0xf8, 0x2c, 0x01, 0xf0, 0x61, - 0x01, 0x20, 0xa0, 0x63, 0xc6, 0xf8, 0x20, 0x80, 0xae, 0xe7, 0x70, 0x61, - 0xc6, 0xf8, 0x18, 0xb0, 0x00, 0xf0, 0x4f, 0xfa, 0x00, 0xf0, 0x6c, 0xfa, - 0x4f, 0xf0, 0x7c, 0x51, 0xf5, 0xf7, 0x5e, 0xfc, 0x00, 0xf0, 0xa2, 0xfa, - 0x01, 0x46, 0x31, 0x62, 0x06, 0x98, 0x03, 0x9a, 0x00, 0x68, 0x00, 0x2a, - 0x14, 0xbf, 0x80, 0x69, 0xc0, 0x69, 0x8f, 0xe7, 0x60, 0x6a, 0x00, 0x28, - 0x04, 0xbf, 0xa0, 0x6a, 0x00, 0x28, 0x05, 0xd0, 0x21, 0x6b, 0x08, 0x46, - 0xf5, 0xf7, 0x48, 0xfc, 0x02, 0x90, 0x01, 0xe0, 0xcd, 0xf8, 0x08, 0x80, - 0x00, 0xf0, 0x13, 0xfa, 0x0c, 0xe0, 0x02, 0x98, 0x51, 0x46, 0xf5, 0xf7, - 0x3d, 0xfc, 0x03, 0x2d, 0x30, 0x62, 0x02, 0xd2, 0x00, 0xf0, 0x0f, 0xfa, - 0x30, 0x62, 0x00, 0xf0, 0x1e, 0xfa, 0x6d, 0x1c, 0x18, 0x2d, 0x71, 0xd2, - 0x60, 0x68, 0x65, 0x63, 0xe8, 0x40, 0xc0, 0x07, 0x5d, 0xbf, 0xa0, 0x68, - 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x09, 0x4f, 0xf0, 0x01, 0x09, 0x00, 0xf0, - 0x17, 0xfa, 0x2f, 0xd4, 0xa1, 0x6a, 0xe9, 0x40, 0xc9, 0x07, 0x2b, 0xd4, - 0x06, 0x99, 0x09, 0x68, 0xd1, 0xf8, 0x14, 0xa0, 0x77, 0xb1, 0x00, 0xeb, - 0x85, 0x01, 0xc6, 0xf8, 0x14, 0x80, 0xc6, 0xf8, 0x18, 0x80, 0xd1, 0xf8, - 0x38, 0x11, 0x00, 0x68, 0xf5, 0xf7, 0x74, 0xfb, 0x00, 0xf0, 0x2b, 0xfa, - 0x00, 0xf0, 0xf4, 0xf9, 0x01, 0x98, 0x68, 0xb1, 0x00, 0xf0, 0xcb, 0xf9, - 0x81, 0x68, 0x01, 0xeb, 0x85, 0x00, 0x09, 0x68, 0xd0, 0xf8, 0x9c, 0x01, - 0xf5, 0xf7, 0x64, 0xfb, 0x00, 0xf0, 0x1b, 0xfa, 0x00, 0xf0, 0xe4, 0xf9, - 0x01, 0x98, 0x38, 0x43, 0xc0, 0xb2, 0x00, 0x28, 0xc1, 0xd1, 0xb9, 0xf1, - 0x00, 0x0f, 0x19, 0xd0, 0x00, 0xf0, 0xbb, 0xf9, 0xb0, 0x61, 0x06, 0x98, - 0xd0, 0xf8, 0x08, 0xa0, 0x49, 0x6e, 0x0a, 0xeb, 0x85, 0x00, 0x40, 0x68, - 0xf5, 0xf7, 0xe8, 0xfb, 0xda, 0xf8, 0x00, 0x10, 0xf5, 0xf7, 0xe4, 0xfb, - 0x01, 0x46, 0xd9, 0xf8, 0x2c, 0x01, 0xf5, 0xf7, 0xcf, 0xfa, 0xf0, 0x61, - 0xa5, 0x63, 0xc6, 0xf8, 0x20, 0x80, 0xa2, 0xe7, 0xc6, 0xf8, 0x14, 0x80, - 0xc6, 0xf8, 0x18, 0x80, 0x00, 0xf0, 0xbf, 0xf9, 0x08, 0x68, 0x49, 0x6e, - 0xf5, 0xf7, 0xc0, 0xfa, 0x4f, 0xf0, 0x7c, 0x51, 0xf5, 0xf7, 0xcc, 0xfb, - 0xf0, 0x61, 0xa5, 0x63, 0x06, 0x98, 0x03, 0x99, 0x00, 0x68, 0x00, 0x29, - 0x14, 0xbf, 0xd0, 0xf8, 0x18, 0xa0, 0xd0, 0xf8, 0x1c, 0xa0, 0x7e, 0xe7, - 0xe0, 0x6b, 0x01, 0x28, 0x05, 0xd1, 0x30, 0x68, 0x21, 0x6c, 0xf5, 0xf7, - 0x2b, 0xfa, 0x30, 0x60, 0x04, 0xe0, 0x02, 0x46, 0x04, 0x98, 0x31, 0x46, - 0x00, 0xf0, 0x14, 0xfb, 0x08, 0x98, 0x02, 0x28, 0x26, 0xd1, 0x34, 0x68, - 0x20, 0x46, 0x21, 0x46, 0xf5, 0xf7, 0x8a, 0xfb, 0x2f, 0xd1, 0x06, 0x98, - 0x85, 0x68, 0x95, 0xf8, 0x00, 0x02, 0xc0, 0x07, 0x12, 0xd5, 0x06, 0x98, - 0x00, 0x68, 0x46, 0x68, 0x40, 0x46, 0x31, 0x46, 0xf5, 0xf7, 0x8c, 0xfa, - 0x29, 0x68, 0xf5, 0xf7, 0x99, 0xfb, 0x07, 0x46, 0x20, 0x46, 0x31, 0x46, - 0xf5, 0xf7, 0x94, 0xfb, 0x00, 0xf0, 0xce, 0xf9, 0x28, 0x60, 0x00, 0xe0, - 0x2c, 0x60, 0xd5, 0xf8, 0x00, 0x02, 0x40, 0xf0, 0x01, 0x00, 0xc5, 0xf8, - 0x00, 0x02, 0x46, 0xe1, 0x00, 0x25, 0x00, 0xe0, 0x6d, 0x1c, 0xe0, 0x6b, - 0x85, 0x42, 0x0a, 0xd2, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x00, 0xd0, 0xf8, - 0x34, 0x02, 0x01, 0x46, 0xf5, 0xf7, 0x5a, 0xfb, 0xf2, 0xd0, 0x01, 0x20, - 0x36, 0xe1, 0x08, 0x98, 0x01, 0x28, 0x0c, 0xbf, 0x02, 0x20, 0x01, 0x20, - 0x00, 0x90, 0x31, 0x46, 0x06, 0x98, 0x03, 0x69, 0x07, 0x98, 0xe2, 0x6b, - 0x00, 0xf5, 0x16, 0x70, 0x00, 0xf0, 0x84, 0xfa, 0x08, 0x98, 0x01, 0x28, - 0x10, 0xd1, 0x00, 0x25, 0x09, 0xe0, 0x07, 0x99, 0x01, 0xeb, 0x80, 0x00, - 0x01, 0xeb, 0x85, 0x01, 0xd0, 0xf8, 0x5c, 0x02, 0xc1, 0xf8, 0x58, 0x02, - 0x6d, 0x1c, 0x06, 0x98, 0x07, 0x68, 0x78, 0x88, 0xa8, 0x42, 0xf0, 0xd2, - 0x00, 0x25, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x0b, 0x08, 0x98, 0x01, 0x28, - 0x1f, 0xd1, 0x06, 0x98, 0x81, 0x68, 0xdb, 0xf8, 0x58, 0x62, 0xd1, 0xf8, - 0x04, 0x02, 0x01, 0xeb, 0x85, 0x08, 0x98, 0xb1, 0x06, 0x98, 0x07, 0x68, - 0x7f, 0x68, 0x00, 0xf0, 0x57, 0xfb, 0x01, 0x46, 0xd8, 0xf8, 0x04, 0x00, - 0xf5, 0xf7, 0x3a, 0xfb, 0x83, 0x46, 0x30, 0x46, 0x39, 0x46, 0xf5, 0xf7, - 0x35, 0xfb, 0x00, 0xf0, 0x36, 0xf9, 0xc8, 0xf8, 0x04, 0x00, 0x2a, 0xe0, - 0xc8, 0xf8, 0x04, 0x60, 0x27, 0xe0, 0x03, 0x28, 0x25, 0xd1, 0x06, 0x98, - 0x82, 0x68, 0x02, 0xf5, 0x01, 0x76, 0x70, 0x68, 0x00, 0x28, 0x04, 0xbf, - 0xb0, 0x68, 0x00, 0x28, 0x16, 0xd0, 0x06, 0x98, 0x07, 0x68, 0x7f, 0x68, - 0x02, 0xeb, 0x85, 0x08, 0x00, 0xf0, 0x32, 0xfb, 0x01, 0x46, 0xd8, 0xf8, - 0x68, 0x00, 0xf5, 0xf7, 0x15, 0xfb, 0x06, 0x46, 0xdb, 0xf8, 0x58, 0x02, - 0x39, 0x46, 0xf5, 0xf7, 0x0f, 0xfb, 0xff, 0xf7, 0xd2, 0xfd, 0xc8, 0xf8, - 0x68, 0x00, 0x04, 0xe0, 0xdb, 0xf8, 0x58, 0x02, 0x02, 0xeb, 0x85, 0x01, - 0x88, 0x66, 0x6d, 0x1c, 0x19, 0x2d, 0xae, 0xd3, 0x00, 0x25, 0x01, 0x20, - 0xa8, 0x40, 0x00, 0x90, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x08, 0x08, 0x98, - 0x01, 0x28, 0x38, 0xd1, 0x06, 0x98, 0x82, 0x68, 0x21, 0x6a, 0x02, 0xf5, - 0x01, 0x76, 0xe9, 0x40, 0x30, 0x68, 0xe8, 0x40, 0xc9, 0x07, 0x00, 0xf0, - 0x01, 0x00, 0x18, 0xd5, 0xd8, 0xf8, 0x58, 0x82, 0x02, 0xeb, 0x85, 0x01, - 0x01, 0xf1, 0xd4, 0x0b, 0x50, 0xb1, 0x00, 0xf0, 0x22, 0xf9, 0x00, 0xf0, - 0xf9, 0xf8, 0x00, 0xf0, 0xd8, 0xf9, 0xff, 0xf7, 0x9f, 0xfd, 0xcb, 0xf8, - 0x00, 0x00, 0x01, 0xe0, 0xcb, 0xf8, 0x00, 0x80, 0x30, 0x68, 0x00, 0x99, - 0x08, 0x43, 0x30, 0x60, 0x8d, 0xe0, 0x00, 0x28, 0xfc, 0xd1, 0x02, 0xeb, - 0x85, 0x00, 0x00, 0xf1, 0xd4, 0x0b, 0x00, 0xf0, 0x0a, 0xf9, 0x00, 0xf0, - 0xe1, 0xf8, 0x06, 0x46, 0xd8, 0xf8, 0x58, 0x02, 0x00, 0xf0, 0xe8, 0xfc, - 0xff, 0xf7, 0x87, 0xfd, 0xcb, 0xf8, 0x00, 0x00, 0x79, 0xe0, 0x08, 0x98, - 0x03, 0x28, 0x76, 0xd1, 0x06, 0x98, 0xd0, 0xf8, 0x08, 0xa0, 0x0a, 0xf5, - 0x01, 0x76, 0x70, 0x68, 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x07, 0xb0, 0x68, - 0xe8, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x01, 0x90, 0x60, 0x6a, 0xe8, 0x40, - 0xc0, 0x07, 0x19, 0xd5, 0x00, 0xf0, 0xde, 0xf8, 0x80, 0x46, 0x0a, 0xeb, - 0x85, 0x00, 0x00, 0xf1, 0xd4, 0x0b, 0x57, 0xb1, 0x00, 0xf0, 0xdf, 0xf8, - 0x00, 0xf0, 0xb1, 0xf8, 0x00, 0xf0, 0x95, 0xf9, 0xff, 0xf7, 0x5c, 0xfd, - 0xcb, 0xf8, 0x64, 0x00, 0x01, 0xe0, 0xcb, 0xf8, 0x64, 0x80, 0x70, 0x68, - 0x00, 0x99, 0x08, 0x43, 0x70, 0x60, 0x4a, 0xe0, 0xa0, 0x6a, 0xe8, 0x40, - 0xc0, 0x07, 0x1b, 0xd5, 0x00, 0xf0, 0xb0, 0xfb, 0x83, 0x46, 0x01, 0x98, - 0x0a, 0xeb, 0x85, 0x09, 0x68, 0xb1, 0x00, 0xf0, 0xc2, 0xf8, 0x00, 0xf0, - 0x8f, 0xf8, 0x80, 0x46, 0x78, 0x68, 0x00, 0xf0, 0xa7, 0xf8, 0x41, 0x46, - 0xf5, 0xf7, 0xde, 0xf9, 0xc9, 0xf8, 0x9c, 0x01, 0x01, 0xe0, 0xc9, 0xf8, - 0x9c, 0xb1, 0xb0, 0x68, 0x00, 0x99, 0x08, 0x43, 0xb0, 0x60, 0x2a, 0xe0, - 0x01, 0x98, 0x38, 0x43, 0x27, 0xd1, 0x06, 0x98, 0x07, 0x68, 0x79, 0x68, - 0x4f, 0xf0, 0x7e, 0x50, 0x0a, 0xeb, 0x85, 0x09, 0xf5, 0xf7, 0x54, 0xf9, - 0x09, 0xf1, 0xd4, 0x0b, 0x00, 0xf0, 0x73, 0xf8, 0x06, 0x46, 0x00, 0xf0, - 0x93, 0xf8, 0x00, 0xf0, 0x7f, 0xfc, 0xff, 0xf7, 0x1e, 0xfd, 0xcb, 0xf8, - 0x64, 0x00, 0x4f, 0xf0, 0x7e, 0x50, 0x7e, 0x68, 0x31, 0x46, 0xf5, 0xf7, - 0x41, 0xf9, 0x00, 0xf0, 0x5d, 0xf8, 0x07, 0x46, 0x00, 0xf0, 0x72, 0xfb, - 0x31, 0x46, 0xf5, 0xf7, 0x49, 0xfa, 0x00, 0xf0, 0x83, 0xf8, 0xc9, 0xf8, - 0x9c, 0x01, 0x6d, 0x1c, 0x19, 0x2d, 0xff, 0xf4, 0x40, 0xaf, 0x00, 0x20, - 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0xc6, 0xf8, 0x14, 0xb0, 0xc6, 0xf8, - 0x18, 0xb0, 0x06, 0x98, 0x70, 0x47, 0x07, 0x98, 0x00, 0xeb, 0x85, 0x09, - 0x09, 0xf1, 0x64, 0x01, 0x08, 0x68, 0x70, 0x61, 0x70, 0x47, 0x06, 0x98, - 0x00, 0x68, 0x40, 0x88, 0x45, 0x1c, 0x70, 0x47, 0x30, 0x6a, 0xdf, 0xf8, - 0x88, 0x18, 0xf5, 0xf7, 0x97, 0xb8, 0x00, 0x00, 0x77, 0xbe, 0x7f, 0x3f, - 0x6f, 0x12, 0x83, 0x3a, 0x80, 0x61, 0x0c, 0x4a, 0x00, 0x00, 0x80, 0xbf, - 0xac, 0xc5, 0x27, 0x37, 0x52, 0x49, 0x9d, 0x39, 0x30, 0x62, 0x00, 0x98, - 0x61, 0xe0, 0x06, 0x98, 0x80, 0x68, 0x00, 0xeb, 0x85, 0x00, 0x00, 0xf5, - 0x9c, 0x71, 0x70, 0x47, 0x06, 0x98, 0x80, 0x68, 0x00, 0xf5, 0x02, 0x71, - 0x0a, 0x68, 0x49, 0x68, 0xe9, 0x40, 0x01, 0xf0, 0x01, 0x01, 0x01, 0x91, - 0xea, 0x40, 0x61, 0x6a, 0xe9, 0x40, 0xc9, 0x07, 0x02, 0xf0, 0x01, 0x07, - 0x70, 0x47, 0x59, 0x46, 0xf5, 0xf7, 0x5e, 0xb9, 0x04, 0xeb, 0x87, 0x00, - 0x00, 0xf5, 0x34, 0x71, 0x08, 0x68, 0x49, 0x6e, 0xf5, 0xf7, 0x56, 0xb9, - 0x01, 0x46, 0xd9, 0xf8, 0x9c, 0x01, 0xf5, 0xf7, 0xed, 0xb9, 0x01, 0x46, - 0xdb, 0xf8, 0x64, 0x00, 0xf5, 0xf7, 0xe8, 0xb9, 0x01, 0x46, 0xdb, 0xf8, - 0x00, 0x00, 0xf5, 0xf7, 0xe3, 0xb9, 0xf0, 0x61, 0xa5, 0x63, 0x51, 0x46, - 0x02, 0x98, 0xf5, 0xf7, 0xdd, 0xb9, 0x01, 0x46, 0x31, 0x62, 0x06, 0x98, - 0x00, 0x68, 0x40, 0x69, 0xf5, 0xf7, 0xd6, 0xb9, 0x59, 0x46, 0xf5, 0xf7, - 0xd3, 0xb9, 0x01, 0xeb, 0x85, 0x00, 0x59, 0x46, 0xd0, 0xf8, 0xd4, 0x00, - 0xf0, 0x61, 0xe0, 0x6a, 0xf5, 0xf7, 0xca, 0xb9, 0xd8, 0xf8, 0x58, 0x02, - 0xda, 0xf8, 0x00, 0x10, 0xf5, 0xf7, 0xb4, 0xb8, 0x39, 0x46, 0xf5, 0xf7, - 0x25, 0xb9, 0x06, 0x98, 0x07, 0x68, 0x79, 0x68, 0x4f, 0xf0, 0x7e, 0x50, - 0xf5, 0xf7, 0xaa, 0xb8, 0xf0, 0x61, 0x01, 0x20, 0xa0, 0x63, 0x20, 0x6b, - 0x01, 0x46, 0xf5, 0xf7, 0xb3, 0xb9, 0x2d, 0xe9, 0xf8, 0x4f, 0x05, 0x46, - 0x05, 0xf1, 0x84, 0x06, 0xf1, 0x68, 0xff, 0xf7, 0x4e, 0xf8, 0xb1, 0x68, - 0xf5, 0xf7, 0xa8, 0xf9, 0x04, 0x46, 0x68, 0x68, 0xf5, 0xf7, 0x06, 0xf8, - 0x00, 0xf0, 0x01, 0xf9, 0x29, 0x6f, 0xf5, 0xf7, 0x03, 0xf9, 0x28, 0x67, - 0x4f, 0xf0, 0x01, 0x0b, 0x68, 0x68, 0x29, 0x68, 0x48, 0x43, 0xf4, 0xf7, - 0xf9, 0xff, 0x80, 0x46, 0xff, 0xf7, 0xc6, 0xf9, 0xb1, 0x68, 0xf5, 0xf7, - 0x91, 0xf9, 0x07, 0x46, 0x10, 0xe0, 0x40, 0x46, 0x39, 0x46, 0x05, 0xeb, - 0x8b, 0x04, 0xf5, 0xf7, 0x89, 0xf9, 0x21, 0x6f, 0xf5, 0xf7, 0xea, 0xf8, - 0x20, 0x67, 0x0b, 0xf1, 0x01, 0x0b, 0x00, 0xf0, 0x7f, 0xf8, 0x00, 0xf0, - 0x7a, 0xf8, 0x80, 0x46, 0xa8, 0x68, 0x83, 0x45, 0xeb, 0xd3, 0x68, 0x68, - 0x40, 0x43, 0xf4, 0xf7, 0xd9, 0xff, 0x83, 0x46, 0x74, 0x68, 0x00, 0xf0, - 0xd1, 0xf8, 0x00, 0xf0, 0xd0, 0xf8, 0xff, 0xf7, 0x99, 0xff, 0xe9, 0x68, - 0xf5, 0xf7, 0xd0, 0xf8, 0xe8, 0x60, 0x01, 0x24, 0x00, 0xf0, 0x66, 0xf8, - 0xff, 0xf7, 0x90, 0xff, 0x81, 0x46, 0xff, 0xf7, 0x95, 0xf9, 0x71, 0x68, - 0xf5, 0xf7, 0x60, 0xf9, 0x00, 0x90, 0xd5, 0xf8, 0x08, 0xa0, 0x19, 0xe0, - 0x00, 0x98, 0x00, 0xf0, 0x4f, 0xf8, 0x05, 0xeb, 0x84, 0x07, 0x80, 0x46, - 0xf8, 0x68, 0x41, 0x46, 0xf5, 0xf7, 0xb6, 0xf8, 0xf8, 0x60, 0x05, 0xeb, - 0x8a, 0x07, 0x41, 0x46, 0xf8, 0x68, 0xf5, 0xf7, 0xaf, 0xf8, 0xf8, 0x60, - 0x64, 0x1c, 0xa8, 0x68, 0x82, 0x44, 0x00, 0xf0, 0x43, 0xf8, 0x00, 0xf0, - 0x39, 0xf8, 0x81, 0x46, 0xd5, 0xf8, 0x08, 0x80, 0x44, 0x45, 0xe1, 0xd3, - 0x34, 0x68, 0x00, 0xf0, 0x99, 0xf8, 0x00, 0xf0, 0x98, 0xf8, 0x06, 0x46, - 0x00, 0xf0, 0x34, 0xf8, 0xff, 0xf7, 0x5e, 0xff, 0x83, 0x46, 0x4f, 0xf0, - 0x01, 0x0a, 0x16, 0xe0, 0x48, 0x46, 0x31, 0x46, 0x05, 0xeb, 0x88, 0x07, - 0xf5, 0xf7, 0x2a, 0xf9, 0xf9, 0x68, 0xf5, 0xf7, 0x8b, 0xf8, 0xf8, 0x60, - 0x08, 0xf1, 0x01, 0x08, 0x00, 0xf0, 0x20, 0xf8, 0x00, 0xf0, 0x16, 0xf8, - 0x81, 0x46, 0x64, 0x1c, 0xa8, 0x68, 0x84, 0x42, 0xea, 0xd3, 0x0a, 0xf1, - 0x01, 0x0a, 0xa8, 0x68, 0x82, 0x45, 0x09, 0xd2, 0x00, 0xf0, 0x12, 0xf8, - 0xff, 0xf7, 0x3c, 0xff, 0x83, 0x46, 0xd9, 0x46, 0x08, 0xf1, 0x01, 0x08, - 0x01, 0x24, 0xed, 0xe7, 0xbd, 0xe8, 0xf1, 0x8f, 0x49, 0x46, 0xf5, 0xf7, - 0x07, 0xb9, 0x81, 0x46, 0x78, 0x68, 0x41, 0x46, 0xf5, 0xf7, 0x02, 0xb9, - 0x28, 0x68, 0xf4, 0xf7, 0x61, 0xbf, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, - 0x0d, 0x46, 0x16, 0x46, 0x99, 0x46, 0x00, 0x24, 0x00, 0x27, 0x0c, 0xe0, - 0x30, 0x46, 0xf4, 0xf7, 0x55, 0xff, 0x58, 0xf8, 0x27, 0x10, 0xf5, 0xf7, - 0xef, 0xf8, 0x21, 0x46, 0xf5, 0xf7, 0x50, 0xf8, 0x04, 0x46, 0x6e, 0x43, - 0x7f, 0x1c, 0x4f, 0x45, 0xf0, 0xd3, 0x20, 0x46, 0xbd, 0xe8, 0xf2, 0x83, - 0x2d, 0xe9, 0xf8, 0x43, 0x08, 0x9c, 0x80, 0x46, 0x0e, 0x46, 0x17, 0x46, - 0x99, 0x46, 0x00, 0x25, 0xa0, 0x07, 0x4c, 0xbf, 0x01, 0x22, 0x2a, 0x46, - 0x3b, 0x46, 0x29, 0x46, 0x30, 0x46, 0xff, 0xf7, 0xd4, 0xff, 0x48, 0xf8, - 0x25, 0x00, 0x6d, 0x1c, 0x19, 0x2d, 0xf1, 0xd3, 0xe0, 0x07, 0x4c, 0xbf, - 0x00, 0x26, 0x58, 0xf8, 0x29, 0x60, 0x4f, 0x46, 0x20, 0xe0, 0xc7, 0xf1, - 0x18, 0x00, 0xf4, 0xf7, 0x25, 0xff, 0x04, 0x46, 0xc9, 0xf1, 0x18, 0x00, - 0xf4, 0xf7, 0x20, 0xff, 0x01, 0x46, 0x20, 0x46, 0xf4, 0xf7, 0x2c, 0xff, - 0x04, 0x46, 0x58, 0xf8, 0x27, 0x00, 0x00, 0xf0, 0x14, 0xf8, 0x05, 0x46, - 0x4f, 0xf0, 0x7e, 0x50, 0x21, 0x46, 0xf4, 0xf7, 0x9f, 0xff, 0x31, 0x46, - 0xf5, 0xf7, 0xac, 0xf8, 0x29, 0x46, 0xf5, 0xf7, 0x0d, 0xf8, 0x48, 0xf8, - 0x27, 0x00, 0x7f, 0x1c, 0x19, 0x2f, 0xdc, 0xd3, 0xbd, 0xe8, 0xf1, 0x83, - 0xf0, 0x68, 0x21, 0x46, 0xf5, 0xf7, 0x9e, 0xb8, 0x2d, 0xe9, 0xf2, 0x4f, - 0x8a, 0xb0, 0x80, 0x46, 0x91, 0x46, 0x00, 0x26, 0x00, 0xe0, 0x76, 0x1c, - 0x4e, 0x45, 0x47, 0xd2, 0x00, 0x25, 0x12, 0xe0, 0x04, 0xeb, 0x0a, 0x00, - 0x00, 0xf0, 0x9a, 0xf8, 0xff, 0xf7, 0xc8, 0xfe, 0x07, 0x46, 0x64, 0x1c, - 0xac, 0x42, 0xf5, 0xd3, 0x06, 0xeb, 0x0a, 0x04, 0x58, 0xf8, 0x24, 0x00, - 0x00, 0xf0, 0x9c, 0xf8, 0x48, 0xf8, 0x24, 0x00, 0x6d, 0x1c, 0xae, 0x42, - 0x04, 0xd3, 0x00, 0x27, 0x00, 0x24, 0x05, 0xfb, 0x09, 0xfa, 0xed, 0xe7, - 0x06, 0xfb, 0x09, 0x61, 0x58, 0xf8, 0x21, 0x10, 0x4f, 0xf0, 0x7e, 0x50, - 0xf4, 0xf7, 0xe2, 0xfe, 0x05, 0x46, 0x05, 0xa8, 0x06, 0xf1, 0x01, 0x0a, - 0x40, 0xf8, 0x26, 0x50, 0x15, 0xe0, 0x04, 0xeb, 0x0b, 0x00, 0x00, 0xf0, - 0x71, 0xf8, 0xff, 0xf7, 0x9f, 0xfe, 0x07, 0x46, 0x64, 0x1c, 0xb4, 0x42, - 0xf5, 0xd3, 0x06, 0xeb, 0x0b, 0x04, 0x58, 0xf8, 0x24, 0x00, 0x00, 0xf0, - 0x73, 0xf8, 0x00, 0xf0, 0x6c, 0xf8, 0x48, 0xf8, 0x24, 0x00, 0x0a, 0xf1, - 0x01, 0x0a, 0xca, 0x45, 0xb9, 0xd2, 0x00, 0x27, 0x00, 0x24, 0x0a, 0xfb, - 0x09, 0xfb, 0xea, 0xe7, 0x0a, 0x98, 0x00, 0x68, 0x00, 0x90, 0x01, 0x25, - 0x15, 0xe0, 0x05, 0xfb, 0x09, 0x60, 0x58, 0xf8, 0x20, 0x00, 0x5d, 0xf8, - 0x26, 0x10, 0xf5, 0xf7, 0x3f, 0xf8, 0xff, 0xf7, 0x79, 0xfe, 0x07, 0x46, - 0x76, 0x1c, 0xae, 0x42, 0xf1, 0xd3, 0x0a, 0x98, 0x50, 0xf8, 0x25, 0x00, - 0x00, 0xf0, 0x4e, 0xf8, 0x4d, 0xf8, 0x25, 0x00, 0x6d, 0x1c, 0x4d, 0x45, - 0x02, 0xd2, 0x00, 0x27, 0x00, 0x26, 0xf0, 0xe7, 0x68, 0x46, 0x00, 0xeb, - 0x89, 0x00, 0xa9, 0xf1, 0x02, 0x05, 0x50, 0xf8, 0x04, 0x1c, 0x05, 0xa8, - 0x00, 0xeb, 0x89, 0x00, 0x50, 0xf8, 0x04, 0x0c, 0xf5, 0xf7, 0x1e, 0xf8, - 0x0a, 0x99, 0x01, 0xeb, 0x89, 0x01, 0x41, 0xf8, 0x04, 0x0c, 0x1b, 0xe0, - 0x0a, 0x99, 0x51, 0xf8, 0x26, 0x10, 0x05, 0xfb, 0x09, 0x60, 0x58, 0xf8, - 0x20, 0x00, 0xf5, 0xf7, 0x0f, 0xf8, 0xff, 0xf7, 0x49, 0xfe, 0x07, 0x46, - 0x76, 0x1c, 0x4e, 0x45, 0xf0, 0xd3, 0x5d, 0xf8, 0x25, 0x00, 0x00, 0xf0, - 0x1f, 0xf8, 0x05, 0xa9, 0x51, 0xf8, 0x25, 0x10, 0xf5, 0xf7, 0x00, 0xf8, - 0x0a, 0x99, 0x41, 0xf8, 0x25, 0x00, 0x6d, 0x1e, 0x00, 0x2d, 0x02, 0xd4, - 0x00, 0x27, 0x6e, 0x1c, 0xeb, 0xe7, 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, - 0x04, 0xfb, 0x09, 0x61, 0x58, 0xf8, 0x20, 0x00, 0x58, 0xf8, 0x21, 0x10, - 0xf4, 0xf7, 0xec, 0xbf, 0x02, 0x98, 0x29, 0x46, 0xf4, 0xf7, 0xe8, 0xbf, - 0x4f, 0xf0, 0x7e, 0x50, 0x39, 0x46, 0xf4, 0xf7, 0xd3, 0xbe, 0x2d, 0xe9, - 0xf2, 0x4f, 0x04, 0x46, 0x04, 0xf5, 0x00, 0x75, 0x50, 0x08, 0x03, 0x22, - 0x59, 0x08, 0x2a, 0x60, 0x40, 0x00, 0x49, 0x00, 0x41, 0xea, 0x00, 0x02, - 0xa8, 0x60, 0x6a, 0x60, 0xe9, 0x60, 0x4f, 0xf0, 0x00, 0x09, 0x68, 0x68, - 0xc0, 0x08, 0xc0, 0x00, 0x68, 0x60, 0xa8, 0x68, 0xc0, 0x08, 0xc0, 0x00, - 0xa8, 0x60, 0xe8, 0x68, 0xc0, 0x08, 0xc0, 0x00, 0xe8, 0x60, 0x68, 0x68, - 0xc0, 0x02, 0xc0, 0x0a, 0x68, 0x60, 0xa8, 0x68, 0xc0, 0x02, 0xc0, 0x0a, - 0xa8, 0x60, 0xe8, 0x68, 0xc0, 0x02, 0xc0, 0x0a, 0xe8, 0x60, 0x18, 0x20, - 0x69, 0x68, 0xc1, 0x40, 0xc9, 0x07, 0x07, 0xd4, 0xa9, 0x68, 0xc1, 0x40, - 0xc9, 0x07, 0x03, 0xd4, 0xe9, 0x68, 0xc1, 0x40, 0xc9, 0x07, 0x01, 0xd5, - 0x81, 0x46, 0x01, 0xe0, 0x40, 0x1e, 0xef, 0xd5, 0x4f, 0xf0, 0x00, 0x0a, - 0x50, 0x46, 0xca, 0x45, 0xc8, 0xbf, 0x48, 0x46, 0x04, 0xeb, 0x80, 0x07, - 0x04, 0xeb, 0x8a, 0x08, 0x08, 0xf1, 0x04, 0x06, 0x78, 0x68, 0x30, 0x60, - 0x08, 0xf1, 0xd4, 0x0b, 0x78, 0x68, 0xcb, 0xf8, 0x00, 0x00, 0x0a, 0xf1, - 0x01, 0x0a, 0xb8, 0x6e, 0x70, 0x66, 0x21, 0x68, 0xb8, 0x6e, 0xf4, 0xf7, - 0x7d, 0xfe, 0xcb, 0xf8, 0x64, 0x00, 0xb8, 0x6e, 0x21, 0x68, 0x00, 0xf0, - 0xb1, 0xf8, 0xc8, 0xf8, 0x9c, 0x01, 0x08, 0xf5, 0x0b, 0x70, 0x31, 0x68, - 0x01, 0x60, 0xba, 0xf1, 0x19, 0x0f, 0x71, 0x6e, 0x41, 0x66, 0x20, 0x68, - 0xa8, 0x62, 0xd3, 0xdb, 0x20, 0x68, 0xa8, 0x62, 0x04, 0xf5, 0x3d, 0x70, - 0x9d, 0xf8, 0x00, 0x10, 0x00, 0xf0, 0x02, 0xf8, 0xbd, 0xe8, 0xf1, 0x8f, - 0x01, 0x70, 0x29, 0x68, 0x41, 0x60, 0x69, 0x68, 0x81, 0x60, 0xa9, 0x68, - 0xc1, 0x60, 0xe9, 0x68, 0x01, 0x61, 0x70, 0x47, 0x38, 0xb5, 0x04, 0x46, - 0x00, 0xf0, 0x89, 0xfa, 0x04, 0xf1, 0xcc, 0x01, 0x4f, 0xf0, 0x7e, 0x50, - 0x00, 0x22, 0x08, 0x60, 0x4a, 0x60, 0x00, 0x21, 0x00, 0x25, 0x04, 0xeb, - 0x81, 0x02, 0x02, 0xf1, 0xd4, 0x03, 0x49, 0x1c, 0x18, 0x60, 0xc2, 0xf8, - 0x9c, 0x51, 0x00, 0x22, 0x19, 0x29, 0x5a, 0x66, 0xf3, 0xd3, 0x04, 0xf5, - 0x00, 0x75, 0x01, 0x21, 0x29, 0x60, 0x6f, 0xf0, 0x01, 0x01, 0x69, 0x60, - 0xa9, 0x60, 0xe9, 0x60, 0x69, 0x68, 0xc9, 0x08, 0xc9, 0x00, 0x69, 0x60, - 0xa9, 0x68, 0xc9, 0x08, 0xc9, 0x00, 0xa9, 0x60, 0xe9, 0x68, 0xc9, 0x08, - 0xc9, 0x00, 0xe9, 0x60, 0x69, 0x68, 0xc9, 0x02, 0xc9, 0x0a, 0x69, 0x60, - 0xa9, 0x68, 0xc9, 0x02, 0xc9, 0x0a, 0xa9, 0x60, 0xe9, 0x68, 0xc9, 0x02, - 0xc9, 0x0a, 0xe9, 0x60, 0x2a, 0x61, 0x6a, 0x61, 0x28, 0x62, 0xaa, 0x61, - 0xea, 0x61, 0x6a, 0x62, 0x04, 0xf5, 0x0a, 0x70, 0x00, 0xf0, 0x49, 0xfa, - 0x04, 0xf5, 0x3d, 0x70, 0x00, 0x21, 0xff, 0xf7, 0xad, 0xff, 0x01, 0x21, - 0x01, 0x75, 0x31, 0xbd, 0x2d, 0xe9, 0xf8, 0x43, 0x80, 0x46, 0x08, 0xf5, - 0x00, 0x75, 0x00, 0x26, 0xa8, 0x6a, 0xc8, 0xf8, 0x00, 0x00, 0x08, 0xeb, - 0x86, 0x09, 0x09, 0xf5, 0x0b, 0x74, 0x09, 0xf1, 0x04, 0x00, 0x21, 0x68, - 0x01, 0x60, 0x09, 0xf1, 0xd4, 0x07, 0x21, 0x68, 0x39, 0x60, 0x76, 0x1c, - 0x61, 0x6e, 0x41, 0x66, 0x60, 0x6e, 0xa9, 0x6a, 0xf4, 0xf7, 0xee, 0xfd, - 0x78, 0x66, 0x60, 0x6e, 0xa9, 0x6a, 0x00, 0xf0, 0x23, 0xf8, 0x19, 0x2e, - 0xc9, 0xf8, 0x9c, 0x01, 0xe3, 0xd3, 0x08, 0xf1, 0xcc, 0x00, 0x4f, 0xf0, - 0x7e, 0x51, 0x00, 0x22, 0x01, 0x60, 0x42, 0x60, 0x08, 0xf5, 0x3e, 0x70, - 0x02, 0x68, 0x2a, 0x60, 0x42, 0x68, 0x6a, 0x60, 0x82, 0x68, 0xaa, 0x60, - 0xc0, 0x68, 0xe8, 0x60, 0x00, 0x20, 0x68, 0x61, 0x29, 0x62, 0x01, 0x20, - 0xa8, 0x61, 0x00, 0x20, 0xe8, 0x61, 0x68, 0x62, 0xbd, 0xe8, 0xf1, 0x83, - 0xd8, 0xf8, 0x58, 0x02, 0xda, 0xf8, 0x00, 0x10, 0x80, 0xf0, 0x00, 0x40, - 0xf4, 0xf7, 0xc2, 0xbd, 0x80, 0xb5, 0x01, 0x21, 0xfb, 0xf7, 0xd8, 0xff, - 0xbd, 0xe8, 0x04, 0x40, 0x74, 0x49, 0xf4, 0xf7, 0xc9, 0xbe, 0x00, 0x00, - 0x0a, 0xd7, 0x23, 0x3c, 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, 0x04, 0xf1, - 0x14, 0x07, 0x07, 0xf5, 0xd0, 0x76, 0x01, 0x20, 0xb0, 0x62, 0x88, 0x46, - 0xe0, 0x68, 0x03, 0x21, 0x01, 0x62, 0x01, 0x22, 0x05, 0x21, 0x01, 0x60, - 0x20, 0x46, 0x39, 0x46, 0xfe, 0xf7, 0xe8, 0xfe, 0x30, 0x68, 0x00, 0x28, - 0x00, 0xf0, 0xc7, 0x80, 0x39, 0x46, 0x20, 0x46, 0xfe, 0xf7, 0x38, 0xfe, - 0x06, 0x46, 0x00, 0x20, 0x00, 0x90, 0x01, 0xab, 0x02, 0xaa, 0x39, 0x46, - 0x20, 0x46, 0xfe, 0xf7, 0xaf, 0xfd, 0xa0, 0x68, 0x00, 0xf5, 0x07, 0x77, - 0x3d, 0x68, 0x1d, 0xb9, 0x02, 0x98, 0x78, 0x60, 0x01, 0x98, 0x46, 0xe0, - 0x20, 0x68, 0x00, 0xf1, 0x88, 0x09, 0xd9, 0xf8, 0x0c, 0x00, 0x85, 0x42, - 0x23, 0xd2, 0x28, 0x46, 0xf4, 0xf7, 0xf0, 0xfc, 0x00, 0xf0, 0xb0, 0xf8, - 0x02, 0x99, 0xf4, 0xf7, 0xed, 0xfd, 0x81, 0x46, 0x68, 0x1c, 0xf4, 0xf7, - 0xe7, 0xfc, 0x01, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xf3, 0xfc, 0x78, 0x60, - 0x3d, 0x68, 0x28, 0x46, 0xf4, 0xf7, 0xde, 0xfc, 0xb9, 0x68, 0xf4, 0xf7, - 0x79, 0xfe, 0x01, 0x99, 0xf4, 0xf7, 0xda, 0xfd, 0x81, 0x46, 0x68, 0x1c, - 0xf4, 0xf7, 0xd4, 0xfc, 0x01, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xe0, 0xfc, - 0x1b, 0xe0, 0xd9, 0xf8, 0x08, 0x50, 0xfe, 0xf7, 0x0f, 0xfd, 0x00, 0xf0, - 0x8b, 0xf8, 0x82, 0x46, 0xff, 0xf7, 0x78, 0xfe, 0x51, 0x46, 0xf4, 0xf7, - 0xc5, 0xfd, 0x78, 0x60, 0x4f, 0xf0, 0x7e, 0x50, 0xd9, 0xf8, 0x08, 0x50, - 0xfe, 0xf7, 0x02, 0xfd, 0xb9, 0x68, 0xf4, 0xf7, 0x57, 0xfe, 0x81, 0x46, - 0x01, 0x98, 0xff, 0xf7, 0x68, 0xfe, 0xff, 0xf7, 0x13, 0xf9, 0xb8, 0x60, - 0x01, 0x2e, 0x18, 0xbf, 0x04, 0x2e, 0x07, 0xd1, 0x20, 0x68, 0xd0, 0xf8, - 0x88, 0x10, 0x34, 0x48, 0xf4, 0xf7, 0x46, 0xfe, 0x05, 0x46, 0x02, 0xe0, - 0x20, 0x68, 0xd0, 0xf8, 0x88, 0x50, 0x79, 0x68, 0x30, 0x48, 0xf4, 0xf7, - 0xa1, 0xfd, 0xd7, 0xf8, 0x08, 0x90, 0x01, 0x46, 0xf4, 0xf7, 0x38, 0xfe, - 0x83, 0x46, 0x48, 0x46, 0xff, 0xf7, 0x2a, 0xfd, 0xff, 0xf7, 0x35, 0xfc, - 0x4f, 0xf0, 0x7a, 0x5a, 0x51, 0x46, 0xf4, 0xf7, 0x2d, 0xfe, 0x81, 0x46, - 0x01, 0x20, 0x01, 0x2e, 0x18, 0xbf, 0x04, 0x2e, 0x03, 0xd1, 0x21, 0x68, - 0x88, 0x31, 0x49, 0x69, 0x02, 0xe0, 0x21, 0x68, 0x88, 0x31, 0x09, 0x69, - 0x88, 0x40, 0xf4, 0xf7, 0x75, 0xfc, 0xff, 0xf7, 0x30, 0xfe, 0x06, 0x46, - 0x02, 0x99, 0x1d, 0x48, 0xf4, 0xf7, 0x7a, 0xfd, 0x01, 0x46, 0xf4, 0xf7, - 0x13, 0xfe, 0x01, 0x99, 0x83, 0x46, 0x08, 0x46, 0xf4, 0xf7, 0x0e, 0xfe, - 0xff, 0xf7, 0x0f, 0xfc, 0x51, 0x46, 0xf4, 0xf7, 0x09, 0xfe, 0x01, 0x46, - 0x30, 0x46, 0xf4, 0xf7, 0xf3, 0xfd, 0x05, 0xd2, 0x08, 0x46, 0xff, 0xf7, - 0x2f, 0xff, 0xc8, 0xf8, 0x00, 0x00, 0x15, 0xe0, 0x21, 0x68, 0x38, 0x68, - 0x88, 0x31, 0xc9, 0x68, 0x88, 0x42, 0x03, 0xd2, 0x40, 0x1c, 0x38, 0x60, - 0x00, 0x20, 0x0c, 0xe0, 0x48, 0x46, 0xff, 0xf7, 0x1f, 0xff, 0xc8, 0xf8, - 0x00, 0x00, 0x29, 0x46, 0x48, 0x46, 0xf4, 0xf7, 0xd9, 0xfd, 0x38, 0xbf, - 0x01, 0x20, 0x00, 0xd3, 0x02, 0x20, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0x00, - 0x00, 0x00, 0x20, 0x42, 0x00, 0x00, 0x20, 0xc1, 0x71, 0x1d, 0x9e, 0x43, - 0x00, 0x00, 0x80, 0xbf, 0x79, 0x68, 0xf4, 0xf7, 0xd9, 0xbd, 0x00, 0x00, - 0x1a, 0x48, 0x01, 0x78, 0x09, 0x06, 0x00, 0xd4, 0x70, 0x47, 0x2d, 0xe9, - 0xf0, 0x41, 0x00, 0x78, 0x17, 0x4d, 0x00, 0xf0, 0x07, 0x04, 0x68, 0x78, - 0x84, 0x42, 0x01, 0xd1, 0x28, 0x78, 0x18, 0xbb, 0x0f, 0xf2, 0x5c, 0x00, - 0x13, 0x4f, 0x50, 0xf8, 0x24, 0x80, 0x4f, 0xf6, 0xff, 0x70, 0x38, 0x80, - 0x01, 0x26, 0x30, 0x46, 0xf4, 0xf7, 0x1e, 0xfc, 0x41, 0x46, 0xf4, 0xf7, - 0xb9, 0xfd, 0x0e, 0x49, 0xf4, 0xf7, 0x28, 0xfc, 0x01, 0x46, 0x0d, 0x48, - 0xf5, 0xf7, 0x29, 0xf8, 0x4f, 0xf0, 0x8f, 0x41, 0xf4, 0xf7, 0xae, 0xfd, - 0xf4, 0xf7, 0x18, 0xfe, 0x27, 0xf8, 0x16, 0x00, 0x76, 0x1c, 0x40, 0x2e, - 0xe7, 0xd3, 0x01, 0x20, 0x6c, 0x70, 0x28, 0x70, 0xbd, 0xe8, 0xf0, 0x81, - 0x13, 0x07, 0x00, 0x46, 0x96, 0xf3, 0x00, 0x20, 0x30, 0xf0, 0x00, 0x20, - 0x00, 0x00, 0xa0, 0x41, 0x00, 0x00, 0x20, 0x41, 0x00, 0x00, 0x80, 0xbe, - 0x00, 0x00, 0x00, 0xbf, 0x00, 0x00, 0x80, 0xbf, 0x00, 0x00, 0x00, 0xc0, - 0x00, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x00, 0x00, 0xa0, 0xc0, - 0x00, 0x00, 0xc0, 0xc0, 0x80, 0xb5, 0x4f, 0xf0, 0x9e, 0x41, 0xf4, 0xf7, - 0x8b, 0xfe, 0x02, 0xd8, 0x6f, 0xf0, 0x00, 0x40, 0x02, 0xbd, 0x4d, 0x49, - 0xf4, 0xf7, 0x6a, 0xfd, 0x24, 0xbf, 0xbd, 0xe8, 0x02, 0x40, 0xf4, 0xf7, - 0xe3, 0xbd, 0x4f, 0xf0, 0x00, 0x40, 0x02, 0xbd, 0x38, 0xb5, 0x0c, 0x46, - 0xf4, 0xf7, 0xd2, 0xfb, 0x46, 0x49, 0xf4, 0xf7, 0x6d, 0xfd, 0x05, 0x46, - 0x20, 0x46, 0xf4, 0xf7, 0xcb, 0xfb, 0x01, 0x46, 0x28, 0x46, 0xf4, 0xf7, - 0xd7, 0xfb, 0x4f, 0xf0, 0x7e, 0x51, 0xf4, 0xf7, 0xc5, 0xfc, 0xbd, 0xe8, - 0x32, 0x40, 0xfb, 0xf7, 0x5d, 0xbc, 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, - 0x0f, 0x46, 0x25, 0x68, 0x4f, 0xf0, 0x7c, 0x50, 0x29, 0x46, 0xf4, 0xf7, - 0x53, 0xfd, 0x29, 0x46, 0xf4, 0xf7, 0x50, 0xfd, 0x00, 0xf0, 0x70, 0xf8, - 0x81, 0x46, 0x28, 0x46, 0x49, 0x46, 0xf4, 0xf7, 0xbb, 0xfb, 0x4f, 0xf0, - 0x9d, 0x4b, 0x59, 0x46, 0xf4, 0xf7, 0x44, 0xfd, 0xff, 0xf7, 0xba, 0xff, - 0x38, 0x60, 0x4f, 0xf0, 0x7e, 0x58, 0x38, 0x1d, 0x00, 0x90, 0x68, 0x37, - 0x00, 0x25, 0xdf, 0xf8, 0xb4, 0xa0, 0x04, 0xeb, 0x85, 0x06, 0x4f, 0xf0, - 0x7c, 0x51, 0xb0, 0x6e, 0xf4, 0xf7, 0x32, 0xfd, 0xb1, 0x6e, 0xf4, 0xf7, - 0x2f, 0xfd, 0x00, 0xf0, 0x4f, 0xf8, 0x71, 0x68, 0xf4, 0xf7, 0x9c, 0xfb, - 0x59, 0x46, 0xf4, 0xf7, 0x27, 0xfd, 0x49, 0x46, 0xf4, 0xf7, 0x96, 0xfb, - 0x41, 0x46, 0xf4, 0xf7, 0x21, 0xfd, 0xff, 0xf7, 0x97, 0xff, 0x00, 0x99, - 0x41, 0xf8, 0x25, 0x00, 0x51, 0x46, 0xb0, 0x6e, 0xf4, 0xf7, 0x18, 0xfd, - 0x71, 0x68, 0xf4, 0xf7, 0x87, 0xfb, 0x59, 0x46, 0xf4, 0xf7, 0x12, 0xfd, - 0x49, 0x46, 0xf4, 0xf7, 0x81, 0xfb, 0x41, 0x46, 0xf4, 0xf7, 0x0c, 0xfd, - 0xff, 0xf7, 0x82, 0xff, 0x47, 0xf8, 0x25, 0x00, 0x51, 0x46, 0x40, 0x46, - 0xf4, 0xf7, 0x04, 0xfd, 0x6d, 0x1c, 0x18, 0x2d, 0x80, 0x46, 0xc6, 0xdb, - 0x60, 0x6e, 0x49, 0x46, 0xf4, 0xf7, 0xfc, 0xfc, 0x01, 0x46, 0x58, 0x46, - 0xf4, 0xf7, 0x6a, 0xfb, 0xff, 0xf7, 0x6e, 0xff, 0x00, 0x99, 0x08, 0x66, - 0x00, 0x20, 0x38, 0x66, 0x02, 0x98, 0x00, 0x68, 0x30, 0xb9, 0x01, 0x99, - 0x00, 0x98, 0x03, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0x00, 0xf0, 0x42, 0xb9, - 0xbd, 0xe8, 0xf7, 0x8f, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xce, - 0x00, 0x00, 0xc0, 0x41, 0x00, 0x00, 0x80, 0xbf, 0x01, 0x46, 0x4f, 0xf0, - 0x7e, 0x50, 0xf4, 0xf7, 0xc9, 0xbb, 0x00, 0x21, 0x01, 0x60, 0x00, 0xeb, - 0x81, 0x02, 0x4f, 0xf0, 0x7e, 0x53, 0x53, 0x60, 0x49, 0x1c, 0x00, 0x23, - 0x19, 0x29, 0x93, 0x66, 0xf5, 0xd3, 0x70, 0x47, 0xf8, 0xb5, 0x0f, 0x46, - 0xd7, 0xf8, 0x00, 0xe0, 0xd7, 0xf8, 0x04, 0xc0, 0x06, 0x46, 0x82, 0xfb, - 0x0e, 0x45, 0x83, 0xfb, 0x0c, 0x01, 0x20, 0x1a, 0x65, 0xeb, 0x01, 0x01, - 0x82, 0xfb, 0x0c, 0x45, 0xc3, 0xfb, 0x0e, 0x45, 0x32, 0x68, 0x73, 0x68, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x81, 0x18, 0x31, 0x60, 0xe4, 0x0d, - 0x44, 0xea, 0x45, 0x24, 0xe1, 0x18, 0x71, 0x60, 0x10, 0x1a, 0x38, 0x60, - 0x18, 0x1b, 0x78, 0x60, 0xf1, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x00, 0xf0, - 0x5b, 0xf8, 0x04, 0xf1, 0x08, 0x01, 0xff, 0xf7, 0xd5, 0xff, 0x00, 0xf0, - 0x55, 0xf8, 0x04, 0xf1, 0x18, 0x01, 0x04, 0xf1, 0x10, 0x00, 0xff, 0xf7, - 0xcd, 0xff, 0x00, 0xf0, 0x4d, 0xf8, 0x04, 0xf1, 0x10, 0x01, 0x20, 0x46, - 0xff, 0xf7, 0xc6, 0xff, 0x04, 0xf1, 0x18, 0x01, 0x04, 0xf1, 0x08, 0x00, - 0xbd, 0xe8, 0x10, 0x40, 0x4f, 0xf4, 0x00, 0x03, 0x00, 0x22, 0xbb, 0xe7, - 0x30, 0xb5, 0x85, 0xb0, 0x04, 0x46, 0x0d, 0x46, 0x68, 0x46, 0x0f, 0xf2, - 0x1c, 0x31, 0x10, 0x22, 0xf7, 0xf7, 0xf8, 0xfb, 0x00, 0x20, 0x10, 0xf8, - 0x0d, 0x10, 0x54, 0xf8, 0x21, 0x10, 0x45, 0xf8, 0x20, 0x10, 0x40, 0x1c, - 0x10, 0x28, 0xf6, 0xd3, 0x28, 0x46, 0xff, 0xf7, 0xc8, 0xff, 0x05, 0xf1, - 0x20, 0x00, 0xff, 0xf7, 0xc4, 0xff, 0x00, 0xf0, 0x21, 0xf8, 0x05, 0xf1, - 0x20, 0x01, 0x28, 0x46, 0xff, 0xf7, 0x9a, 0xff, 0xb1, 0x4c, 0x23, 0x46, - 0x22, 0x46, 0x05, 0xf1, 0x28, 0x01, 0x05, 0xf1, 0x08, 0x00, 0xff, 0xf7, - 0x91, 0xff, 0x4f, 0xf4, 0x00, 0x03, 0x00, 0x22, 0x05, 0xf1, 0x30, 0x01, - 0x05, 0xf1, 0x10, 0x00, 0xff, 0xf7, 0x88, 0xff, 0x23, 0x46, 0xa9, 0x4a, - 0x05, 0xf1, 0x38, 0x01, 0x05, 0xf1, 0x18, 0x00, 0xff, 0xf7, 0x80, 0xff, - 0x05, 0xb0, 0x30, 0xbd, 0x00, 0x23, 0x4f, 0xf4, 0x00, 0x02, 0x70, 0x47, - 0x2d, 0xe9, 0xf3, 0x43, 0x87, 0xb0, 0xff, 0xf7, 0xb9, 0xff, 0x08, 0x98, - 0x00, 0xf1, 0x40, 0x01, 0x07, 0x98, 0x08, 0x30, 0xff, 0xf7, 0xb2, 0xff, - 0x08, 0x98, 0x00, 0xf1, 0x80, 0x01, 0x07, 0x98, 0x10, 0x30, 0xff, 0xf7, - 0xab, 0xff, 0x00, 0x22, 0x08, 0x98, 0x07, 0x99, 0x50, 0xf8, 0x22, 0x00, - 0x41, 0xf8, 0x22, 0x00, 0x52, 0x1c, 0x30, 0x2a, 0xf6, 0xd3, 0x03, 0x20, - 0x4f, 0xf4, 0x00, 0x0e, 0x4f, 0xf0, 0x00, 0x08, 0x00, 0x27, 0x02, 0x90, - 0x00, 0x22, 0x07, 0x98, 0x50, 0xf8, 0x22, 0xc0, 0x00, 0xeb, 0x82, 0x01, - 0x08, 0x1d, 0x03, 0x68, 0xc4, 0x6b, 0x05, 0x6c, 0xc6, 0x6f, 0x01, 0x96, - 0xd1, 0xf8, 0x84, 0x10, 0x00, 0x91, 0x2f, 0xb9, 0x01, 0x98, 0x00, 0x19, - 0x00, 0xeb, 0x0c, 0x06, 0x48, 0x19, 0x52, 0xe0, 0x86, 0x48, 0x80, 0xfb, - 0x0e, 0x01, 0xcd, 0xe9, 0x04, 0x01, 0x85, 0x48, 0x80, 0xfb, 0x0e, 0x69, - 0x82, 0x48, 0x80, 0xfb, 0x08, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x2e, 0xdd, 0xe9, 0x04, 0x01, 0x7e, 0x4e, - 0xc6, 0xfb, 0x08, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x28, 0x84, 0xfb, - 0x0e, 0x69, 0x85, 0xfb, 0x08, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x84, 0x44, 0x85, 0xfb, 0x0e, 0x01, - 0xc4, 0xfb, 0x08, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0xc3, 0x18, - 0x8e, 0xfb, 0x0e, 0x45, 0x88, 0xfb, 0x08, 0x01, 0x20, 0x1a, 0x65, 0xeb, - 0x01, 0x01, 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x24, 0x88, 0xfb, 0x0e, 0x01, - 0x80, 0x0d, 0x40, 0xea, 0x81, 0x25, 0x01, 0x98, 0x80, 0xfb, 0x04, 0x69, - 0x00, 0x98, 0x80, 0xfb, 0x05, 0x01, 0x30, 0x1a, 0x69, 0xeb, 0x01, 0x01, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x00, 0xeb, 0x0c, 0x06, 0x00, 0x98, - 0xdd, 0xf8, 0x04, 0x90, 0x80, 0xfb, 0x04, 0x01, 0xc9, 0xfb, 0x05, 0x01, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x08, 0x99, 0x41, 0xf8, 0x27, 0x60, - 0x92, 0x1c, 0x08, 0x99, 0x01, 0xeb, 0x87, 0x01, 0xbf, 0x1c, 0xc0, 0x18, - 0x10, 0x2a, 0x48, 0x60, 0x8b, 0xd3, 0x02, 0x98, 0x40, 0x1e, 0x02, 0x90, - 0x86, 0xd1, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x83, 0x2d, 0xe9, 0xf3, 0x4f, - 0x87, 0xb0, 0x4f, 0xf4, 0x00, 0x02, 0x4f, 0xf0, 0x00, 0x0e, 0x00, 0x23, - 0x07, 0x98, 0x4f, 0xea, 0xee, 0x79, 0xde, 0xf5, 0x00, 0x0a, 0x50, 0xf8, - 0x23, 0x00, 0x69, 0xeb, 0x49, 0x07, 0xc1, 0x17, 0xaa, 0xfb, 0x00, 0x45, - 0x0a, 0xfb, 0x01, 0x55, 0x07, 0xfb, 0x00, 0x55, 0xcd, 0xe9, 0x04, 0x45, - 0x07, 0x99, 0x03, 0xf1, 0x19, 0x06, 0x51, 0xf8, 0x26, 0x60, 0x04, 0x46, - 0x50, 0x46, 0x39, 0x46, 0xf5, 0x17, 0xa0, 0xfb, 0x06, 0xa7, 0x00, 0xfb, - 0x05, 0x77, 0x1e, 0xf5, 0x00, 0x00, 0x01, 0xfb, 0x06, 0x77, 0x49, 0xf1, - 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0xc2, 0xfb, 0x04, 0xa7, 0x07, 0x98, - 0x59, 0x42, 0x00, 0xeb, 0x81, 0x00, 0x50, 0xf8, 0x60, 0xcf, 0x40, 0x6e, - 0xcc, 0xf1, 0x00, 0x01, 0xdd, 0xe9, 0x02, 0x45, 0xc2, 0xfb, 0x01, 0xa7, - 0x40, 0x42, 0xd0, 0x46, 0xb9, 0x46, 0xc1, 0x17, 0xa4, 0xfb, 0x00, 0xa7, - 0x04, 0xfb, 0x01, 0x77, 0x05, 0xfb, 0x00, 0x77, 0x4d, 0x46, 0x18, 0xeb, - 0x0a, 0x04, 0x7d, 0x41, 0xdd, 0xe9, 0x04, 0xa7, 0x71, 0x42, 0xc2, 0xfb, - 0x01, 0xa7, 0xcd, 0xe9, 0x00, 0xa7, 0x4f, 0xea, 0xec, 0x71, 0xdd, 0xe9, - 0x02, 0xa7, 0xaa, 0xfb, 0x0c, 0x6b, 0x0a, 0xfb, 0x01, 0xbb, 0x07, 0xfb, - 0x0c, 0xbb, 0xdd, 0xe9, 0x00, 0x17, 0x11, 0xeb, 0x06, 0x0a, 0x47, 0xeb, - 0x0b, 0x07, 0xc2, 0xfb, 0x00, 0xa7, 0x4f, 0xea, 0xda, 0x50, 0x40, 0xea, - 0x47, 0x21, 0x21, 0x48, 0xff, 0x15, 0xa0, 0xfb, 0x01, 0x89, 0x00, 0xfb, - 0x07, 0x99, 0x4f, 0xea, 0xd8, 0x50, 0x40, 0xea, 0x49, 0x21, 0x08, 0x98, - 0xdf, 0xf8, 0x6c, 0xa0, 0x40, 0xf8, 0x33, 0x10, 0xe4, 0x0d, 0x44, 0xea, - 0x45, 0x24, 0xed, 0x15, 0xaa, 0xfb, 0x04, 0x01, 0x0a, 0xfb, 0x05, 0x11, - 0xc0, 0x0d, 0x40, 0xea, 0x41, 0x20, 0x08, 0x99, 0x01, 0xeb, 0xc3, 0x01, - 0x5b, 0x1c, 0x48, 0x60, 0x12, 0x49, 0x13, 0x48, 0x81, 0xfb, 0x02, 0x45, - 0xc0, 0xfb, 0x0e, 0x45, 0x06, 0x46, 0xce, 0xf1, 0x00, 0x00, 0x81, 0xfb, - 0x00, 0x01, 0xc6, 0xfb, 0x02, 0x01, 0xc0, 0x0d, 0xe4, 0x0d, 0x18, 0x2b, - 0x40, 0xea, 0x41, 0x22, 0x44, 0xea, 0x45, 0x2e, 0xff, 0xf4, 0x6a, 0xaf, - 0x07, 0x99, 0x08, 0x98, 0x09, 0xb0, 0xbd, 0xe8, 0xf0, 0x4f, 0xbb, 0xe6, - 0x7a, 0x82, 0x5a, 0x00, 0x86, 0x7d, 0xa5, 0xff, 0xfc, 0x20, 0x21, 0x00, - 0x75, 0xa3, 0x7b, 0x00, 0xab, 0xaa, 0x02, 0x00, 0x15, 0xb5, 0x10, 0x00, - 0xaa, 0xe7, 0x7e, 0x00, 0x00, 0x01, 0x18, 0x19, 0x0c, 0x0d, 0x24, 0x25, - 0x06, 0x07, 0x1e, 0x1f, 0x12, 0x13, 0x2a, 0x2b, 0x2d, 0xe9, 0xf0, 0x4f, - 0x04, 0x46, 0x8b, 0xb0, 0x00, 0x20, 0x20, 0x77, 0x04, 0xf1, 0x1d, 0x05, - 0x60, 0x69, 0x00, 0xf1, 0x68, 0x01, 0x00, 0x1d, 0x07, 0x90, 0x06, 0x91, - 0x04, 0xf5, 0xe8, 0x70, 0x02, 0x90, 0x04, 0xf5, 0x24, 0x70, 0x01, 0x90, - 0x04, 0xf1, 0x50, 0x00, 0x0a, 0x90, 0x01, 0x20, 0xa1, 0x68, 0x46, 0x42, - 0x01, 0xeb, 0x80, 0x02, 0x01, 0xeb, 0x86, 0x01, 0x13, 0x6e, 0xd1, 0xf8, - 0xc0, 0x60, 0x16, 0x66, 0xc1, 0xf8, 0xc0, 0x30, 0x40, 0x1c, 0xd2, 0xf8, - 0x20, 0x31, 0xd1, 0xf8, 0x80, 0x61, 0xc2, 0xf8, 0x20, 0x61, 0x0c, 0x28, - 0xc1, 0xf8, 0x80, 0x31, 0xe8, 0xdb, 0x00, 0x20, 0x28, 0x70, 0x01, 0x26, - 0x02, 0x99, 0x08, 0x60, 0x4f, 0xf0, 0x42, 0x58, 0x01, 0x99, 0x08, 0x60, - 0x20, 0x69, 0xf0, 0x40, 0x00, 0xf0, 0x01, 0x00, 0x70, 0x55, 0xa7, 0x68, - 0x57, 0xf8, 0x26, 0x00, 0xf4, 0xf7, 0x02, 0xf9, 0x00, 0xf0, 0x42, 0xfa, - 0x02, 0x99, 0x41, 0xf8, 0x26, 0x00, 0x07, 0xeb, 0x86, 0x00, 0xd0, 0xf8, - 0xc0, 0x00, 0xf4, 0xf7, 0xf7, 0xf8, 0x00, 0xf0, 0x37, 0xfa, 0x01, 0x99, - 0x41, 0xf8, 0x26, 0x00, 0xa9, 0x1b, 0xe0, 0x68, 0xf0, 0x40, 0x00, 0xf0, - 0x01, 0x00, 0x81, 0xf8, 0x30, 0x00, 0xa0, 0x68, 0x00, 0xeb, 0x86, 0x07, - 0x38, 0x6e, 0xf4, 0xf7, 0xe5, 0xf8, 0x00, 0xf0, 0x25, 0xfa, 0x02, 0x99, - 0x01, 0xeb, 0x86, 0x01, 0x08, 0x66, 0xd7, 0xf8, 0x20, 0x01, 0xf4, 0xf7, - 0xdb, 0xf8, 0x00, 0xf0, 0x1b, 0xfa, 0x01, 0x99, 0x01, 0xeb, 0x86, 0x01, - 0x76, 0x1c, 0x18, 0x2e, 0x08, 0x66, 0xc5, 0xdb, 0x01, 0x22, 0xdf, 0xf8, - 0x00, 0x08, 0x01, 0x46, 0x40, 0x08, 0x49, 0x08, 0xc3, 0x07, 0x5c, 0xbf, - 0x00, 0x23, 0x53, 0x55, 0xcb, 0x07, 0x03, 0xd4, 0xae, 0x1a, 0x00, 0x23, - 0x86, 0xf8, 0x30, 0x30, 0x52, 0x1c, 0x18, 0x2a, 0xf0, 0xdb, 0x00, 0x27, - 0x03, 0xe0, 0x00, 0x2f, 0x18, 0xbf, 0x18, 0x2f, 0x02, 0xd1, 0x4f, 0xf0, - 0xff, 0x39, 0x65, 0xe0, 0x78, 0x5d, 0x00, 0x28, 0x62, 0xd0, 0x01, 0x98, - 0x50, 0xf8, 0x27, 0xa0, 0x02, 0x98, 0x50, 0xf8, 0x27, 0xb0, 0x58, 0x46, - 0x59, 0x46, 0xf4, 0xf7, 0x51, 0xfa, 0x00, 0x90, 0x51, 0x46, 0x50, 0x46, - 0xf4, 0xf7, 0x4c, 0xfa, 0x00, 0x99, 0xf4, 0xf7, 0xad, 0xf9, 0xb9, 0xf1, - 0x00, 0x0f, 0x0e, 0xd5, 0x06, 0x46, 0x58, 0x46, 0x00, 0x21, 0xf4, 0xf7, - 0x21, 0xfa, 0xb9, 0x46, 0x08, 0xbf, 0x88, 0x46, 0x44, 0xd0, 0x50, 0x46, - 0x59, 0x46, 0xf4, 0xf7, 0xab, 0xf8, 0x80, 0x46, 0x3e, 0xe0, 0x00, 0x90, - 0x00, 0x21, 0x58, 0x46, 0xf4, 0xf7, 0x12, 0xfa, 0x08, 0xbf, 0x8a, 0x46, - 0x04, 0xd0, 0x50, 0x46, 0x59, 0x46, 0xf4, 0xf7, 0x9d, 0xf8, 0x82, 0x46, - 0x00, 0x98, 0x31, 0x46, 0xf4, 0xf7, 0x98, 0xf8, 0xf4, 0xf7, 0xca, 0xf9, - 0xdf, 0xf8, 0x58, 0x17, 0xf4, 0xf7, 0x84, 0xf9, 0x06, 0x46, 0x50, 0x46, - 0x41, 0x46, 0xf4, 0xf7, 0x0b, 0xf9, 0x80, 0x46, 0x30, 0x46, 0x31, 0x46, - 0xf4, 0xf7, 0x16, 0xfa, 0x06, 0x46, 0x40, 0x46, 0x00, 0xf0, 0xac, 0xf9, - 0x31, 0x46, 0xf4, 0xf7, 0x73, 0xf9, 0xa7, 0xeb, 0x09, 0x0b, 0x06, 0x46, - 0x0b, 0xfb, 0x0b, 0xf0, 0xf4, 0xf7, 0x60, 0xf8, 0x01, 0x46, 0x30, 0x46, - 0xf4, 0xf7, 0x76, 0xf8, 0xdf, 0xf8, 0x1c, 0x17, 0xf4, 0xf7, 0x08, 0xfb, - 0x03, 0xd8, 0x00, 0x20, 0x09, 0xf8, 0x05, 0x00, 0x78, 0x55, 0xb9, 0x46, - 0x00, 0x9e, 0xd0, 0x46, 0x7f, 0x1c, 0x30, 0x2f, 0x8f, 0xdb, 0x00, 0x20, - 0x00, 0x21, 0x4a, 0x5d, 0x01, 0x2a, 0x08, 0xbf, 0x40, 0x1c, 0x49, 0x1c, - 0x30, 0x29, 0xf8, 0xdb, 0xa1, 0x69, 0x89, 0x78, 0x88, 0x42, 0x03, 0xd2, - 0x20, 0x7f, 0x40, 0xf0, 0x02, 0x00, 0x20, 0x77, 0x00, 0x26, 0x00, 0x20, - 0x02, 0x21, 0x4a, 0x5d, 0x00, 0x2a, 0x1e, 0xbf, 0x6a, 0x1a, 0x92, 0xf8, - 0x30, 0x20, 0x00, 0x2a, 0x02, 0xd0, 0x01, 0x22, 0x8a, 0x40, 0x10, 0x43, - 0x49, 0x1c, 0x18, 0x29, 0xf1, 0xdb, 0x00, 0x21, 0x4f, 0xf4, 0x80, 0x72, - 0x80, 0x23, 0x4f, 0xf0, 0x17, 0x08, 0x18, 0x42, 0x1c, 0xbf, 0x1e, 0x43, - 0x49, 0x1c, 0x0c, 0x29, 0x07, 0xd0, 0x10, 0x42, 0x03, 0xd0, 0x16, 0x43, - 0x49, 0x1c, 0x0c, 0x29, 0x01, 0xd0, 0x5b, 0x10, 0x52, 0x00, 0xb8, 0xf1, - 0x01, 0x08, 0xee, 0xd1, 0x04, 0x29, 0x07, 0xda, 0x68, 0x78, 0x00, 0x28, - 0x1e, 0xbf, 0x95, 0xf8, 0x2f, 0x00, 0x00, 0x28, 0x46, 0xf0, 0x01, 0x06, - 0x00, 0x27, 0x4f, 0xf0, 0x01, 0x09, 0x19, 0xf8, 0x05, 0x00, 0x00, 0x28, - 0x1e, 0xbf, 0xa5, 0xeb, 0x09, 0x00, 0x90, 0xf8, 0x30, 0x00, 0x00, 0x28, - 0xc9, 0xf1, 0x30, 0x0a, 0x00, 0xf0, 0x93, 0x80, 0x01, 0x98, 0x02, 0x99, - 0x50, 0xf8, 0x29, 0x00, 0x51, 0xf8, 0x29, 0x10, 0xf4, 0xf7, 0x0c, 0xf8, - 0x00, 0x90, 0x02, 0x99, 0x01, 0x98, 0x51, 0xf8, 0x2a, 0x10, 0x50, 0xf8, - 0x2a, 0x00, 0xf4, 0xf7, 0x03, 0xf8, 0x83, 0x46, 0x4f, 0xf4, 0x80, 0x10, - 0x05, 0x90, 0x4f, 0xf0, 0x93, 0x40, 0x00, 0x99, 0xf4, 0xf7, 0x88, 0xf9, - 0xf4, 0xf7, 0xf2, 0xf9, 0x00, 0xf0, 0x14, 0xf9, 0x00, 0xf0, 0x1f, 0xf9, - 0x00, 0xf0, 0x20, 0xf9, 0x00, 0xf0, 0x22, 0xf9, 0x09, 0x90, 0x59, 0x46, - 0x00, 0xf0, 0x03, 0xf9, 0xf4, 0xf7, 0xe4, 0xf9, 0x00, 0xf0, 0x06, 0xf9, - 0x00, 0xf0, 0x11, 0xf9, 0x00, 0xf0, 0x12, 0xf9, 0x00, 0xf0, 0x14, 0xf9, - 0x08, 0x90, 0x01, 0x98, 0x50, 0xf8, 0x29, 0xb0, 0x02, 0x98, 0x50, 0xf8, - 0x29, 0x10, 0x08, 0x46, 0xf4, 0xf7, 0x66, 0xf9, 0x00, 0x90, 0x59, 0x46, - 0x58, 0x46, 0xf4, 0xf7, 0x61, 0xf9, 0x00, 0x99, 0xf4, 0xf7, 0xc2, 0xf8, - 0x00, 0x90, 0x01, 0x98, 0x50, 0xf8, 0x2a, 0xb0, 0x02, 0x98, 0x50, 0xf8, - 0x2a, 0x10, 0x08, 0x46, 0xf4, 0xf7, 0x54, 0xf9, 0x82, 0x46, 0x58, 0x46, - 0x59, 0x46, 0xf4, 0xf7, 0x4f, 0xf9, 0x51, 0x46, 0xf4, 0xf7, 0xb0, 0xf8, - 0x82, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0xee, 0xf8, 0x50, 0x46, 0xf4, 0xf7, - 0xeb, 0xf8, 0x08, 0x98, 0x09, 0x99, 0xf4, 0xf7, 0x31, 0xf8, 0x4f, 0xf0, - 0x7c, 0x51, 0xf4, 0xf7, 0x3d, 0xf9, 0x06, 0x99, 0x41, 0xf8, 0x29, 0x00, - 0x51, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0x36, 0xf9, 0xf4, 0xf7, 0xda, 0xf8, - 0xf4, 0xf7, 0xd8, 0xf8, 0x83, 0x46, 0x00, 0x98, 0xf4, 0xf7, 0xd4, 0xf8, - 0x50, 0x46, 0xf4, 0xf7, 0xd1, 0xf8, 0x07, 0x98, 0x40, 0xf8, 0x29, 0xb0, - 0x08, 0x99, 0x09, 0x98, 0xf4, 0xf7, 0x88, 0xf8, 0x4f, 0xf0, 0x7c, 0x51, - 0xf4, 0xf7, 0x20, 0xf9, 0x0a, 0x99, 0x41, 0xf8, 0x29, 0x00, 0x26, 0xfa, - 0x09, 0xf1, 0xc9, 0x07, 0x09, 0xd5, 0x41, 0x46, 0xf4, 0xf7, 0x7a, 0xf8, - 0x80, 0x46, 0x4f, 0xf0, 0x7e, 0x50, 0x39, 0x46, 0xf4, 0xf7, 0x74, 0xf8, - 0x07, 0x46, 0x09, 0xf1, 0x01, 0x09, 0xb9, 0xf1, 0x18, 0x0f, 0xff, 0xf6, - 0x5a, 0xaf, 0x38, 0x46, 0x00, 0x21, 0xf4, 0xf7, 0xe5, 0xf8, 0x08, 0xbf, - 0x00, 0x26, 0x04, 0xd0, 0x40, 0x46, 0x39, 0x46, 0xf3, 0xf7, 0x70, 0xff, - 0x06, 0x46, 0x60, 0x69, 0x06, 0x60, 0x4f, 0xf0, 0x01, 0x08, 0xc8, 0xf1, - 0x30, 0x0a, 0x18, 0xf8, 0x05, 0x00, 0x1a, 0xf8, 0x05, 0x10, 0x00, 0x28, - 0x02, 0xd0, 0x00, 0x29, 0x4d, 0xd1, 0x01, 0xe0, 0x00, 0x29, 0x4a, 0xd0, - 0x40, 0xb1, 0x02, 0x98, 0x50, 0xf8, 0x28, 0x70, 0x01, 0x98, 0x50, 0xf8, - 0x28, 0x00, 0x80, 0xf0, 0x00, 0x49, 0x07, 0xe0, 0x08, 0x00, 0x05, 0xd0, - 0x02, 0x98, 0x50, 0xf8, 0x2a, 0x70, 0x01, 0x98, 0x50, 0xf8, 0x2a, 0x90, - 0x48, 0x46, 0x39, 0x46, 0xf3, 0xf7, 0x48, 0xff, 0x01, 0x46, 0x06, 0x98, - 0x40, 0xf8, 0x28, 0x10, 0x00, 0xf0, 0x59, 0xf8, 0xf4, 0xf7, 0x3a, 0xf9, - 0x00, 0xf0, 0x5c, 0xf8, 0x00, 0xf0, 0x67, 0xf8, 0x00, 0xf0, 0x68, 0xf8, - 0x00, 0xf0, 0x6a, 0xf8, 0x01, 0x46, 0x06, 0x98, 0x40, 0xf8, 0x28, 0x10, - 0x18, 0xf8, 0x05, 0x00, 0x18, 0xb1, 0x30, 0x46, 0xf4, 0xf7, 0x20, 0xf8, - 0x06, 0xe0, 0x1a, 0xf8, 0x05, 0x00, 0x30, 0xb1, 0x08, 0x46, 0x31, 0x46, - 0xf3, 0xf7, 0xa4, 0xff, 0x06, 0x99, 0x41, 0xf8, 0x28, 0x00, 0x38, 0x46, - 0x00, 0xf0, 0x45, 0xf8, 0x82, 0x46, 0x48, 0x46, 0x49, 0x46, 0xf4, 0xf7, - 0xa9, 0xf8, 0x51, 0x46, 0xf4, 0xf7, 0x0a, 0xf8, 0xf4, 0xf7, 0x4a, 0xf8, - 0x07, 0x99, 0x41, 0xf8, 0x28, 0x00, 0x08, 0xf1, 0x01, 0x08, 0xb8, 0xf1, - 0x18, 0x0f, 0xa2, 0xdb, 0xa0, 0x69, 0x01, 0x90, 0x04, 0xf5, 0x88, 0x73, - 0x04, 0xf5, 0x54, 0x70, 0x00, 0x90, 0x04, 0xf1, 0x50, 0x02, 0x60, 0x69, - 0x04, 0xf1, 0x1d, 0x01, 0x00, 0xf0, 0x36, 0xf8, 0x00, 0x24, 0x07, 0x98, - 0x50, 0xf8, 0x24, 0x20, 0x10, 0x46, 0x00, 0x21, 0xf4, 0xf7, 0x66, 0xf8, - 0x4f, 0xf0, 0x7e, 0x50, 0x1c, 0xbf, 0x11, 0x46, 0xf3, 0xf7, 0xf2, 0xfe, - 0x07, 0x99, 0x41, 0xf8, 0x24, 0x00, 0x64, 0x1c, 0x19, 0x2c, 0xec, 0xdb, - 0x0b, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x4f, 0xf4, 0x80, 0x10, 0x05, 0x90, - 0x4f, 0xf0, 0x93, 0x40, 0xf4, 0xf7, 0x70, 0xb8, 0x04, 0x90, 0x03, 0xab, - 0x00, 0x20, 0x03, 0x90, 0x05, 0xaa, 0x04, 0xa9, 0x8b, 0xe1, 0x39, 0x46, - 0xf4, 0xf7, 0x66, 0xb8, 0x41, 0x46, 0xf4, 0xf7, 0x63, 0xb8, 0x03, 0x98, - 0xf3, 0xf7, 0xb8, 0xbe, 0x4f, 0xf0, 0x56, 0x51, 0xf4, 0xf7, 0x5c, 0xb8, - 0xdf, 0xf8, 0xd0, 0x13, 0xf4, 0xf7, 0x58, 0xb8, 0x2d, 0xe9, 0xf0, 0x4f, - 0x9d, 0xb0, 0x0c, 0x46, 0x00, 0xf1, 0x68, 0x01, 0x00, 0x1d, 0x02, 0x91, - 0x01, 0x90, 0x90, 0x46, 0x9a, 0x46, 0x00, 0x20, 0x00, 0x21, 0x48, 0xf8, - 0x20, 0x10, 0x4a, 0xf8, 0x20, 0x10, 0x40, 0x1c, 0x30, 0x28, 0xf8, 0xdb, - 0x01, 0x20, 0x02, 0x99, 0x51, 0xf8, 0x20, 0x10, 0x81, 0xf0, 0x00, 0x41, - 0x48, 0xf8, 0x20, 0x10, 0x41, 0x42, 0x02, 0x9a, 0x52, 0xf8, 0x20, 0x20, - 0x08, 0xeb, 0x81, 0x03, 0x0a, 0xeb, 0x81, 0x01, 0xc3, 0xf8, 0xc0, 0x20, - 0x01, 0x9a, 0x52, 0xf8, 0x20, 0x20, 0x4a, 0xf8, 0x20, 0x20, 0x01, 0x9a, - 0x52, 0xf8, 0x20, 0x20, 0xc1, 0xf8, 0xc0, 0x20, 0x40, 0x1c, 0x18, 0x28, - 0xe1, 0xdb, 0x4f, 0xf0, 0x18, 0x0b, 0x01, 0x20, 0x01, 0x5d, 0x01, 0x29, - 0x1e, 0xbf, 0x21, 0x1a, 0x91, 0xf8, 0x30, 0x10, 0x01, 0x29, 0x01, 0xd1, - 0x83, 0x46, 0x02, 0xe0, 0x40, 0x1c, 0x18, 0x28, 0xf2, 0xdb, 0x60, 0x78, - 0x00, 0x28, 0x1c, 0xbf, 0x94, 0xf8, 0x2f, 0x10, 0x00, 0x29, 0x21, 0xd1, - 0x01, 0x28, 0x04, 0xbf, 0x94, 0xf8, 0x2f, 0x10, 0x00, 0x29, 0x03, 0xd1, - 0x02, 0x20, 0x84, 0xf8, 0x2f, 0x00, 0x17, 0xe0, 0x00, 0x28, 0x04, 0xbf, - 0x94, 0xf8, 0x2f, 0x00, 0x01, 0x28, 0x02, 0xd1, 0x02, 0x20, 0x60, 0x70, - 0x0e, 0xe0, 0x02, 0x20, 0x60, 0x70, 0x01, 0x98, 0x50, 0xf8, 0x2b, 0x00, - 0xca, 0xf8, 0x04, 0x00, 0x02, 0x20, 0x84, 0xf8, 0x2f, 0x00, 0x01, 0x98, - 0x50, 0xf8, 0x2b, 0x00, 0xca, 0xf8, 0xbc, 0x00, 0x05, 0x20, 0x26, 0x9f, - 0x00, 0xf0, 0x00, 0xf9, 0x00, 0xf0, 0xf9, 0xf8, 0x00, 0x26, 0x07, 0xf1, - 0x84, 0x05, 0x4f, 0xf0, 0x7e, 0x59, 0x03, 0xe0, 0x18, 0x2e, 0x18, 0xd0, - 0x18, 0x2e, 0x01, 0xda, 0x3e, 0x60, 0x02, 0xe0, 0xc6, 0xf1, 0x30, 0x00, - 0x38, 0x60, 0xc5, 0xf8, 0x00, 0x90, 0xc5, 0xf8, 0x04, 0x90, 0x30, 0x5d, - 0x28, 0xb1, 0x5a, 0xf8, 0x26, 0x00, 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0x90, - 0x03, 0xe0, 0xc5, 0xf8, 0x08, 0x90, 0xac, 0x48, 0xe8, 0x60, 0x00, 0xf0, - 0xe3, 0xf8, 0x76, 0x1c, 0x30, 0x2e, 0xe1, 0xdb, 0xdd, 0xf8, 0x9c, 0xa0, - 0x9a, 0xf9, 0x00, 0x60, 0xba, 0x68, 0x00, 0x2e, 0x3a, 0xd4, 0x96, 0x42, - 0x38, 0xd2, 0x00, 0x20, 0x00, 0x21, 0x0d, 0xf1, 0x0c, 0x0c, 0x10, 0xe0, - 0xb1, 0x42, 0x18, 0xbf, 0xb2, 0x42, 0x07, 0xd0, 0x03, 0xfb, 0x01, 0x23, - 0x07, 0xeb, 0x83, 0x03, 0xdb, 0x68, 0x4c, 0xf8, 0x20, 0x30, 0x40, 0x1c, - 0x52, 0x1c, 0xbb, 0x68, 0x9a, 0x42, 0xef, 0xd3, 0x49, 0x1c, 0xba, 0x68, - 0x91, 0x42, 0x38, 0xbf, 0x00, 0x22, 0xf6, 0xd3, 0x70, 0x1c, 0x04, 0xe0, - 0x07, 0xeb, 0x80, 0x01, 0x40, 0x1c, 0x0a, 0x6f, 0xca, 0x66, 0xb9, 0x68, - 0x88, 0x42, 0xf7, 0xd3, 0x4a, 0x1e, 0x07, 0xf1, 0x70, 0x01, 0x03, 0xa8, - 0xfe, 0xf7, 0xf0, 0xfe, 0xb8, 0x68, 0x03, 0xe0, 0x07, 0xeb, 0x80, 0x01, - 0xca, 0x6e, 0x0a, 0x67, 0x40, 0x1e, 0x86, 0x42, 0xf8, 0xd3, 0x07, 0xeb, - 0x86, 0x01, 0x00, 0x20, 0x08, 0x67, 0x01, 0xe0, 0x00, 0xf0, 0x8b, 0xf8, - 0x02, 0x20, 0x00, 0x90, 0x9a, 0xf8, 0x01, 0x30, 0xba, 0x68, 0x01, 0x98, - 0x07, 0xf1, 0x70, 0x01, 0xfe, 0xf7, 0x90, 0xfe, 0x00, 0x26, 0x0d, 0xe0, - 0x30, 0x5d, 0x02, 0x28, 0x04, 0xbf, 0x00, 0x20, 0x30, 0x55, 0xa0, 0x1b, - 0x90, 0xf8, 0x30, 0x10, 0x02, 0x29, 0x04, 0xbf, 0x00, 0x21, 0x80, 0xf8, - 0x30, 0x10, 0x76, 0x1c, 0x5e, 0x45, 0xef, 0xdb, 0x60, 0x78, 0x00, 0x28, - 0x1c, 0xbf, 0x94, 0xf8, 0x2f, 0x00, 0x00, 0x28, 0x1d, 0xd1, 0xab, 0xf1, - 0x01, 0x06, 0x18, 0xe0, 0x96, 0xfb, 0xfb, 0xf0, 0xf3, 0xf7, 0xac, 0xfd, - 0x02, 0x99, 0x51, 0xf8, 0x2b, 0x10, 0xf3, 0xf7, 0x4f, 0xff, 0x02, 0x21, - 0x31, 0x55, 0x02, 0x22, 0x80, 0xf0, 0x00, 0x41, 0x48, 0xf8, 0x26, 0x10, - 0x71, 0x42, 0x0b, 0x19, 0x08, 0xeb, 0x81, 0x01, 0x83, 0xf8, 0x30, 0x20, - 0xc1, 0xf8, 0xc0, 0x00, 0x76, 0x1e, 0x01, 0x2e, 0xe4, 0xda, 0x05, 0x20, - 0x00, 0xf0, 0x52, 0xf8, 0x00, 0xf0, 0x4b, 0xf8, 0x00, 0x26, 0x03, 0xe0, - 0x18, 0x2e, 0x19, 0xd0, 0x18, 0x2e, 0x03, 0xda, 0x3e, 0x60, 0x5d, 0x48, - 0x28, 0x60, 0x04, 0xe0, 0xc6, 0xf1, 0x30, 0x00, 0x38, 0x60, 0xc5, 0xf8, - 0x00, 0x90, 0xc5, 0xf8, 0x04, 0x90, 0x30, 0x5d, 0x28, 0xb1, 0x58, 0xf8, - 0x26, 0x00, 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0x90, 0x02, 0xe0, 0xa8, 0x60, - 0x56, 0x48, 0xe8, 0x60, 0x00, 0xf0, 0x38, 0xf8, 0x76, 0x1c, 0x30, 0x2e, - 0xe0, 0xdb, 0xba, 0x68, 0x00, 0xf0, 0x21, 0xf8, 0x00, 0x20, 0x38, 0x67, - 0x07, 0xf1, 0x70, 0x01, 0x03, 0x20, 0x00, 0x90, 0x9a, 0xf8, 0x01, 0x30, - 0xba, 0x68, 0x02, 0x98, 0xfe, 0xf7, 0x24, 0xfe, 0x00, 0x20, 0x0d, 0xe0, - 0x01, 0x5d, 0x02, 0x29, 0x04, 0xbf, 0x00, 0x21, 0x01, 0x55, 0x21, 0x1a, - 0x91, 0xf8, 0x30, 0x20, 0x02, 0x2a, 0x04, 0xbf, 0x00, 0x22, 0x81, 0xf8, - 0x30, 0x20, 0x40, 0x1c, 0x58, 0x45, 0xef, 0xdb, 0x1d, 0xb0, 0xbd, 0xe8, - 0xf0, 0x8f, 0x07, 0xf1, 0x70, 0x01, 0x07, 0xf1, 0x0c, 0x00, 0xfe, 0xf7, - 0x4f, 0xbe, 0x14, 0x21, 0x07, 0xf1, 0x70, 0x00, 0xf4, 0xf7, 0x98, 0xbd, - 0xb8, 0x60, 0x64, 0x21, 0x07, 0xf1, 0x0c, 0x00, 0xf4, 0xf7, 0x92, 0xbd, - 0x01, 0x20, 0x78, 0x60, 0x38, 0x46, 0xfe, 0xf7, 0x2a, 0xbd, 0x2d, 0xe9, - 0xf0, 0x43, 0x01, 0x24, 0x01, 0x26, 0x4f, 0xf0, 0xff, 0x39, 0xa8, 0xb1, - 0x1f, 0x68, 0xb7, 0xf5, 0x80, 0x2f, 0xc8, 0xbf, 0xa7, 0xf5, 0x00, 0x26, - 0x04, 0xdc, 0x17, 0xf5, 0x80, 0x2f, 0x03, 0xda, 0x07, 0xf5, 0x00, 0x26, - 0x1e, 0x60, 0x4e, 0x46, 0x2c, 0x4f, 0x17, 0x60, 0x00, 0x27, 0x0f, 0x60, - 0x1f, 0x68, 0x00, 0x2f, 0x13, 0xd5, 0x11, 0xe0, 0x00, 0x26, 0x1e, 0x60, - 0x17, 0x68, 0x00, 0x2f, 0x09, 0xd5, 0x0e, 0x68, 0x00, 0x2e, 0x54, 0xbf, - 0x01, 0x26, 0x4e, 0x46, 0x7f, 0x42, 0x17, 0x60, 0x0f, 0x68, 0x7f, 0x42, - 0x0f, 0x60, 0x0f, 0x68, 0x00, 0x2f, 0x00, 0xd4, 0x4c, 0x46, 0x00, 0x27, - 0x0f, 0xf2, 0x7c, 0x0c, 0xd2, 0xf8, 0x00, 0xe0, 0x0d, 0x68, 0x4e, 0xfa, - 0x07, 0xf8, 0x3d, 0x41, 0x05, 0xfb, 0x14, 0xee, 0xc2, 0xf8, 0x00, 0xe0, - 0xd1, 0xf8, 0x00, 0xe0, 0x08, 0xfb, 0x04, 0xee, 0xc1, 0xf8, 0x00, 0xe0, - 0x5c, 0xf8, 0x27, 0x50, 0xd3, 0xf8, 0x00, 0xe0, 0x05, 0xfb, 0x14, 0xee, - 0xc3, 0xf8, 0x00, 0xe0, 0x01, 0x24, 0x18, 0xb1, 0xbe, 0xf1, 0x00, 0x0f, - 0x04, 0xd5, 0x02, 0xe0, 0x0d, 0x68, 0x00, 0x2d, 0x00, 0xd4, 0x4c, 0x46, - 0x7f, 0x1c, 0x13, 0x2f, 0xda, 0xdb, 0x10, 0x68, 0x70, 0x43, 0x10, 0x60, - 0x08, 0x68, 0x70, 0x43, 0x08, 0x60, 0x18, 0x68, 0x00, 0xeb, 0xc6, 0x40, - 0x18, 0x60, 0xbd, 0xe8, 0xf0, 0x83, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x00, - 0x00, 0x00, 0x80, 0xbf, 0xad, 0xc5, 0x27, 0x38, 0xdb, 0x0f, 0xc9, 0x40, - 0x95, 0xbf, 0xd6, 0x33, 0x4f, 0xb7, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x40, 0x2e, 0x01, 0x00, 0xb4, 0x9f, 0x00, 0x00, 0x11, 0x51, 0x00, 0x00, - 0xb1, 0x28, 0x00, 0x00, 0x5d, 0x14, 0x00, 0x00, 0x2f, 0x0a, 0x00, 0x00, - 0x18, 0x05, 0x00, 0x00, 0x8c, 0x02, 0x00, 0x00, 0x46, 0x01, 0x00, 0x00, - 0xa3, 0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, - 0x14, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, - 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, - 0x70, 0x47, 0x38, 0xb5, 0xdf, 0xf8, 0x34, 0x04, 0x40, 0x89, 0xc0, 0xf3, - 0x81, 0x04, 0xc0, 0xf3, 0x01, 0x10, 0x08, 0xb1, 0x44, 0xf0, 0x04, 0x04, - 0x0c, 0xb9, 0x00, 0x20, 0x32, 0xbd, 0xdf, 0xf8, 0x20, 0x04, 0x05, 0x78, - 0x01, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xf2, 0xf7, 0x26, 0xf9, 0x20, 0x46, - 0xef, 0xf7, 0xca, 0xff, 0x08, 0xb9, 0x04, 0x20, 0x32, 0xbd, 0x20, 0x46, - 0x00, 0xf0, 0xbd, 0xf8, 0x04, 0x46, 0x29, 0x46, 0x4f, 0xf4, 0x82, 0x70, - 0xf2, 0xf7, 0x17, 0xf9, 0x20, 0x46, 0x32, 0xbd, 0x2d, 0xe9, 0xf0, 0x4c, - 0x06, 0x46, 0x15, 0xb2, 0x6f, 0xf0, 0x02, 0x00, 0x85, 0x42, 0x0c, 0x46, - 0x1f, 0x46, 0xb8, 0xbf, 0x05, 0x46, 0x02, 0xdb, 0x04, 0x2d, 0xa8, 0xbf, - 0x03, 0x25, 0xd7, 0xe9, 0x00, 0xab, 0x0f, 0x20, 0x00, 0x21, 0xa2, 0x00, - 0xf4, 0xf7, 0x82, 0xf8, 0x5b, 0x46, 0x2a, 0xea, 0x00, 0x0a, 0x23, 0xea, - 0x01, 0x0b, 0xe8, 0x1c, 0xc1, 0x17, 0xa2, 0x00, 0xf4, 0xf7, 0x78, 0xf8, - 0x4a, 0xea, 0x00, 0x00, 0x4b, 0xea, 0x01, 0x01, 0xc7, 0xe9, 0x00, 0x01, - 0x72, 0xb6, 0xdf, 0xf8, 0xa4, 0x03, 0x4f, 0xf6, 0xfe, 0x61, 0x01, 0x60, - 0x01, 0x60, 0x86, 0xf0, 0x01, 0x03, 0xdf, 0xf8, 0x98, 0x13, 0x0a, 0x78, - 0x1b, 0x01, 0x02, 0xf0, 0x8f, 0x02, 0x03, 0xf0, 0x70, 0x03, 0x1a, 0x43, - 0x0a, 0x70, 0x04, 0xf0, 0x0f, 0x03, 0x4a, 0x78, 0x02, 0xf0, 0xf0, 0x02, - 0x1a, 0x43, 0x4a, 0x70, 0x8d, 0x70, 0x00, 0x21, 0x01, 0x60, 0x62, 0xb6, - 0xbd, 0xe8, 0xf0, 0x8c, 0x2d, 0xe9, 0xf8, 0x4f, 0x90, 0x46, 0x01, 0xf0, - 0x04, 0x05, 0x72, 0xb6, 0xdf, 0xf8, 0x58, 0xa3, 0x4f, 0xf6, 0xfe, 0x69, - 0x80, 0x00, 0xca, 0xf8, 0x00, 0x90, 0x00, 0xf0, 0x1c, 0x00, 0xd4, 0x4f, - 0xd4, 0x4c, 0xca, 0xf8, 0x00, 0x90, 0x01, 0xf0, 0x03, 0x01, 0x01, 0x43, - 0x39, 0x70, 0x40, 0xea, 0x95, 0x00, 0x20, 0x70, 0x00, 0x20, 0xca, 0xf8, - 0x00, 0x00, 0x62, 0xb6, 0xce, 0x49, 0xf3, 0xf7, 0x91, 0xfb, 0x97, 0xf8, - 0x00, 0xb0, 0x26, 0x78, 0xf1, 0xf7, 0xc9, 0xf9, 0x08, 0xb1, 0x01, 0x26, - 0x0d, 0xe0, 0x03, 0x21, 0x1b, 0xea, 0x01, 0x0f, 0x03, 0xd1, 0xf0, 0x07, - 0x01, 0xd4, 0x00, 0x26, 0x05, 0xe0, 0x00, 0x20, 0xf3, 0xf7, 0x96, 0xfb, - 0x00, 0x28, 0xea, 0xd0, 0x02, 0x26, 0x00, 0x20, 0xf3, 0xf7, 0x08, 0xfb, - 0x86, 0xbb, 0x72, 0xb6, 0xca, 0xf8, 0x00, 0x90, 0xca, 0xf8, 0x00, 0x90, - 0x00, 0x20, 0x41, 0x01, 0x39, 0x70, 0x39, 0x79, 0xfa, 0x78, 0xbb, 0x78, - 0x97, 0xf8, 0x01, 0xc0, 0x42, 0xea, 0x01, 0x21, 0x43, 0xea, 0x01, 0x21, - 0x4c, 0xea, 0x01, 0x21, 0x48, 0xf8, 0x20, 0x10, 0x40, 0x1c, 0x08, 0x28, - 0xed, 0xd3, 0x9d, 0xb1, 0x00, 0x21, 0x08, 0x20, 0x4a, 0x01, 0x22, 0x70, - 0x49, 0x1c, 0x22, 0x79, 0xe3, 0x78, 0xa5, 0x78, 0x67, 0x78, 0x43, 0xea, - 0x02, 0x22, 0x45, 0xea, 0x02, 0x22, 0x47, 0xea, 0x02, 0x22, 0x48, 0xf8, - 0x20, 0x20, 0x40, 0x1c, 0x0c, 0x28, 0xed, 0xd3, 0x00, 0x20, 0xca, 0xf8, - 0x00, 0x00, 0x62, 0xb6, 0x30, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, 0x2d, 0xe9, - 0xf0, 0x4f, 0xa9, 0xb0, 0x80, 0x46, 0x0b, 0xa8, 0x0f, 0xf2, 0xc0, 0x21, - 0x10, 0x22, 0xf6, 0xf7, 0xd9, 0xfc, 0x00, 0x20, 0x00, 0xf0, 0xe2, 0xf9, - 0x00, 0x21, 0x00, 0x20, 0xf0, 0xf7, 0xef, 0xf8, 0x00, 0xf0, 0xec, 0xf9, - 0x00, 0x25, 0x07, 0xae, 0xad, 0x55, 0x6d, 0x1c, 0x10, 0x2d, 0xfb, 0xd3, - 0x00, 0xf0, 0x44, 0xfa, 0x5f, 0xea, 0x00, 0x09, 0xfa, 0xd0, 0x00, 0x24, - 0xdf, 0xf8, 0x5c, 0xa2, 0x00, 0xf0, 0x39, 0xf9, 0x0a, 0xd5, 0x00, 0x25, - 0x0a, 0xf1, 0x30, 0x00, 0x00, 0xeb, 0xc4, 0x03, 0x00, 0x22, 0x00, 0xf0, - 0x37, 0xf9, 0x6d, 0x1c, 0x10, 0x2d, 0xf5, 0xd3, 0x0a, 0xeb, 0x84, 0x01, - 0x64, 0x1c, 0x6f, 0xf0, 0x00, 0x40, 0x06, 0x2c, 0x08, 0x66, 0xe9, 0xdb, - 0x00, 0xf0, 0x1f, 0xf9, 0x04, 0x00, 0x55, 0xd1, 0x01, 0x90, 0x0d, 0xf1, - 0x3c, 0x0b, 0x00, 0x20, 0x00, 0x90, 0x01, 0x98, 0x30, 0xb9, 0x00, 0x99, - 0x0f, 0xf2, 0x54, 0x20, 0x00, 0xeb, 0x41, 0x10, 0x03, 0x90, 0x24, 0xe0, - 0x15, 0xa8, 0x03, 0x90, 0x02, 0x20, 0x09, 0xf0, 0x01, 0x01, 0x49, 0x42, - 0x80, 0x4a, 0x11, 0x40, 0x81, 0xea, 0x59, 0x09, 0x00, 0x27, 0x3a, 0x1d, - 0x29, 0xfa, 0x07, 0xf1, 0x29, 0xfa, 0x02, 0xf3, 0x01, 0xf0, 0x0f, 0x01, - 0x03, 0xf0, 0x0f, 0x03, 0x8a, 0x5d, 0x9c, 0x5d, 0x8c, 0x55, 0x08, 0x37, - 0x9a, 0x55, 0x20, 0x2f, 0xef, 0xd3, 0x40, 0x1e, 0xe5, 0xd1, 0x00, 0x25, - 0x15, 0xa9, 0xa8, 0x5d, 0x21, 0xf8, 0x15, 0x00, 0x6d, 0x1c, 0x10, 0x2d, - 0xf9, 0xd3, 0x00, 0x25, 0x03, 0x98, 0x30, 0xf9, 0x15, 0x00, 0x02, 0x90, - 0x04, 0xaa, 0x00, 0x20, 0x6f, 0xf0, 0x00, 0x41, 0x4b, 0xf8, 0x20, 0x10, - 0x00, 0x21, 0x22, 0xf8, 0x10, 0x10, 0x40, 0x1c, 0x06, 0x28, 0xf5, 0xdb, - 0x00, 0x27, 0x00, 0x24, 0x00, 0xf0, 0xd9, 0xf8, 0x05, 0xd5, 0x00, 0xf0, - 0xcd, 0xf8, 0x02, 0x99, 0xfa, 0x1e, 0x00, 0xf0, 0xda, 0xf8, 0x64, 0x1c, - 0x06, 0x2c, 0xf3, 0xdb, 0x00, 0xf0, 0xc9, 0xf8, 0x04, 0x00, 0x06, 0xd0, - 0x00, 0xf0, 0x96, 0xf9, 0x00, 0x20, 0xf0, 0xf7, 0xc7, 0xf8, 0x20, 0x46, - 0xa4, 0xe0, 0x00, 0xeb, 0xd0, 0x71, 0x49, 0x10, 0x28, 0xfa, 0x01, 0xf2, - 0xd1, 0x07, 0x0b, 0xd5, 0x1d, 0xa9, 0x5b, 0xf8, 0x20, 0x20, 0x51, 0xf8, - 0x30, 0x10, 0x91, 0x42, 0x04, 0xda, 0x4b, 0xf8, 0x20, 0x10, 0x04, 0xa9, - 0x21, 0xf8, 0x10, 0x70, 0x40, 0x1c, 0x06, 0x28, 0xe9, 0xdb, 0x7f, 0x1c, - 0x07, 0x2f, 0xce, 0xd3, 0x00, 0xf0, 0xa9, 0xf8, 0x16, 0xd5, 0x04, 0xa8, - 0x0a, 0xeb, 0xc4, 0x07, 0x30, 0xf9, 0x14, 0x00, 0x02, 0x99, 0xc2, 0x1e, - 0x07, 0xf1, 0x30, 0x03, 0x00, 0xf0, 0xa5, 0xf8, 0x0a, 0xeb, 0x84, 0x03, - 0x5b, 0xf8, 0x24, 0x20, 0x18, 0x6e, 0x82, 0x42, 0x04, 0xda, 0xd7, 0xe9, - 0x0c, 0x01, 0xc7, 0xe9, 0x00, 0x01, 0x1a, 0x66, 0x64, 0x1c, 0x06, 0x2c, - 0xe2, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0x9d, 0xd3, 0x00, 0x98, 0x40, 0x1c, - 0x04, 0x28, 0x00, 0x90, 0xff, 0xf4, 0x69, 0xaf, 0x01, 0x98, 0x07, 0x28, - 0x41, 0xd2, 0x40, 0x1c, 0x01, 0x90, 0x0b, 0xa8, 0x01, 0x99, 0x00, 0xeb, - 0x41, 0x00, 0x00, 0x25, 0x00, 0x90, 0x00, 0x24, 0x00, 0xf0, 0x77, 0xf8, - 0x2d, 0xd5, 0x0a, 0xeb, 0xc4, 0x02, 0xd2, 0xe9, 0x00, 0x01, 0xaa, 0x00, - 0xfb, 0xf7, 0xfa, 0xfd, 0x00, 0xf0, 0x0f, 0x00, 0xc7, 0x1e, 0x3f, 0xb2, - 0x00, 0x2f, 0x09, 0xd4, 0x01, 0x2f, 0x0c, 0xda, 0x00, 0xf0, 0x68, 0xf9, - 0x00, 0xeb, 0xd0, 0x71, 0x49, 0x10, 0xb0, 0xeb, 0x41, 0x00, 0x04, 0xd0, - 0x00, 0x98, 0x30, 0xf8, 0x02, 0x0c, 0xc2, 0x19, 0x03, 0xe0, 0x00, 0x98, - 0x30, 0xf8, 0x02, 0x0c, 0x3a, 0x1a, 0x12, 0xb2, 0x04, 0x2a, 0xa8, 0xbf, - 0x03, 0x22, 0x04, 0xda, 0x12, 0xf1, 0x03, 0x0f, 0xb8, 0xbf, 0x6f, 0xf0, - 0x02, 0x02, 0x00, 0xf0, 0x41, 0xf8, 0x00, 0xf0, 0x4f, 0xf8, 0x64, 0x1c, - 0x06, 0x2c, 0xcb, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0xbf, 0xf4, 0x23, 0xaf, - 0xc5, 0xe7, 0x00, 0x25, 0x00, 0x24, 0x00, 0xf0, 0x3c, 0xf8, 0x0f, 0xd5, - 0x0a, 0xeb, 0xc4, 0x02, 0x00, 0xf0, 0x2e, 0xf8, 0xd2, 0xe9, 0x00, 0x01, - 0x1e, 0x46, 0xaa, 0x00, 0xfb, 0xf7, 0xbc, 0xfd, 0x00, 0xf0, 0x0f, 0x00, - 0xc2, 0x1e, 0x33, 0x46, 0x00, 0xf0, 0x32, 0xf8, 0x64, 0x1c, 0x06, 0x2c, - 0xe9, 0xdb, 0x6d, 0x1c, 0x10, 0x2d, 0xe5, 0xd3, 0x00, 0xf0, 0xf0, 0xf8, - 0x00, 0x20, 0xf0, 0xf7, 0x21, 0xf8, 0x00, 0x20, 0x29, 0xb0, 0xbd, 0xe8, - 0xf0, 0x8f, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0x04, 0x01, 0x00, 0x46, - 0x48, 0x00, 0x00, 0x50, 0xb0, 0x05, 0x00, 0x46, 0xb8, 0x05, 0x00, 0x46, - 0x48, 0x08, 0x00, 0x46, 0x20, 0xa1, 0x07, 0x00, 0xb0, 0xf0, 0x00, 0x20, - 0x01, 0x00, 0x00, 0xd0, 0x0a, 0xeb, 0xc4, 0x00, 0x00, 0xf1, 0x30, 0x03, - 0x70, 0x47, 0x1d, 0xaa, 0x41, 0x46, 0x04, 0x20, 0x34, 0xe6, 0x04, 0xeb, - 0xd4, 0x70, 0x40, 0x10, 0x28, 0xfa, 0x00, 0xf1, 0xc8, 0x07, 0x70, 0x47, - 0x29, 0x46, 0x20, 0x46, 0xe4, 0xe5, 0x00, 0x00, 0x04, 0x00, 0xfc, 0xff, - 0xfe, 0xff, 0x02, 0x00, 0x01, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, - 0x06, 0x00, 0x07, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, - 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, - 0x0d, 0x00, 0x0c, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x08, 0x00, - 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x08, 0x00, 0x09, 0x00, 0x0a, 0x00, 0x0b, 0x00, - 0x0c, 0x00, 0x0d, 0x00, 0x0e, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x01, 0x00, - 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, - 0x07, 0x00, 0x06, 0x00, 0x05, 0x00, 0x04, 0x00, 0x03, 0x00, 0x02, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0d, 0x00, 0x0c, 0x00, - 0x0b, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, - 0x04, 0x00, 0x06, 0x00, 0x08, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0e, 0x00, - 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0b, 0x00, - 0x0d, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0x0b, 0x00, 0x09, 0x00, - 0x07, 0x00, 0x05, 0x00, 0x03, 0x00, 0x01, 0x00, 0x0e, 0x00, 0x0c, 0x00, - 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x03, 0x00, 0x05, 0x00, 0x07, 0x00, 0x09, 0x00, 0x0b, 0x00, - 0x0d, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x06, 0x00, - 0x08, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x0c, 0x00, - 0x0a, 0x00, 0x08, 0x00, 0x06, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0f, 0x00, 0x0d, 0x00, 0x0b, 0x00, 0x09, 0x00, 0x07, 0x00, 0x05, 0x00, - 0x03, 0x00, 0x01, 0x00, 0x10, 0xb5, 0x04, 0x46, 0x04, 0x48, 0xc0, 0x46, - 0xc0, 0x46, 0x00, 0x21, 0x01, 0x70, 0x03, 0x48, 0xc0, 0x46, 0xc0, 0x46, - 0x04, 0x60, 0x10, 0xbd, 0x90, 0xbc, 0x00, 0x20, 0x94, 0xbc, 0x00, 0x20, - 0x38, 0xb5, 0x2c, 0x48, 0x01, 0x78, 0x80, 0x7d, 0xc0, 0x07, 0x03, 0xd5, - 0x48, 0x07, 0x58, 0xbf, 0x08, 0x22, 0x00, 0xd5, 0x04, 0x22, 0x0c, 0x21, - 0x4f, 0xf4, 0xb6, 0x60, 0xef, 0xf7, 0xa6, 0xfc, 0x40, 0x22, 0x00, 0xf0, - 0x41, 0xf8, 0x40, 0x22, 0x00, 0xf0, 0x39, 0xf8, 0x40, 0x22, 0x00, 0xf0, - 0x31, 0xf8, 0x21, 0x4c, 0x21, 0x4d, 0x20, 0x78, 0x28, 0x70, 0x40, 0x22, - 0x00, 0xf0, 0x25, 0xf8, 0x60, 0x78, 0x68, 0x70, 0x40, 0x22, 0xbd, 0xe8, - 0x38, 0x40, 0x40, 0x21, 0x40, 0xf2, 0xe1, 0x50, 0xef, 0xf7, 0x8c, 0xbc, - 0x80, 0xb5, 0x00, 0x22, 0x00, 0xf0, 0x26, 0xf8, 0x00, 0x22, 0x00, 0xf0, - 0x1e, 0xf8, 0x00, 0x22, 0x00, 0xf0, 0x16, 0xf8, 0x00, 0x22, 0x00, 0xf0, - 0x0e, 0xf8, 0x00, 0x22, 0x40, 0x21, 0x40, 0xf2, 0xe1, 0x50, 0xef, 0xf7, - 0x79, 0xfc, 0xbd, 0xe8, 0x08, 0x40, 0x00, 0x22, 0x0c, 0x21, 0x4f, 0xf4, - 0xb6, 0x60, 0xef, 0xf7, 0x71, 0xbc, 0x40, 0x21, 0x4f, 0xf4, 0xbc, 0x60, - 0xef, 0xf7, 0x6c, 0xbc, 0x40, 0x21, 0x40, 0xf2, 0xdf, 0x50, 0xef, 0xf7, - 0x67, 0xbc, 0x40, 0x21, 0x40, 0xf2, 0xde, 0x50, 0xef, 0xf7, 0x62, 0xbc, - 0x40, 0x21, 0x40, 0xf2, 0xdd, 0x50, 0xef, 0xf7, 0x5d, 0xbc, 0x00, 0x00, - 0x02, 0x01, 0x00, 0x46, 0xe0, 0x05, 0x00, 0x46, 0x9a, 0xf3, 0x00, 0x20, - 0xf8, 0xb5, 0x34, 0x4f, 0x38, 0x46, 0xc0, 0x46, 0xc0, 0x46, 0x04, 0x46, - 0x38, 0x1d, 0xc0, 0x46, 0xc0, 0x46, 0x05, 0x46, 0x07, 0xf1, 0x08, 0x00, - 0xc0, 0x46, 0xc0, 0x46, 0x06, 0x46, 0x07, 0xf1, 0x0c, 0x00, 0xc0, 0x46, - 0xc0, 0x46, 0x23, 0x78, 0x2b, 0x49, 0x2c, 0x4a, 0x00, 0x2b, 0x40, 0xd1, - 0x2b, 0x68, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x08, 0x27, 0x02, 0xfb, - 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, - 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, - 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, 0x03, 0x13, 0x2b, 0x60, 0x02, 0xfb, - 0x03, 0x13, 0x2b, 0x60, 0x03, 0x46, 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, - 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, 0x7f, 0x1e, - 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, - 0x43, 0xf8, 0x04, 0xcb, 0xd5, 0xf8, 0x00, 0xc0, 0x02, 0xfb, 0x0c, 0x1c, - 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, 0xd5, 0xf8, 0x00, 0xc0, - 0x02, 0xfb, 0x0c, 0x1c, 0xc5, 0xf8, 0x00, 0xc0, 0x43, 0xf8, 0x04, 0xcb, - 0xdd, 0xd1, 0xc3, 0x6f, 0x33, 0x60, 0x01, 0x23, 0x23, 0x70, 0x2b, 0x68, - 0x02, 0xfb, 0x03, 0x11, 0x29, 0x60, 0x31, 0x78, 0x01, 0xf0, 0x1f, 0x01, - 0x50, 0xf8, 0x21, 0x20, 0x32, 0x60, 0x2a, 0x68, 0x40, 0xf8, 0x21, 0x20, - 0x30, 0x68, 0x80, 0x00, 0x80, 0x08, 0xf2, 0xbd, 0x90, 0xbc, 0x00, 0x20, - 0x5f, 0xf3, 0x6e, 0x3c, 0x0d, 0x66, 0x19, 0x00, 0x00, 0xb5, 0x32, 0x38, - 0xa1, 0xfb, 0x00, 0x01, 0xdf, 0xf8, 0x98, 0x24, 0x00, 0x23, 0xf3, 0xf7, - 0x01, 0xfe, 0x80, 0xb2, 0x00, 0xbd, 0x10, 0xb5, 0xdf, 0xf8, 0x8c, 0x44, - 0x61, 0x89, 0x00, 0x20, 0xc1, 0xf3, 0x81, 0x01, 0x11, 0xb1, 0x00, 0xf0, - 0x1b, 0xf8, 0x28, 0xb9, 0x61, 0x89, 0xc1, 0xf3, 0x82, 0x11, 0x11, 0xb1, - 0x00, 0xf0, 0x85, 0xf9, 0x88, 0xb9, 0x61, 0x89, 0xc1, 0xf3, 0x01, 0x11, - 0x69, 0xb1, 0xf1, 0xf7, 0x0a, 0xf9, 0x21, 0x6c, 0xff, 0xf7, 0xda, 0xff, - 0xdf, 0xf8, 0x5c, 0x14, 0x08, 0x80, 0x08, 0x20, 0xf4, 0xf7, 0xae, 0xfa, - 0xbd, 0xe8, 0x10, 0x40, 0xb5, 0xe0, 0x10, 0xbd, 0x00, 0x21, 0x00, 0x20, - 0x2d, 0xe9, 0xf8, 0x4f, 0xef, 0xf7, 0xfb, 0xfd, 0x00, 0x22, 0x03, 0x21, - 0x40, 0xf6, 0x84, 0x50, 0xef, 0xf7, 0xaa, 0xfb, 0x10, 0x21, 0x4f, 0xf4, - 0xc6, 0x60, 0xef, 0xf7, 0x9b, 0xfb, 0x40, 0x21, 0x40, 0xf2, 0x31, 0x60, - 0xef, 0xf7, 0x96, 0xfb, 0x00, 0x21, 0x40, 0xf2, 0x32, 0x60, 0xef, 0xf7, - 0x91, 0xfb, 0x33, 0x21, 0x40, 0xf2, 0x33, 0x60, 0xef, 0xf7, 0x8c, 0xfb, - 0x00, 0xf0, 0x81, 0xf8, 0x00, 0xf0, 0x7a, 0xf8, 0x00, 0xf0, 0x73, 0xf8, - 0x32, 0x21, 0x40, 0xf2, 0x34, 0x60, 0xef, 0xf7, 0x81, 0xfb, 0x40, 0xf2, - 0x35, 0x65, 0x1b, 0x22, 0x1f, 0x21, 0x28, 0x46, 0xef, 0xf7, 0x84, 0xfb, - 0x40, 0xf2, 0x36, 0x66, 0x13, 0x21, 0x00, 0xf0, 0x16, 0xfa, 0x40, 0xf2, - 0x37, 0x6b, 0x0a, 0x21, 0x00, 0xf0, 0x1d, 0xfa, 0x40, 0xf2, 0x3a, 0x68, - 0x00, 0xf0, 0x14, 0xfa, 0x40, 0xf2, 0x3b, 0x69, 0x00, 0xf0, 0x68, 0xf8, - 0x40, 0xf2, 0x39, 0x6a, 0x00, 0xf0, 0x60, 0xf8, 0xdf, 0xf8, 0xbc, 0x03, - 0x00, 0x78, 0x8d, 0xf8, 0x00, 0x00, 0x40, 0xf2, 0x76, 0x67, 0x00, 0x21, - 0x38, 0x46, 0xef, 0xf7, 0x59, 0xfb, 0x02, 0x22, 0x00, 0xf0, 0x5a, 0xf8, - 0xe9, 0x4b, 0x00, 0x22, 0x02, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xf6, 0xf7, - 0x13, 0xf8, 0x00, 0x24, 0x18, 0xb1, 0x00, 0x22, 0x00, 0xf0, 0x4e, 0xf8, - 0x01, 0x24, 0x9d, 0xf8, 0x00, 0x10, 0x38, 0x46, 0xef, 0xf7, 0x44, 0xfb, - 0xf1, 0xf7, 0x97, 0xf8, 0xdc, 0x49, 0xc9, 0x6a, 0xff, 0xf7, 0x62, 0xff, - 0x07, 0x46, 0xf9, 0xb2, 0x40, 0xf2, 0x31, 0x60, 0xef, 0xf7, 0x38, 0xfb, - 0x39, 0x0a, 0x40, 0xf2, 0x32, 0x60, 0xef, 0xf7, 0x33, 0xfb, 0x00, 0x21, - 0x40, 0xf2, 0x33, 0x60, 0xef, 0xf7, 0x2e, 0xfb, 0x61, 0x21, 0x00, 0xf0, - 0xcc, 0xf9, 0x0a, 0x21, 0x00, 0xf0, 0xd5, 0xf9, 0x00, 0xf0, 0x22, 0xf8, - 0x00, 0xf0, 0xcc, 0xf9, 0x00, 0xf0, 0x22, 0xf8, 0x00, 0xf0, 0x17, 0xf8, - 0x00, 0xf0, 0x10, 0xf8, 0x00, 0xf0, 0x09, 0xf8, 0x7b, 0x21, 0x00, 0xf0, - 0xbe, 0xf9, 0x00, 0x20, 0xef, 0xf7, 0xc8, 0xfd, 0x20, 0x46, 0xbd, 0xe8, - 0xf2, 0x8f, 0x11, 0x21, 0x40, 0xf2, 0x41, 0x60, 0xef, 0xf7, 0x0e, 0xbb, - 0x00, 0x21, 0x4f, 0xf4, 0xc8, 0x60, 0xef, 0xf7, 0x09, 0xbb, 0x00, 0x21, - 0x40, 0xf2, 0x3f, 0x60, 0xef, 0xf7, 0x04, 0xbb, 0x3f, 0x21, 0x50, 0x46, - 0xef, 0xf7, 0x00, 0xbb, 0x00, 0x21, 0x48, 0x46, 0xef, 0xf7, 0xfc, 0xba, - 0x02, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xef, 0xf7, 0x01, 0xbb, 0x2d, 0xe9, - 0xf0, 0x4f, 0x87, 0xb0, 0x00, 0x21, 0x00, 0x20, 0xef, 0xf7, 0x45, 0xfd, - 0x10, 0x22, 0x00, 0xf0, 0xad, 0xf8, 0x00, 0xf0, 0xa0, 0xf9, 0x10, 0x21, - 0x40, 0xf2, 0x4f, 0x60, 0xef, 0xf7, 0xe6, 0xfa, 0x40, 0x21, 0x4f, 0xf4, - 0xca, 0x60, 0xef, 0xf7, 0xe1, 0xfa, 0x00, 0x21, 0x40, 0xf2, 0x51, 0x60, - 0xef, 0xf7, 0xdc, 0xfa, 0x40, 0xf2, 0x52, 0x64, 0x33, 0x21, 0x20, 0x46, - 0xef, 0xf7, 0xd6, 0xfa, 0x32, 0x21, 0x40, 0xf2, 0x53, 0x60, 0xef, 0xf7, - 0xd1, 0xfa, 0x7b, 0x22, 0x7f, 0x21, 0x40, 0xf2, 0x54, 0x60, 0xef, 0xf7, - 0xd5, 0xfa, 0x01, 0x21, 0x40, 0xf2, 0x55, 0x60, 0xef, 0xf7, 0xc6, 0xfa, - 0x40, 0xf2, 0x56, 0x65, 0x00, 0xf0, 0x66, 0xf9, 0x40, 0xf2, 0x57, 0x6a, - 0x3c, 0x21, 0xff, 0xf7, 0xba, 0xff, 0x40, 0xf2, 0x59, 0x6b, 0x00, 0xf0, - 0x65, 0xf9, 0x40, 0xf2, 0x5a, 0x68, 0x00, 0x21, 0x00, 0xf0, 0x5d, 0xf9, - 0x00, 0xf0, 0x6d, 0xf8, 0x98, 0x48, 0x97, 0x4f, 0x00, 0x78, 0x01, 0x90, - 0x40, 0xf2, 0x42, 0x69, 0x04, 0xa8, 0xf1, 0xf7, 0xe4, 0xfc, 0x00, 0x20, - 0xf1, 0xf7, 0x09, 0xfd, 0x93, 0x48, 0x00, 0x78, 0x00, 0x90, 0x02, 0x21, - 0xff, 0xf7, 0xa1, 0xff, 0x3b, 0x46, 0x00, 0x22, 0x02, 0x21, 0x48, 0x46, - 0xf5, 0xf7, 0x5e, 0xff, 0x06, 0x46, 0x00, 0x21, 0x04, 0xa8, 0xf1, 0xf7, - 0xe2, 0xfc, 0x1e, 0xb1, 0xff, 0xf7, 0x92, 0xff, 0x02, 0x26, 0x16, 0xe0, - 0x02, 0xa8, 0xf1, 0xf7, 0x3a, 0xff, 0x01, 0x21, 0x00, 0x20, 0xf1, 0xf7, - 0x37, 0xfe, 0x04, 0x21, 0xff, 0xf7, 0x87, 0xff, 0x3b, 0x46, 0x00, 0x22, - 0x04, 0x21, 0x48, 0x46, 0xf5, 0xf7, 0x44, 0xff, 0x10, 0xb1, 0xff, 0xf7, - 0x7d, 0xff, 0x03, 0x26, 0x02, 0xa8, 0xf1, 0xf7, 0x33, 0xff, 0x00, 0xf0, - 0x02, 0xf9, 0x00, 0x22, 0x00, 0xf0, 0x34, 0xf8, 0xff, 0x21, 0x40, 0xf2, - 0x4f, 0x60, 0xef, 0xf7, 0x6f, 0xfa, 0x74, 0x4f, 0x39, 0x88, 0xc9, 0xb2, - 0x4f, 0xf4, 0xca, 0x60, 0xef, 0xf7, 0x68, 0xfa, 0x38, 0x88, 0x01, 0x0a, - 0x40, 0xf2, 0x51, 0x60, 0xef, 0xf7, 0x62, 0xfa, 0x00, 0x21, 0x20, 0x46, - 0xef, 0xf7, 0x5e, 0xfa, 0x00, 0xf0, 0x00, 0xf9, 0x3c, 0x21, 0xff, 0xf7, - 0x56, 0xff, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, 0x01, 0xf9, 0x00, 0x21, - 0x00, 0xf0, 0xfb, 0xf8, 0x00, 0x98, 0x40, 0xf0, 0x10, 0x01, 0xc9, 0xb2, - 0xff, 0xf7, 0x4d, 0xff, 0x00, 0x20, 0xef, 0xf7, 0xfb, 0xfc, 0x30, 0x46, - 0x07, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x3f, 0x21, 0x4f, 0xf4, 0xcb, 0x60, - 0xef, 0xf7, 0x40, 0xba, 0x10, 0x21, 0x40, 0xf6, 0x82, 0x50, 0xef, 0xf7, - 0x45, 0xba, 0x00, 0x20, 0x2d, 0xe9, 0xfe, 0x4f, 0x00, 0x21, 0xef, 0xf7, - 0x8a, 0xfc, 0x00, 0xf0, 0xe8, 0xf8, 0x5b, 0x48, 0x00, 0x78, 0x8d, 0xf8, - 0x08, 0x00, 0x03, 0x21, 0x40, 0xf6, 0x1a, 0x00, 0xef, 0xf7, 0x2a, 0xfa, - 0x00, 0xf0, 0xd8, 0xf8, 0x40, 0x21, 0x40, 0xf2, 0x44, 0x60, 0xef, 0xf7, - 0x23, 0xfa, 0x30, 0x21, 0x40, 0xf2, 0x45, 0x60, 0xef, 0xf7, 0x1e, 0xfa, - 0x00, 0xf0, 0xb7, 0xf8, 0x32, 0x21, 0x40, 0xf2, 0x47, 0x60, 0xef, 0xf7, - 0x17, 0xfa, 0x1b, 0x22, 0x1f, 0x21, 0x4f, 0xf4, 0xc9, 0x60, 0xef, 0xf7, - 0x1b, 0xfa, 0x00, 0xf0, 0xa5, 0xf8, 0x00, 0xf0, 0x9e, 0xf8, 0x40, 0xf2, - 0x4b, 0x65, 0x08, 0x21, 0x00, 0xf0, 0xad, 0xf8, 0x40, 0xf2, 0x4d, 0x66, - 0x00, 0xf0, 0xa4, 0xf8, 0x40, 0xf2, 0x4e, 0x69, 0xff, 0xf7, 0x00, 0xff, - 0x40, 0xf2, 0x4c, 0x68, 0x14, 0x21, 0x00, 0xf0, 0xa4, 0xf8, 0x00, 0x22, - 0x00, 0xf0, 0x7e, 0xf8, 0x40, 0xf6, 0x1f, 0x07, 0x00, 0x22, 0xc0, 0x21, - 0x38, 0x46, 0xf1, 0xf7, 0xcd, 0xfb, 0x38, 0x48, 0x00, 0x78, 0x01, 0x90, - 0x04, 0x21, 0x4f, 0xf4, 0x82, 0x70, 0xf1, 0xf7, 0x9e, 0xfb, 0x40, 0xf6, - 0x15, 0x0a, 0x20, 0x22, 0x20, 0x21, 0x50, 0x46, 0xf1, 0xf7, 0xbe, 0xfb, - 0x31, 0x48, 0x00, 0x78, 0x00, 0x90, 0x40, 0xf2, 0x42, 0x6b, 0x01, 0x21, - 0x00, 0xf0, 0x87, 0xf8, 0x2b, 0x4b, 0x00, 0x22, 0x01, 0x21, 0x58, 0x46, - 0xf5, 0xf7, 0x98, 0xfe, 0x00, 0x24, 0x10, 0xb1, 0x00, 0xf0, 0x7c, 0xf8, - 0x04, 0x24, 0x00, 0x22, 0x20, 0x21, 0x50, 0x46, 0xf1, 0xf7, 0xa6, 0xfb, - 0x00, 0xf0, 0x53, 0xf8, 0x80, 0x22, 0x00, 0xf0, 0x4b, 0xf8, 0xc0, 0x22, - 0xc0, 0x21, 0x38, 0x46, 0xf1, 0xf7, 0x9c, 0xfb, 0x9d, 0xf8, 0x08, 0x10, - 0x40, 0xf6, 0x1a, 0x00, 0xef, 0xf7, 0xba, 0xf9, 0x00, 0xf0, 0x68, 0xf8, - 0xf0, 0xf7, 0x03, 0xff, 0x16, 0x49, 0x49, 0x6d, 0xff, 0xf7, 0xd6, 0xfd, - 0x07, 0x46, 0xf9, 0xb2, 0x40, 0xf2, 0x44, 0x60, 0xef, 0xf7, 0xac, 0xf9, - 0x39, 0x0a, 0x40, 0xf2, 0x45, 0x60, 0xef, 0xf7, 0xa7, 0xf9, 0x00, 0xf0, - 0x40, 0xf8, 0x00, 0xf0, 0x39, 0xf8, 0x00, 0xf0, 0x32, 0xf8, 0x08, 0x21, - 0x00, 0xf0, 0x43, 0xf8, 0x14, 0x21, 0x00, 0xf0, 0x44, 0xf8, 0x00, 0xf0, - 0x39, 0xf8, 0xff, 0xf7, 0x97, 0xfe, 0x00, 0x98, 0x40, 0xf0, 0x08, 0x01, - 0xc9, 0xb2, 0x00, 0xf0, 0x3e, 0xf8, 0x00, 0x20, 0xef, 0xf7, 0x40, 0xfc, - 0x20, 0x46, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x09, 0x3d, - 0x78, 0x29, 0x00, 0x20, 0x94, 0xf3, 0x00, 0x20, 0x76, 0x06, 0x00, 0x46, - 0x40, 0x42, 0x0f, 0x00, 0x04, 0x01, 0x00, 0x46, 0x42, 0x06, 0x00, 0x46, - 0x1a, 0x08, 0x00, 0x46, 0x80, 0x21, 0x4f, 0xf4, 0x02, 0x60, 0xf1, 0xf7, - 0x51, 0xbb, 0x01, 0x99, 0xc9, 0xb2, 0x4f, 0xf4, 0x82, 0x70, 0xf1, 0xf7, - 0x24, 0xbb, 0x0a, 0x21, 0x40, 0xf2, 0x4a, 0x60, 0xef, 0xf7, 0x6a, 0xb9, - 0x13, 0x21, 0x40, 0xf2, 0x49, 0x60, 0xef, 0xf7, 0x65, 0xb9, 0x00, 0x21, - 0x40, 0xf2, 0x46, 0x60, 0xef, 0xf7, 0x60, 0xb9, 0x00, 0x21, 0x30, 0x46, - 0xef, 0xf7, 0x5c, 0xb9, 0x0a, 0x21, 0x28, 0x46, 0xef, 0xf7, 0x58, 0xb9, - 0x01, 0x21, 0x40, 0x46, 0xef, 0xf7, 0x54, 0xb9, 0x00, 0x21, 0x58, 0x46, - 0xef, 0xf7, 0x50, 0xb9, 0x10, 0x21, 0x40, 0xf2, 0x43, 0x60, 0xef, 0xf7, - 0x4b, 0xb9, 0x00, 0x22, 0x01, 0x21, 0x40, 0xf6, 0x87, 0x50, 0xef, 0xf7, - 0x4f, 0xb9, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x4f, 0x00, 0xf1, 0x58, 0x06, - 0x83, 0xb0, 0x00, 0xf1, 0x08, 0x05, 0x30, 0x78, 0x0c, 0x46, 0x60, 0xb1, - 0xf1, 0x78, 0xb0, 0x78, 0x22, 0x46, 0xf0, 0xf7, 0x44, 0xff, 0x30, 0xb9, - 0x01, 0x20, 0x68, 0x64, 0x28, 0x64, 0xe8, 0x68, 0x40, 0xf0, 0x02, 0x00, - 0xe8, 0x60, 0x00, 0x2c, 0xc4, 0xf1, 0x00, 0x0b, 0x4f, 0xf0, 0x82, 0x40, - 0x4f, 0xf0, 0x01, 0x0a, 0x04, 0xd5, 0x0a, 0xfa, 0x0b, 0xf1, 0x01, 0x60, - 0x00, 0x21, 0x03, 0xe0, 0x00, 0x21, 0x01, 0x60, 0x0a, 0xfa, 0x04, 0xf1, - 0x41, 0x60, 0x68, 0x6c, 0x00, 0x28, 0x71, 0xd1, 0x70, 0x78, 0x00, 0x21, - 0xf0, 0xf7, 0xef, 0xff, 0x00, 0x28, 0x5f, 0xd1, 0x6a, 0x46, 0x01, 0xa9, - 0x20, 0x46, 0xf1, 0xf7, 0x35, 0xf8, 0xd6, 0xe9, 0x02, 0x23, 0x01, 0x98, - 0x12, 0xeb, 0x00, 0x08, 0x43, 0xeb, 0xe0, 0x79, 0xc6, 0xe9, 0x02, 0x89, - 0xd6, 0xe9, 0x04, 0x23, 0x00, 0x98, 0xc1, 0x17, 0x10, 0x18, 0x59, 0x41, - 0xc6, 0xe9, 0x04, 0x01, 0x72, 0x68, 0x52, 0x1c, 0x72, 0x60, 0x2b, 0x68, - 0x5b, 0x88, 0x9a, 0x42, 0xd9, 0xd3, 0x6f, 0x68, 0x00, 0x2c, 0x1d, 0xd4, - 0xa3, 0x46, 0x77, 0xb1, 0x00, 0x23, 0xf3, 0xf7, 0xf9, 0xfa, 0x07, 0xeb, - 0x8b, 0x01, 0x00, 0x23, 0xc1, 0xf8, 0xc0, 0x00, 0x40, 0x46, 0x72, 0x68, - 0x49, 0x46, 0xf3, 0xf7, 0xef, 0xfa, 0x47, 0xf8, 0x2b, 0x00, 0xac, 0x61, - 0xc5, 0xe9, 0x08, 0x89, 0xd6, 0xe9, 0x04, 0x01, 0xc5, 0xe9, 0x0a, 0x01, - 0xe8, 0x6c, 0x0a, 0xfa, 0x0b, 0xf1, 0x88, 0x43, 0xe8, 0x64, 0x1a, 0xe0, - 0x6f, 0xb1, 0x00, 0x23, 0x07, 0xeb, 0x8b, 0x07, 0xf3, 0xf7, 0xda, 0xfa, - 0xc7, 0xf8, 0x20, 0x01, 0x40, 0x46, 0x72, 0x68, 0x49, 0x46, 0x00, 0x23, - 0xf3, 0xf7, 0xd2, 0xfa, 0x38, 0x66, 0xec, 0x61, 0xc5, 0xe9, 0x0c, 0x89, - 0xd6, 0xe9, 0x04, 0x01, 0xc5, 0xe9, 0x0e, 0x01, 0xa8, 0x6c, 0x0a, 0xfa, - 0x0b, 0xf1, 0x88, 0x43, 0xa8, 0x64, 0x00, 0x20, 0x70, 0x60, 0xc6, 0xe9, - 0x04, 0x00, 0xc6, 0xe9, 0x02, 0x00, 0x0b, 0xe0, 0x01, 0x28, 0x08, 0xbf, - 0x68, 0x64, 0x07, 0xd0, 0xe8, 0x68, 0xc5, 0xf8, 0x44, 0xa0, 0x40, 0xf0, - 0x04, 0x00, 0xc5, 0xf8, 0x40, 0xa0, 0xe8, 0x60, 0xbd, 0xe8, 0xf7, 0x8f, - 0x2d, 0xe9, 0xfe, 0x4f, 0x04, 0x46, 0xdf, 0xf8, 0x90, 0x13, 0x20, 0x78, - 0xdf, 0xf8, 0x8c, 0x53, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x90, 0x00, 0x20, - 0x60, 0x61, 0x60, 0x78, 0x01, 0x28, 0x04, 0xd1, 0xd1, 0xe9, 0x08, 0x6b, - 0x2b, 0x6c, 0xaa, 0x69, 0x03, 0xe0, 0xd1, 0xe9, 0x06, 0x6b, 0xeb, 0x6a, - 0x6a, 0x6b, 0xa1, 0x68, 0x0f, 0x88, 0x39, 0x0a, 0x01, 0xf0, 0x03, 0x0a, - 0x01, 0x28, 0x08, 0xbf, 0x4f, 0xf0, 0x00, 0x0a, 0x09, 0xd0, 0x00, 0x21, - 0x8b, 0x45, 0xd5, 0x48, 0x05, 0xd8, 0x86, 0x42, 0x3c, 0xbf, 0xba, 0xf1, - 0x03, 0x0f, 0x4f, 0xf0, 0x03, 0x0a, 0x4f, 0xf6, 0xff, 0x40, 0x38, 0x40, - 0x40, 0xea, 0x0a, 0x20, 0xad, 0xf8, 0x0a, 0x00, 0x28, 0x68, 0xb0, 0xeb, - 0x83, 0x0f, 0x39, 0xd3, 0x60, 0x68, 0x01, 0x89, 0xad, 0xf8, 0x04, 0x10, - 0x4f, 0xf0, 0x01, 0x09, 0x40, 0x89, 0xad, 0xf8, 0x06, 0x00, 0x4f, 0xf0, - 0x00, 0x0c, 0x01, 0xa8, 0x4f, 0xf4, 0x7a, 0x78, 0x30, 0xf8, 0x1c, 0x50, - 0xa8, 0x05, 0x80, 0x0d, 0xb3, 0xfb, 0xf8, 0xf8, 0xc5, 0xf3, 0x81, 0x21, - 0x08, 0xfb, 0x00, 0xf7, 0x21, 0xb9, 0x4f, 0xf4, 0x7a, 0x70, 0xb7, 0xfb, - 0xf0, 0xf0, 0x07, 0xe0, 0x01, 0x29, 0x05, 0xd1, 0xbc, 0x48, 0xa0, 0xfb, - 0x07, 0x01, 0xc0, 0x0f, 0x40, 0xea, 0x41, 0x00, 0xb0, 0xf5, 0x80, 0x6f, - 0x02, 0xd3, 0xc4, 0xf8, 0x14, 0x90, 0x64, 0xe1, 0x05, 0xf4, 0x70, 0x41, - 0x08, 0x43, 0x01, 0xa9, 0x40, 0xf4, 0x00, 0x60, 0x21, 0xf8, 0x1c, 0x00, - 0x0c, 0xf1, 0x01, 0x0c, 0xbc, 0xf1, 0x02, 0x0f, 0xd1, 0xd3, 0x01, 0xe0, - 0x4f, 0xf0, 0x00, 0x09, 0x19, 0x46, 0x10, 0x46, 0xfe, 0xf7, 0x76, 0xf9, - 0x05, 0x28, 0x38, 0xbf, 0x04, 0x20, 0x01, 0x21, 0x40, 0x1c, 0x01, 0xfa, - 0x00, 0xf0, 0x61, 0x68, 0x0a, 0x68, 0x49, 0x68, 0x40, 0x1e, 0x02, 0x40, - 0x08, 0x40, 0xa1, 0x78, 0xa2, 0x61, 0x22, 0x65, 0xe0, 0x61, 0x60, 0x65, - 0x00, 0x29, 0x18, 0xbf, 0x01, 0x29, 0x04, 0xf1, 0x58, 0x00, 0x28, 0xd1, - 0x01, 0x21, 0x01, 0x70, 0xa1, 0x78, 0x01, 0x29, 0x08, 0xbf, 0x04, 0x21, - 0x04, 0xd0, 0x00, 0x99, 0x00, 0x29, 0x0c, 0xbf, 0x01, 0x21, 0x02, 0x21, - 0xc1, 0x70, 0x61, 0x78, 0x09, 0xb9, 0x81, 0x70, 0x1a, 0xe0, 0x01, 0x21, - 0x81, 0x70, 0x02, 0x21, 0x41, 0x70, 0x00, 0x21, 0xa1, 0x64, 0xc0, 0xe9, - 0x02, 0x11, 0xc0, 0xe9, 0x04, 0x11, 0x41, 0x60, 0x30, 0x46, 0x59, 0x46, - 0xf1, 0xf7, 0x52, 0xfc, 0x8d, 0xf8, 0x08, 0x00, 0x04, 0xf1, 0x7a, 0x06, - 0xdf, 0xf8, 0x3c, 0x82, 0x40, 0xf6, 0x41, 0x4b, 0x21, 0xe0, 0x61, 0x78, - 0x00, 0x29, 0xe6, 0xd1, 0x00, 0x99, 0xe5, 0xe7, 0xee, 0xf7, 0xe4, 0xff, - 0xf1, 0x78, 0x40, 0xf2, 0x35, 0x40, 0xee, 0xf7, 0xdf, 0xff, 0x31, 0x79, - 0x40, 0xf2, 0x36, 0x40, 0xee, 0xf7, 0xda, 0xff, 0xb1, 0x78, 0x40, 0xf2, - 0x33, 0x40, 0xee, 0xf7, 0xd5, 0xff, 0x71, 0x78, 0x40, 0xf2, 0x2e, 0x40, - 0xee, 0xf7, 0xd0, 0xff, 0x00, 0xf0, 0x08, 0xf9, 0xee, 0xf7, 0xea, 0xff, - 0x00, 0x20, 0xef, 0xf7, 0x7b, 0xfa, 0xa1, 0x6c, 0x20, 0x6d, 0x00, 0x29, - 0x40, 0xf0, 0xe2, 0x80, 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6d, 0x00, 0x28, - 0x00, 0xf0, 0xe1, 0x80, 0x00, 0x20, 0xe0, 0x64, 0xef, 0xf7, 0x0f, 0xfa, - 0x00, 0xf0, 0xf2, 0xf8, 0xee, 0xf7, 0xe7, 0xff, 0x73, 0x48, 0x00, 0x78, - 0x30, 0x70, 0x04, 0xf1, 0x70, 0x00, 0xf1, 0xf7, 0x5c, 0xfc, 0x60, 0x78, - 0x01, 0x28, 0x0c, 0xbf, 0x02, 0x21, 0x03, 0x21, 0x00, 0x98, 0xc0, 0xb2, - 0xf1, 0xf7, 0x54, 0xfb, 0x00, 0x98, 0x9d, 0xf8, 0x08, 0x10, 0xc0, 0xb2, - 0xf1, 0xf7, 0x1c, 0xfc, 0x50, 0x46, 0xf1, 0xf7, 0x21, 0xfc, 0x00, 0x98, - 0x03, 0x21, 0xc0, 0xb2, 0xf1, 0xf7, 0x2f, 0xfc, 0x00, 0x98, 0x3f, 0x21, - 0xc0, 0xb2, 0xf1, 0xf7, 0x35, 0xfc, 0xf1, 0xf7, 0x98, 0xfb, 0xf1, 0xf7, - 0x7a, 0xfb, 0x60, 0x78, 0x01, 0x28, 0x0b, 0xd1, 0x60, 0x68, 0x00, 0x7d, - 0x20, 0xb1, 0xc0, 0x22, 0xc0, 0x21, 0x58, 0x46, 0xf1, 0xf7, 0x60, 0xf9, - 0xff, 0x20, 0x60, 0x74, 0x04, 0x20, 0x5f, 0xe0, 0x98, 0xf8, 0x00, 0x00, - 0x70, 0x70, 0x98, 0xf8, 0x05, 0x00, 0xb0, 0x70, 0x00, 0xf0, 0xfc, 0x01, - 0x40, 0xf2, 0x33, 0x40, 0xee, 0xf7, 0x74, 0xff, 0x70, 0x78, 0x00, 0xf0, - 0xf0, 0x01, 0x40, 0xf2, 0x2e, 0x40, 0xee, 0xf7, 0x6d, 0xff, 0x98, 0xf8, - 0x07, 0x00, 0xf0, 0x70, 0x98, 0xf8, 0x08, 0x00, 0x30, 0x71, 0x00, 0x20, - 0xf8, 0xf7, 0x10, 0xfc, 0x00, 0x23, 0x99, 0x42, 0x4a, 0x4a, 0x05, 0xd8, - 0x90, 0x42, 0x03, 0xd2, 0x49, 0x48, 0x90, 0xf9, 0x1d, 0x50, 0x02, 0xe0, - 0x47, 0x48, 0x90, 0xf9, 0x24, 0x50, 0x60, 0x68, 0x00, 0x99, 0x00, 0x7d, - 0xc9, 0xb9, 0x20, 0xb1, 0x0c, 0x22, 0x0c, 0x21, 0x58, 0x46, 0xee, 0xf7, - 0x57, 0xff, 0xf0, 0x78, 0x60, 0x74, 0xff, 0x27, 0xf9, 0xb2, 0x00, 0x20, - 0xee, 0xf7, 0xf9, 0xff, 0x85, 0x42, 0x06, 0xdb, 0x67, 0x74, 0xf9, 0xb2, - 0x40, 0xf2, 0x35, 0x40, 0xee, 0xf7, 0x3e, 0xff, 0x01, 0xe0, 0x7f, 0x1e, - 0xf0, 0xd5, 0x00, 0x20, 0x18, 0xe0, 0x20, 0xb1, 0x30, 0x22, 0x30, 0x21, - 0x58, 0x46, 0xee, 0xf7, 0x3d, 0xff, 0x30, 0x79, 0x60, 0x74, 0xff, 0x27, - 0xf9, 0xb2, 0x01, 0x20, 0xee, 0xf7, 0xdf, 0xff, 0x85, 0x42, 0x06, 0xdb, - 0x67, 0x74, 0xf9, 0xb2, 0x40, 0xf2, 0x36, 0x40, 0xee, 0xf7, 0x24, 0xff, - 0x01, 0xe0, 0x7f, 0x1e, 0xf0, 0xd5, 0x01, 0x20, 0xee, 0xf7, 0xca, 0xff, - 0x20, 0x74, 0x60, 0x68, 0xf0, 0xf7, 0x8c, 0xfd, 0xbd, 0xf8, 0x0a, 0x00, - 0xf0, 0xf7, 0x84, 0xfd, 0xb9, 0xf1, 0x00, 0x0f, 0x06, 0xd0, 0xbd, 0xf8, - 0x04, 0x00, 0x24, 0x49, 0x08, 0x80, 0xbd, 0xf8, 0x06, 0x00, 0x48, 0x80, - 0x01, 0x25, 0x07, 0xe0, 0x60, 0x6d, 0xe8, 0x40, 0xc0, 0x07, 0x08, 0xd5, - 0x29, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xbe, 0xfd, 0xe0, 0x6c, 0x00, 0x28, - 0xf4, 0xd0, 0xe0, 0x6c, 0x40, 0xb9, 0x20, 0x6d, 0xe8, 0x40, 0xc0, 0x07, - 0x04, 0xd5, 0x69, 0x42, 0x20, 0x46, 0xff, 0xf7, 0xb1, 0xfd, 0xf4, 0xe7, - 0x6d, 0x1c, 0x18, 0x2d, 0xee, 0xd3, 0xf0, 0xf7, 0xc1, 0xfd, 0x04, 0xf1, - 0x70, 0x00, 0xf1, 0xf7, 0xa5, 0xfb, 0x60, 0x78, 0x31, 0x78, 0x01, 0x28, - 0x58, 0x46, 0x7f, 0xf4, 0xff, 0xae, 0xf1, 0xf7, 0x98, 0xf8, 0x11, 0xe7, - 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6d, 0x00, 0x28, 0x01, 0xd1, 0x01, 0x20, - 0x00, 0xe0, 0x00, 0x20, 0xbd, 0xe8, 0xfe, 0x8f, 0x00, 0xf2, 0x00, 0x20, - 0x78, 0x29, 0x00, 0x20, 0x00, 0x9c, 0xe4, 0xa6, 0x98, 0x6e, 0x12, 0x83, - 0x2e, 0x04, 0x00, 0x46, 0x41, 0x0c, 0x00, 0x46, 0x00, 0x28, 0x6b, 0xee, - 0xdc, 0x29, 0x00, 0x20, 0x08, 0x00, 0x00, 0x41, 0x02, 0x22, 0x04, 0xf1, - 0x78, 0x01, 0x0f, 0xf2, 0x1c, 0x00, 0x70, 0x47, 0x00, 0x29, 0x18, 0xbf, - 0x01, 0x29, 0x05, 0xd1, 0x01, 0x00, 0x18, 0xbf, 0x01, 0x21, 0x08, 0x46, - 0xf0, 0xf7, 0x7e, 0xbc, 0x70, 0x47, 0x00, 0x00, 0x82, 0x01, 0x0b, 0x02, - 0x38, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0xf1, 0xf7, 0x7e, 0xfc, 0x20, 0x68, - 0xf1, 0xf7, 0x77, 0xfc, 0x28, 0x46, 0xbd, 0xe8, 0x32, 0x40, 0xf1, 0xf7, - 0x7d, 0xbc, 0x2d, 0xe9, 0xf0, 0x41, 0x0d, 0x46, 0x04, 0x46, 0x00, 0x26, - 0x05, 0xf5, 0x98, 0x77, 0x05, 0xf5, 0x90, 0x78, 0x64, 0x42, 0x28, 0x68, - 0x21, 0xb2, 0x00, 0xf0, 0x7a, 0xfa, 0xf1, 0xf7, 0x0a, 0xfc, 0xf1, 0xf7, - 0x24, 0xfc, 0x08, 0xb1, 0x04, 0x26, 0x17, 0xe0, 0xf9, 0x68, 0xa8, 0x68, - 0xf1, 0xf7, 0xe0, 0xfd, 0xa8, 0x68, 0x41, 0x46, 0x00, 0xf0, 0xa1, 0xfa, - 0x69, 0x68, 0xdf, 0xf8, 0x44, 0x04, 0xf2, 0xf7, 0x41, 0xfd, 0x01, 0x46, - 0x38, 0x68, 0xf2, 0xf7, 0x45, 0xfe, 0xe1, 0xd8, 0x28, 0x68, 0x05, 0xf5, - 0x9a, 0x72, 0x41, 0x46, 0x00, 0xf0, 0x32, 0xfb, 0xa8, 0x68, 0x00, 0xf0, - 0x8b, 0xfa, 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x2d, 0xe9, 0xf8, 0x4f, - 0x04, 0x46, 0x80, 0x25, 0xb4, 0xf9, 0x18, 0x61, 0x31, 0x00, 0x48, 0xbf, - 0x49, 0x42, 0x80, 0x29, 0x4f, 0xf0, 0x00, 0x0a, 0x4f, 0xf0, 0x04, 0x08, - 0x04, 0xda, 0x00, 0x2e, 0x46, 0xbf, 0x75, 0x42, 0x2d, 0xb2, 0x35, 0x46, - 0x77, 0x1b, 0x3f, 0xb2, 0xd1, 0x46, 0x5f, 0xea, 0xc9, 0x70, 0x52, 0xbf, - 0x07, 0xeb, 0x45, 0x07, 0x3f, 0xb2, 0xa7, 0xeb, 0x45, 0x07, 0x20, 0x68, - 0x3a, 0xb2, 0x00, 0x21, 0xf1, 0xf7, 0x74, 0xfb, 0x21, 0x46, 0x40, 0x46, - 0xff, 0xf7, 0xa5, 0xff, 0x5f, 0xea, 0x00, 0x0b, 0x16, 0xd1, 0x04, 0xf5, - 0x8c, 0x70, 0x00, 0x21, 0xc2, 0x69, 0x10, 0x46, 0xf2, 0xf7, 0xec, 0xfc, - 0x38, 0xbf, 0x82, 0xf0, 0x00, 0x42, 0x50, 0x46, 0x11, 0x46, 0xf2, 0xf7, - 0xe5, 0xfc, 0x38, 0xbf, 0x92, 0x46, 0x09, 0xf1, 0x01, 0x09, 0xb9, 0xf1, - 0x04, 0x0f, 0x4f, 0xf0, 0x00, 0x08, 0xd4, 0xd3, 0x20, 0x68, 0x32, 0x46, - 0x00, 0x21, 0xf1, 0xf7, 0x51, 0xfb, 0xbb, 0xf1, 0x00, 0x0f, 0x14, 0xd1, - 0x28, 0x46, 0xf2, 0xf7, 0x3b, 0xfb, 0x51, 0x46, 0xf2, 0xf7, 0x52, 0xfb, - 0xdf, 0x49, 0xf2, 0xf7, 0xcb, 0xfc, 0x38, 0xbf, 0x08, 0x46, 0x04, 0xd3, - 0xdd, 0x49, 0xf2, 0xf7, 0xdf, 0xfd, 0x98, 0xbf, 0xdc, 0x48, 0x01, 0x46, - 0x20, 0x68, 0x00, 0xf0, 0xc4, 0xfa, 0x58, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, - 0x2d, 0xe9, 0xf0, 0x47, 0x05, 0x46, 0x8a, 0x46, 0x17, 0x46, 0x4f, 0xf0, - 0x00, 0x09, 0x4f, 0xf0, 0x06, 0x08, 0x05, 0xf5, 0x8e, 0x74, 0x38, 0x68, - 0x41, 0x42, 0x39, 0x60, 0x09, 0xb2, 0x28, 0x68, 0x00, 0xf0, 0xe1, 0xf9, - 0xf1, 0xf7, 0x71, 0xfb, 0xf1, 0xf7, 0x8b, 0xfb, 0x10, 0xb1, 0x4f, 0xf0, - 0x04, 0x09, 0x28, 0xe0, 0x21, 0x6a, 0xa8, 0x68, 0xf1, 0xf7, 0x46, 0xfd, - 0x39, 0x68, 0xa8, 0x68, 0x05, 0xf5, 0x90, 0x72, 0x00, 0xf0, 0x14, 0xfb, - 0x21, 0x68, 0x08, 0x1a, 0x20, 0x60, 0x81, 0x11, 0x00, 0xeb, 0x51, 0x60, - 0x46, 0x02, 0x36, 0x14, 0x30, 0x46, 0x48, 0xbf, 0x40, 0x42, 0x7f, 0x28, - 0x04, 0xdb, 0x01, 0x2e, 0xac, 0xbf, 0x7f, 0x26, 0x6f, 0xf0, 0x7e, 0x06, - 0x28, 0x68, 0x32, 0x46, 0x02, 0x21, 0xf1, 0xf7, 0xfb, 0xfa, 0xa8, 0x68, - 0x00, 0xf0, 0xe8, 0xf9, 0xb8, 0xf1, 0x01, 0x08, 0xc9, 0xd1, 0xaa, 0xf8, - 0x00, 0x61, 0x48, 0x46, 0xbd, 0xe8, 0xf0, 0x87, 0x2d, 0xe9, 0xf0, 0x4f, - 0x04, 0x46, 0x8f, 0xb0, 0x20, 0x68, 0x02, 0x90, 0x88, 0x46, 0xf9, 0xf7, - 0x91, 0xfb, 0xb2, 0x4a, 0x06, 0x90, 0xd2, 0xe9, 0x08, 0x01, 0x27, 0x69, - 0xb0, 0x4a, 0x00, 0x23, 0xf2, 0xf7, 0xe6, 0xff, 0x39, 0x8b, 0x00, 0x26, - 0x80, 0xb2, 0x88, 0x42, 0x34, 0xbf, 0xb8, 0x7c, 0xb8, 0x7e, 0x8d, 0xf8, - 0x04, 0x00, 0xaa, 0x49, 0xb7, 0xf9, 0x0e, 0x00, 0x81, 0xfb, 0x00, 0x01, - 0x00, 0xf0, 0xa5, 0xf9, 0x05, 0x90, 0x04, 0xf5, 0x8a, 0x77, 0x02, 0x98, - 0xc0, 0xf1, 0x01, 0x00, 0x38, 0x70, 0xc0, 0xb2, 0x00, 0xf0, 0x86, 0xfc, - 0x78, 0x80, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, 0xee, 0xff, 0x3a, 0x78, - 0x79, 0x88, 0x04, 0xf1, 0x14, 0x00, 0x00, 0xf0, 0xfa, 0xfb, 0x38, 0x78, - 0x00, 0xf0, 0x50, 0xfc, 0x20, 0xb1, 0x00, 0x20, 0xef, 0xf7, 0x3e, 0xf8, - 0x05, 0x20, 0x22, 0xe1, 0x02, 0x98, 0x0b, 0xa9, 0xf1, 0xf7, 0x82, 0xfd, - 0x40, 0xf2, 0xee, 0x20, 0xb8, 0x80, 0xfe, 0x80, 0xbe, 0x60, 0x02, 0x98, - 0xf1, 0xf7, 0x70, 0xfa, 0xa0, 0x68, 0x00, 0xf0, 0x91, 0xf9, 0x02, 0x98, - 0x09, 0xa9, 0xf2, 0xf7, 0xc1, 0xfe, 0xdd, 0xe9, 0x09, 0x01, 0xcd, 0xe9, - 0x07, 0x01, 0x8d, 0xf8, 0x1e, 0x60, 0x07, 0xaa, 0x02, 0x98, 0x02, 0x21, - 0xf2, 0xf7, 0xed, 0xfe, 0xe2, 0x68, 0x12, 0x78, 0x02, 0x99, 0x20, 0x69, - 0x52, 0x1e, 0x12, 0x04, 0x02, 0xf4, 0xfe, 0x02, 0x42, 0xea, 0x81, 0x71, - 0x9d, 0xf8, 0x04, 0x20, 0xd2, 0x05, 0x02, 0xf0, 0x7e, 0x52, 0x11, 0x43, - 0x82, 0x7d, 0xd2, 0x03, 0x02, 0xf4, 0x00, 0x42, 0x11, 0x43, 0x02, 0x7d, - 0x02, 0xf0, 0x07, 0x02, 0x11, 0x43, 0x41, 0xf0, 0x00, 0x41, 0x41, 0xf4, - 0x80, 0x41, 0x04, 0x91, 0x85, 0x78, 0x00, 0xe0, 0x6d, 0x1c, 0x20, 0x69, - 0xc1, 0x78, 0xa9, 0x42, 0xc0, 0xf0, 0x83, 0x80, 0x28, 0x18, 0x01, 0x79, - 0x03, 0x91, 0x06, 0x99, 0x03, 0x29, 0x07, 0xd1, 0x03, 0x98, 0x1b, 0x28, - 0x34, 0xbf, 0xc0, 0xf1, 0x64, 0x09, 0x4f, 0xf0, 0x32, 0x09, 0x01, 0xe0, - 0x90, 0xf8, 0x1b, 0x90, 0x03, 0x9a, 0x02, 0x98, 0x5f, 0xfa, 0x89, 0xf1, - 0xf2, 0xf7, 0xe8, 0xfe, 0x9d, 0xf8, 0x04, 0x10, 0x04, 0xa8, 0xff, 0xf7, - 0x79, 0xfe, 0xb8, 0x62, 0xe0, 0x68, 0x40, 0x78, 0xf1, 0xf7, 0x16, 0xfb, - 0x01, 0x2d, 0x03, 0xd1, 0x20, 0x46, 0xff, 0xf7, 0xaf, 0xfe, 0x06, 0x46, - 0x4f, 0xf0, 0x04, 0x0a, 0x86, 0xbb, 0x21, 0x46, 0x04, 0x20, 0xff, 0xf7, - 0x74, 0xfe, 0x06, 0x00, 0x2a, 0xd1, 0x78, 0x6a, 0x5e, 0x49, 0xf2, 0xf7, - 0xd1, 0xfb, 0x78, 0x62, 0x5c, 0x49, 0x38, 0x6a, 0xf2, 0xf7, 0xcc, 0xfb, - 0x83, 0x46, 0xf8, 0x88, 0xc7, 0xf8, 0x20, 0xb0, 0x00, 0x90, 0x78, 0x6a, - 0xf2, 0xf7, 0x30, 0xfc, 0x00, 0x99, 0x40, 0x18, 0xf8, 0x80, 0xb8, 0x88, - 0x00, 0x90, 0x58, 0x46, 0xf2, 0xf7, 0x28, 0xfc, 0x00, 0x99, 0x42, 0x18, - 0xba, 0x80, 0x12, 0xb2, 0x02, 0x98, 0x00, 0x21, 0xf1, 0xf7, 0x1c, 0xfa, - 0xb7, 0xf9, 0x06, 0x20, 0x02, 0x98, 0x01, 0x21, 0xf1, 0xf7, 0x16, 0xfa, - 0xba, 0xf1, 0x01, 0x0a, 0xcf, 0xd1, 0x00, 0xe0, 0x3e, 0xbb, 0x20, 0x69, - 0xb9, 0x88, 0x28, 0x18, 0x04, 0x2d, 0x00, 0x79, 0x28, 0xf8, 0x10, 0x10, - 0x08, 0xeb, 0x40, 0x00, 0xf9, 0x88, 0xa0, 0xf8, 0x80, 0x10, 0x91, 0xd2, - 0x0f, 0xf2, 0x0c, 0x10, 0x28, 0x5c, 0x03, 0x9a, 0x00, 0xeb, 0x09, 0x01, - 0x02, 0x98, 0xd2, 0xb2, 0xc9, 0xb2, 0xf2, 0xf7, 0x8b, 0xfe, 0x9d, 0xf8, - 0x04, 0x00, 0x29, 0x18, 0xc9, 0xb2, 0x04, 0xa8, 0xff, 0xf7, 0x1a, 0xfe, - 0xb8, 0x62, 0x05, 0xaa, 0x41, 0x46, 0x20, 0x46, 0xff, 0xf7, 0xb6, 0xfe, - 0x06, 0x00, 0x3f, 0xf4, 0x77, 0xaf, 0x00, 0xf0, 0x6d, 0xf8, 0x20, 0x69, - 0x80, 0x78, 0x45, 0x1c, 0x10, 0xe0, 0x28, 0x18, 0x90, 0xf8, 0x04, 0x90, - 0x90, 0xf8, 0x05, 0xa0, 0x52, 0x46, 0x49, 0x46, 0x40, 0x46, 0x00, 0xf0, - 0xc2, 0xfa, 0x52, 0x46, 0x49, 0x46, 0x08, 0xf1, 0x80, 0x00, 0x00, 0xf0, - 0xbc, 0xfa, 0x6d, 0x1c, 0x20, 0x69, 0xc1, 0x78, 0x8d, 0x42, 0xea, 0xd3, - 0x81, 0x78, 0x09, 0x18, 0x00, 0x22, 0x49, 0x79, 0x0c, 0xe0, 0x38, 0xf8, - 0x11, 0x30, 0x28, 0xf8, 0x12, 0x30, 0x08, 0xeb, 0x42, 0x05, 0x08, 0xeb, - 0x41, 0x03, 0x52, 0x1c, 0xb3, 0xf8, 0x80, 0x30, 0xa5, 0xf8, 0x80, 0x30, - 0x8a, 0x42, 0xf0, 0xdb, 0xc1, 0x78, 0x08, 0x18, 0x00, 0x79, 0x41, 0x1c, - 0x0c, 0xe0, 0x38, 0xf8, 0x10, 0x20, 0x28, 0xf8, 0x11, 0x20, 0x08, 0xeb, - 0x41, 0x03, 0x08, 0xeb, 0x40, 0x02, 0x49, 0x1c, 0xb2, 0xf8, 0x80, 0x20, - 0xa3, 0xf8, 0x80, 0x20, 0x40, 0x29, 0xf0, 0xdb, 0x02, 0x98, 0x09, 0xa9, - 0xf2, 0xf7, 0xe6, 0xfd, 0x02, 0x98, 0x0b, 0xa9, 0xf1, 0xf7, 0x8a, 0xfc, - 0x3a, 0x78, 0x79, 0x88, 0x04, 0xf1, 0x14, 0x00, 0x00, 0xf0, 0xff, 0xfa, - 0x08, 0xb1, 0x06, 0xb9, 0x05, 0x26, 0x00, 0x20, 0xee, 0xf7, 0x1e, 0xff, - 0x02, 0x98, 0x41, 0x46, 0x00, 0xf0, 0x27, 0xfa, 0x30, 0x46, 0x0f, 0xb0, - 0xbd, 0xe8, 0xf0, 0x8f, 0xb7, 0x43, 0xba, 0x51, 0xcd, 0xcc, 0xcc, 0x3e, - 0x01, 0x00, 0x20, 0x40, 0x00, 0x00, 0x20, 0x40, 0x00, 0xf2, 0x00, 0x20, - 0x40, 0x42, 0x0f, 0x00, 0x66, 0x66, 0x26, 0x3f, 0x00, 0x00, 0x0a, 0x1c, - 0x00, 0x21, 0x4f, 0xf4, 0x44, 0x60, 0xee, 0xf7, 0x4f, 0xbc, 0x80, 0xb5, - 0x80, 0x21, 0x4f, 0xf4, 0x44, 0x60, 0xee, 0xf7, 0x49, 0xfc, 0xbd, 0xe8, - 0x02, 0x40, 0x28, 0x20, 0xf2, 0xf7, 0x88, 0xb8, 0x70, 0xb5, 0x0d, 0x46, - 0x04, 0x46, 0x2e, 0x12, 0x00, 0x2c, 0x0c, 0xbf, 0x31, 0x46, 0x00, 0x21, - 0xc9, 0xb2, 0x40, 0xf6, 0xcb, 0x10, 0xee, 0xf7, 0x37, 0xfc, 0x00, 0x2c, - 0x0c, 0xbf, 0x29, 0x46, 0x00, 0x21, 0xc9, 0xb2, 0x40, 0xf6, 0xcc, 0x10, - 0xee, 0xf7, 0x2e, 0xfc, 0x04, 0xb9, 0x00, 0x26, 0xf1, 0xb2, 0x40, 0xf6, - 0xcd, 0x10, 0xee, 0xf7, 0x27, 0xfc, 0x04, 0xb9, 0x00, 0x25, 0xe9, 0xb2, - 0x40, 0xf6, 0xce, 0x10, 0xee, 0xf7, 0x20, 0xfc, 0xbd, 0xe8, 0x70, 0x40, - 0xcd, 0xe7, 0x31, 0xb1, 0xc9, 0x03, 0xc0, 0x22, 0x91, 0xfb, 0xf2, 0xf1, - 0xc1, 0xf5, 0x80, 0x31, 0xd0, 0xe7, 0x70, 0x47, 0x10, 0xb5, 0x04, 0x46, - 0x1b, 0x04, 0x43, 0xea, 0x12, 0x41, 0x10, 0x04, 0x0d, 0x4a, 0x52, 0x69, - 0x00, 0x23, 0xf2, 0xf7, 0x15, 0xfe, 0xc0, 0xf5, 0x80, 0x31, 0x20, 0x46, - 0xbd, 0xe8, 0x10, 0x40, 0xbe, 0xe7, 0x10, 0xb5, 0x4f, 0xf4, 0xc0, 0x74, - 0xa4, 0xfb, 0x00, 0x23, 0x10, 0x46, 0x05, 0x4a, 0x52, 0x69, 0x04, 0xfb, - 0x01, 0x33, 0x19, 0x46, 0x00, 0x23, 0xf2, 0xf7, 0x01, 0xfe, 0x00, 0xb2, - 0x10, 0xbd, 0x00, 0x00, 0x78, 0x29, 0x00, 0x20, 0xef, 0xf3, 0x11, 0x80, - 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x50, 0x21, 0xee, 0xf7, - 0xa9, 0xbb, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0xf1, 0x34, 0x05, 0x0c, 0x46, - 0xd5, 0xf8, 0x04, 0x80, 0xaf, 0x68, 0x28, 0x68, 0x00, 0xf0, 0x98, 0xf9, - 0x06, 0x46, 0x00, 0xf0, 0x91, 0xf9, 0x01, 0x46, 0x30, 0x46, 0xf2, 0xf7, - 0x83, 0xf9, 0x06, 0x46, 0x31, 0x46, 0xf2, 0xf7, 0x8f, 0xfa, 0xba, 0x49, - 0xf2, 0xf7, 0x94, 0xfb, 0x4c, 0xd8, 0xe8, 0x68, 0x00, 0xf0, 0x86, 0xf9, - 0x80, 0x46, 0x68, 0x69, 0x00, 0xf0, 0x7f, 0xf9, 0x01, 0x46, 0x40, 0x46, - 0xf2, 0xf7, 0x70, 0xf9, 0x00, 0xf0, 0x48, 0xf8, 0x20, 0x60, 0x29, 0x69, - 0x68, 0x68, 0xf2, 0xf7, 0x79, 0xfa, 0x07, 0x46, 0xa9, 0x69, 0xa8, 0x68, - 0xf2, 0xf7, 0x74, 0xfa, 0x00, 0xf0, 0xd8, 0xf8, 0x00, 0xf0, 0x3a, 0xf8, - 0x60, 0x60, 0x69, 0x69, 0x28, 0x68, 0xf2, 0xf7, 0x6b, 0xfa, 0x07, 0x46, - 0xe9, 0x68, 0xa8, 0x68, 0xf2, 0xf7, 0x66, 0xfa, 0x00, 0xf0, 0xca, 0xf8, - 0x00, 0xf0, 0x2c, 0xf8, 0xa0, 0x60, 0xa9, 0x69, 0x28, 0x68, 0xf2, 0xf7, - 0x5d, 0xfa, 0x07, 0x46, 0x29, 0x69, 0xa8, 0x68, 0xf2, 0xf7, 0x58, 0xfa, - 0x00, 0xf0, 0xbc, 0xf8, 0x00, 0xf0, 0x1e, 0xf8, 0xe0, 0x60, 0x66, 0x68, - 0x27, 0x68, 0x29, 0x68, 0x68, 0x68, 0xf2, 0xf7, 0xb1, 0xf9, 0x05, 0x46, - 0x00, 0xf0, 0x44, 0xf9, 0x07, 0x46, 0x30, 0x46, 0x31, 0x46, 0xf2, 0xf7, - 0x45, 0xfa, 0x39, 0x46, 0xf2, 0xf7, 0xa6, 0xf9, 0x00, 0xf0, 0xa3, 0xf8, - 0x20, 0x61, 0x05, 0xe0, 0x20, 0x46, 0xbd, 0xe8, 0xf0, 0x41, 0x14, 0x21, - 0xee, 0xf7, 0x3c, 0xbb, 0xbd, 0xe8, 0xf0, 0x81, 0x31, 0x46, 0xf2, 0xf7, - 0xa5, 0xb8, 0x30, 0xb5, 0x0c, 0x46, 0x15, 0x46, 0x85, 0xb0, 0x29, 0x46, - 0xff, 0xf7, 0x87, 0xff, 0x69, 0x46, 0x20, 0x46, 0xff, 0xf7, 0x83, 0xff, - 0x28, 0x68, 0x00, 0x99, 0xf2, 0xf7, 0x14, 0xf9, 0x28, 0x60, 0x01, 0x99, - 0x68, 0x68, 0xf2, 0xf7, 0x0f, 0xf9, 0x68, 0x60, 0x02, 0x99, 0xa8, 0x68, - 0xf2, 0xf7, 0x0a, 0xf9, 0xa8, 0x60, 0x03, 0x99, 0xe8, 0x68, 0xf2, 0xf7, - 0x05, 0xf9, 0xe8, 0x60, 0x29, 0x69, 0x04, 0x98, 0xf2, 0xf7, 0x74, 0xf9, - 0x28, 0x61, 0x05, 0xb0, 0x30, 0xbd, 0x10, 0xb5, 0x04, 0x46, 0x79, 0x48, - 0xf2, 0xf7, 0x08, 0xfa, 0x78, 0x49, 0x41, 0xf8, 0x24, 0x00, 0x10, 0xbd, - 0x2d, 0xe9, 0xf0, 0x4f, 0x82, 0x46, 0x83, 0xb0, 0x0f, 0x46, 0x14, 0x46, - 0x01, 0x20, 0xf7, 0xf7, 0xe9, 0xff, 0x3d, 0x68, 0x7e, 0x68, 0xd7, 0xf8, - 0x08, 0xb0, 0xff, 0x68, 0x80, 0x46, 0x89, 0x46, 0x28, 0x46, 0x00, 0xf0, - 0x54, 0xf8, 0x00, 0x90, 0x31, 0x46, 0x30, 0x46, 0xf2, 0xf7, 0xec, 0xf9, - 0x00, 0x99, 0xf2, 0xf7, 0x4d, 0xf9, 0x01, 0x90, 0x59, 0x46, 0x58, 0x46, - 0xf2, 0xf7, 0xe4, 0xf9, 0x00, 0x90, 0x39, 0x46, 0x38, 0x46, 0xf2, 0xf7, - 0xdf, 0xf9, 0x00, 0x99, 0xf2, 0xf7, 0x40, 0xf9, 0x01, 0x46, 0x01, 0x98, - 0xf2, 0xf7, 0x4a, 0xf8, 0xf2, 0xf7, 0x7c, 0xf9, 0x60, 0x49, 0xf2, 0xf7, - 0x37, 0xf9, 0x60, 0x49, 0xf2, 0xf7, 0xd0, 0xf9, 0x60, 0x60, 0x59, 0x46, - 0x28, 0x46, 0xf2, 0xf7, 0xcb, 0xf9, 0x00, 0x90, 0x39, 0x46, 0x30, 0x46, - 0xf2, 0xf7, 0xc6, 0xf9, 0x00, 0x99, 0xf2, 0xf7, 0x27, 0xf9, 0x00, 0x90, - 0x39, 0x46, 0x28, 0x46, 0xf2, 0xf7, 0xbe, 0xf9, 0x07, 0x46, 0x30, 0x46, - 0x59, 0x46, 0xf2, 0xf7, 0xb9, 0xf9, 0x00, 0xf0, 0x1d, 0xf8, 0x01, 0x46, - 0x00, 0x98, 0xf2, 0xf7, 0x25, 0xf8, 0x4e, 0x49, 0x51, 0xf8, 0x2a, 0x10, - 0xf2, 0xf7, 0xae, 0xf9, 0x05, 0x46, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, - 0xdd, 0xff, 0x4c, 0x49, 0xf2, 0xf7, 0x18, 0xf8, 0x01, 0x46, 0x28, 0x46, - 0xf2, 0xf7, 0x14, 0xf8, 0x80, 0xf0, 0x00, 0x40, 0x20, 0x60, 0xbd, 0xe8, - 0xf7, 0x8f, 0x29, 0x46, 0xf2, 0xf7, 0x9a, 0xb9, 0x01, 0x46, 0x38, 0x46, - 0xf2, 0xf7, 0x86, 0xb8, 0x2d, 0xe9, 0xf2, 0x4f, 0x82, 0xb0, 0xd7, 0x68, - 0xd2, 0xf8, 0x00, 0x80, 0x95, 0x68, 0x56, 0x68, 0x00, 0xf1, 0x34, 0x04, - 0x40, 0x46, 0x00, 0xf0, 0x84, 0xf8, 0x81, 0x46, 0x30, 0x46, 0xff, 0xf7, - 0xe8, 0xff, 0x01, 0x46, 0x48, 0x46, 0xf2, 0xf7, 0x71, 0xf8, 0x81, 0x46, - 0x20, 0x69, 0x01, 0x90, 0x38, 0x46, 0xd4, 0xf8, 0x0c, 0xa0, 0x51, 0x46, - 0xf2, 0xf7, 0x78, 0xf9, 0x83, 0x46, 0x01, 0x98, 0xff, 0xf7, 0xd7, 0xff, - 0x01, 0x46, 0x58, 0x46, 0xf2, 0xf7, 0x60, 0xf8, 0x00, 0xf0, 0x62, 0xf8, - 0x83, 0x46, 0x01, 0x98, 0x00, 0xf0, 0x68, 0xf8, 0x00, 0x90, 0x51, 0x46, - 0x30, 0x46, 0xf2, 0xf7, 0x65, 0xf9, 0x01, 0x46, 0x00, 0x98, 0xf2, 0xf7, - 0x51, 0xf8, 0x00, 0xf0, 0x53, 0xf8, 0x82, 0x46, 0xa0, 0x69, 0x00, 0x90, - 0x38, 0x46, 0x64, 0x69, 0x00, 0xf0, 0x4f, 0xf8, 0x07, 0x46, 0x00, 0x98, - 0xff, 0xf7, 0xb7, 0xff, 0xff, 0xf7, 0xb8, 0xff, 0x00, 0xf0, 0x44, 0xf8, - 0x05, 0x46, 0x00, 0x98, 0x00, 0xf0, 0x4a, 0xf8, 0x07, 0x46, 0x30, 0x46, - 0x00, 0xf0, 0x3f, 0xf8, 0xff, 0xf7, 0xac, 0xff, 0x00, 0xf0, 0x38, 0xf8, - 0x04, 0x46, 0x28, 0x46, 0x00, 0xf0, 0x37, 0xf8, 0x06, 0x46, 0x58, 0x46, - 0x51, 0x46, 0xf2, 0xf7, 0x3b, 0xf9, 0x31, 0x46, 0xf2, 0xf7, 0x9c, 0xf8, - 0x06, 0x46, 0x28, 0x46, 0x51, 0x46, 0xf2, 0xf7, 0x33, 0xf9, 0x05, 0x46, - 0x58, 0x46, 0x00, 0xf0, 0x26, 0xf8, 0x01, 0x46, 0x28, 0x46, 0xf2, 0xf7, - 0x1b, 0xf8, 0x01, 0x46, 0x30, 0x46, 0xf1, 0xf7, 0x99, 0xff, 0x04, 0x46, - 0x02, 0x98, 0xf1, 0xf7, 0x7b, 0xff, 0x0a, 0x49, 0xf2, 0xf7, 0x20, 0xf9, - 0x00, 0xf0, 0x15, 0xf8, 0xbd, 0xe8, 0xfe, 0x4f, 0xf2, 0xf7, 0x86, 0xb9, - 0x00, 0x24, 0x74, 0x49, 0x00, 0xcc, 0x6e, 0x46, 0x84, 0xb8, 0x00, 0x20, - 0x00, 0x00, 0x80, 0xbf, 0x00, 0xff, 0x7f, 0x47, 0x28, 0x6b, 0x6e, 0x4e, - 0x00, 0x30, 0x81, 0x45, 0x49, 0x46, 0xf1, 0xf7, 0x7b, 0xbf, 0x21, 0x46, - 0xf2, 0xf7, 0x06, 0xb9, 0x38, 0x46, 0x39, 0x46, 0xf2, 0xf7, 0x02, 0xb9, - 0x41, 0x46, 0xf2, 0xf7, 0xff, 0xb8, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0xff, 0xf7, 0x4c, 0xfe, 0x06, 0x46, 0x20, 0x46, 0xee, 0xf7, 0xa0, 0xfb, - 0x07, 0x46, 0x35, 0xf9, 0x17, 0x20, 0x00, 0x21, 0x20, 0x46, 0xf0, 0xf7, - 0x57, 0xff, 0x05, 0xeb, 0x47, 0x00, 0x01, 0x21, 0xb0, 0xf9, 0x80, 0x20, - 0x20, 0x46, 0xf0, 0xf7, 0x4f, 0xff, 0x00, 0x20, 0x85, 0xf8, 0x02, 0x01, - 0x86, 0xf3, 0x11, 0x88, 0xf1, 0xbd, 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, - 0x17, 0x46, 0x1e, 0x46, 0xff, 0xf7, 0x2c, 0xfe, 0x06, 0x99, 0xfa, 0x07, - 0x44, 0xbf, 0x0a, 0x88, 0x25, 0xf8, 0x16, 0x20, 0xba, 0x07, 0x04, 0xd5, - 0x49, 0x88, 0x05, 0xeb, 0x46, 0x02, 0xa2, 0xf8, 0x80, 0x10, 0x80, 0xf3, - 0x11, 0x88, 0x29, 0x46, 0x20, 0x46, 0xbd, 0xe8, 0xf4, 0x40, 0xc6, 0xe7, - 0xf8, 0xb5, 0x04, 0x46, 0x0d, 0x46, 0x16, 0x46, 0xff, 0xf7, 0x12, 0xfe, - 0x07, 0x46, 0x20, 0x46, 0xee, 0xf7, 0x66, 0xfb, 0xa9, 0x19, 0x91, 0xf8, - 0x02, 0x21, 0x01, 0x2a, 0x18, 0xbf, 0x40, 0xf0, 0x00, 0x40, 0x01, 0x22, - 0x81, 0xf8, 0x02, 0x21, 0x87, 0xf3, 0x11, 0x88, 0xf2, 0xbd, 0xf0, 0xb5, - 0x30, 0xf9, 0x11, 0x30, 0x30, 0xf9, 0x12, 0x40, 0x4d, 0x1c, 0x09, 0xe0, - 0xe6, 0x1a, 0x6f, 0x1a, 0x7e, 0x43, 0x57, 0x1a, 0x96, 0xfb, 0xf7, 0xf6, - 0x9e, 0x19, 0x20, 0xf8, 0x15, 0x60, 0x6d, 0x1c, 0x95, 0x42, 0xf3, 0xdb, - 0xf0, 0xbd, 0x00, 0x00, 0x2d, 0xe9, 0xf0, 0x41, 0x05, 0x46, 0x0f, 0x46, - 0x16, 0x46, 0x98, 0x46, 0x00, 0x24, 0xef, 0xf7, 0xa8, 0xfc, 0x08, 0xb1, - 0x02, 0x24, 0x0d, 0xe0, 0x05, 0xf1, 0x8c, 0x40, 0x07, 0xea, 0x06, 0x01, - 0x00, 0x78, 0x38, 0x40, 0x88, 0x42, 0x05, 0xd0, 0x40, 0x46, 0xf1, 0xf7, - 0x75, 0xfe, 0x00, 0x28, 0xed, 0xd0, 0x01, 0x24, 0x20, 0x46, 0xbd, 0xe8, - 0xf0, 0x81, 0x10, 0xb5, 0x4f, 0xf4, 0x7a, 0x71, 0x00, 0x20, 0xf1, 0xf7, - 0x51, 0xfe, 0x00, 0x23, 0x00, 0x22, 0x40, 0x21, 0x40, 0xf6, 0xff, 0x50, - 0xff, 0xf7, 0xd6, 0xff, 0x04, 0x46, 0x00, 0x20, 0xf1, 0xf7, 0xd6, 0xfd, - 0x01, 0x2c, 0x16, 0xbf, 0x03, 0x2c, 0x01, 0x20, 0x00, 0x20, 0x10, 0xbd, - 0x10, 0xb5, 0x01, 0x21, 0x01, 0xfa, 0x00, 0xf0, 0x40, 0xf0, 0x80, 0x04, - 0xe1, 0xb2, 0x40, 0xf6, 0xff, 0x50, 0xee, 0xf7, 0x9d, 0xf9, 0x44, 0xf0, - 0x40, 0x00, 0xc0, 0xb2, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, - 0x88, 0x46, 0x10, 0x46, 0xff, 0xf7, 0xea, 0xff, 0x00, 0x27, 0x00, 0x26, - 0x12, 0xe0, 0x00, 0x20, 0x24, 0xf8, 0x16, 0x00, 0x00, 0x25, 0x00, 0xf0, - 0x44, 0xf8, 0x47, 0x48, 0x00, 0x78, 0x34, 0xf8, 0x16, 0x10, 0xa8, 0x40, - 0x7f, 0x1c, 0x08, 0x43, 0x08, 0x35, 0x24, 0xf8, 0x16, 0x00, 0x09, 0x2d, - 0xf1, 0xd3, 0x76, 0x1c, 0x46, 0x45, 0xea, 0xd3, 0xbd, 0xe8, 0xf0, 0x41, - 0x00, 0x21, 0x40, 0xf6, 0xff, 0x50, 0xee, 0xf7, 0x73, 0xb9, 0x2d, 0xe9, - 0xf8, 0x4f, 0x80, 0x46, 0x8a, 0x46, 0x10, 0x46, 0xff, 0xf7, 0xc4, 0xff, - 0x00, 0x26, 0x00, 0x27, 0x83, 0x46, 0x00, 0x24, 0x40, 0xf6, 0xff, 0x59, - 0x16, 0xe0, 0x00, 0x25, 0x00, 0xf0, 0x1d, 0xf8, 0x38, 0xf9, 0x14, 0x00, - 0x28, 0x41, 0xc1, 0xb2, 0x4f, 0xf4, 0x60, 0x60, 0xee, 0xf7, 0x5a, 0xf9, - 0x59, 0x46, 0x48, 0x46, 0xee, 0xf7, 0x56, 0xf9, 0xff, 0xf7, 0x95, 0xff, - 0x7f, 0x1c, 0x06, 0x43, 0x08, 0x35, 0x09, 0x2d, 0xea, 0xd3, 0x64, 0x1c, - 0x54, 0x45, 0xe6, 0xd3, 0x00, 0x21, 0x48, 0x46, 0xee, 0xf7, 0x48, 0xf9, - 0x30, 0x46, 0xbd, 0xe8, 0xf2, 0x8f, 0xf9, 0xb2, 0x40, 0xf6, 0x01, 0x60, - 0xee, 0xf7, 0x40, 0xb9, 0x2d, 0xe9, 0xf0, 0x41, 0x04, 0x46, 0xff, 0xf7, - 0x93, 0xff, 0x06, 0x46, 0x20, 0x46, 0x00, 0xf0, 0x1f, 0xf8, 0x44, 0x00, - 0x00, 0x25, 0xa4, 0xb2, 0x00, 0x27, 0x40, 0xf6, 0xff, 0x58, 0x0e, 0xe0, - 0xff, 0xf7, 0xe9, 0xff, 0x00, 0x21, 0x4f, 0xf4, 0x60, 0x60, 0xee, 0xf7, - 0x29, 0xf9, 0x31, 0x46, 0x40, 0x46, 0xee, 0xf7, 0x25, 0xf9, 0xff, 0xf7, - 0x64, 0xff, 0x05, 0x43, 0x7f, 0x1c, 0xa7, 0x42, 0xee, 0xd3, 0x00, 0x21, - 0x40, 0x46, 0xee, 0xf7, 0x1b, 0xf9, 0x28, 0x46, 0xbd, 0xe8, 0xf0, 0x81, - 0x18, 0x21, 0x04, 0x28, 0x0e, 0x4a, 0x12, 0xd8, 0xdf, 0xe8, 0x00, 0xf0, - 0x03, 0x03, 0x09, 0x09, 0x0d, 0x00, 0x0c, 0x48, 0x00, 0x78, 0x40, 0x09, - 0x40, 0x1c, 0x00, 0x01, 0x70, 0x47, 0x10, 0x78, 0xc0, 0xf3, 0x41, 0x10, - 0x06, 0xe0, 0x10, 0x78, 0xc0, 0xf3, 0x41, 0x00, 0x02, 0xe0, 0x10, 0x78, - 0xc0, 0xf3, 0xc1, 0x00, 0x40, 0x1c, 0x48, 0x43, 0x70, 0x47, 0x00, 0x00, - 0x00, 0x0e, 0x00, 0x46, 0x10, 0x04, 0x00, 0x46, 0x10, 0x09, 0x00, 0x46, - 0xef, 0xf3, 0x11, 0x80, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, - 0x2d, 0xe9, 0xf0, 0x47, 0xad, 0xf5, 0x08, 0x7d, 0x04, 0x46, 0x4f, 0xf0, - 0x00, 0x08, 0xdf, 0xf8, 0xbc, 0x93, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, - 0x36, 0xfb, 0x20, 0x88, 0x01, 0xa9, 0xf1, 0xf7, 0x94, 0xf8, 0xa2, 0x69, - 0x12, 0x78, 0x21, 0x88, 0xa0, 0x68, 0x52, 0x1e, 0x12, 0x04, 0x02, 0xf4, - 0xfe, 0x02, 0x42, 0xea, 0x81, 0x71, 0xa2, 0x78, 0xd2, 0x05, 0x02, 0xf0, - 0x7e, 0x52, 0x11, 0x43, 0x42, 0x78, 0x00, 0x79, 0xd2, 0x03, 0x02, 0xf4, - 0x00, 0x42, 0x11, 0x43, 0x00, 0xf0, 0x07, 0x00, 0x08, 0x43, 0x40, 0xf0, - 0x00, 0x40, 0x40, 0xf4, 0x80, 0x40, 0xf0, 0xf7, 0x8c, 0xfe, 0xa0, 0x69, - 0x40, 0x78, 0xf0, 0xf7, 0xab, 0xfe, 0x00, 0x27, 0x00, 0x25, 0x04, 0xeb, - 0x85, 0x00, 0x06, 0x69, 0x6d, 0xb1, 0x00, 0x2f, 0x02, 0xbf, 0xe0, 0x69, - 0x00, 0x68, 0x00, 0x28, 0x4b, 0xd1, 0x20, 0x88, 0x01, 0x21, 0xc0, 0xb2, - 0xf0, 0xf7, 0x77, 0xfd, 0x02, 0x20, 0xf1, 0xf7, 0xeb, 0xfc, 0x00, 0xf0, - 0x18, 0xf9, 0x0f, 0xfa, 0x80, 0xfa, 0x30, 0x6b, 0x82, 0x45, 0x18, 0xd0, - 0x04, 0xa8, 0x31, 0x46, 0x50, 0x22, 0xf4, 0xf7, 0xd3, 0xfe, 0x30, 0x46, - 0x06, 0xf1, 0x50, 0x01, 0x50, 0x22, 0xf4, 0xf7, 0xcd, 0xfe, 0x06, 0xf1, - 0x50, 0x00, 0x04, 0xa9, 0x50, 0x22, 0xf4, 0xf7, 0xc7, 0xfe, 0x30, 0x6b, - 0x82, 0x45, 0x04, 0xd0, 0x30, 0x46, 0xff, 0xf7, 0x9f, 0xfc, 0xc6, 0xf8, - 0x30, 0xa0, 0xf0, 0xf7, 0xfa, 0xfd, 0xf0, 0xf7, 0x14, 0xfe, 0x02, 0x28, - 0x06, 0xd1, 0xe0, 0x69, 0x81, 0x8a, 0x09, 0x04, 0x41, 0xf0, 0x01, 0x01, - 0x01, 0x60, 0x02, 0xe0, 0x01, 0x28, 0x08, 0xbf, 0x01, 0x27, 0x00, 0xf0, - 0xe8, 0xf8, 0x06, 0x46, 0x17, 0xb9, 0xef, 0xf7, 0x46, 0xfb, 0x00, 0xe0, - 0x01, 0x20, 0x36, 0xb2, 0x40, 0xea, 0xd6, 0x77, 0x18, 0xa8, 0xe0, 0x21, - 0x01, 0xfb, 0x05, 0x00, 0xf0, 0xf7, 0x9a, 0xfe, 0x6d, 0x1c, 0x02, 0x2d, - 0xa9, 0xd3, 0x01, 0xa8, 0xf1, 0xf7, 0x67, 0xf8, 0x00, 0x20, 0xee, 0xf7, - 0x0f, 0xfb, 0xe0, 0x69, 0x00, 0x68, 0x00, 0x28, 0x4a, 0xd1, 0x00, 0x2f, - 0x42, 0xd1, 0xa0, 0x78, 0xf0, 0xf7, 0x2c, 0xfe, 0x02, 0x46, 0xa0, 0x68, - 0x62, 0x64, 0xc1, 0x68, 0x18, 0xa8, 0xf0, 0xf7, 0xaf, 0xff, 0x98, 0xb3, - 0x62, 0x6c, 0x20, 0x69, 0x18, 0xa9, 0xf0, 0xf7, 0x85, 0xfe, 0x62, 0x6c, - 0x60, 0x69, 0x50, 0xa9, 0xf0, 0xf7, 0x80, 0xfe, 0x61, 0x69, 0x20, 0x69, - 0x04, 0xf1, 0x28, 0x02, 0xff, 0xf7, 0xc7, 0xfc, 0xa0, 0x6b, 0x49, 0x46, - 0xf1, 0xf7, 0xf6, 0xfe, 0x05, 0x46, 0x61, 0x68, 0x97, 0x48, 0xf1, 0xf7, - 0xf1, 0xfe, 0x01, 0x46, 0x28, 0x46, 0xf1, 0xf7, 0x5f, 0xfd, 0x80, 0x46, - 0xff, 0xf7, 0x38, 0xff, 0x07, 0x46, 0xe0, 0x69, 0xc1, 0x8a, 0x49, 0x1c, - 0xc1, 0x82, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, 0xe9, 0xff, 0x98, 0xbf, - 0x64, 0x20, 0x02, 0xd9, 0xf1, 0xf7, 0x48, 0xff, 0x80, 0xb2, 0xe1, 0x69, - 0x48, 0x60, 0x87, 0xf3, 0x11, 0x88, 0x03, 0xe0, 0xa0, 0x68, 0x80, 0x68, - 0xed, 0xf7, 0x7a, 0xfd, 0x40, 0x46, 0x49, 0x46, 0xf1, 0xf7, 0xbc, 0xfe, - 0xff, 0xf4, 0x29, 0xaf, 0xe0, 0x69, 0x00, 0x68, 0x00, 0x28, 0x72, 0xd1, - 0x20, 0x88, 0x03, 0x22, 0x04, 0xf1, 0x24, 0x01, 0xf0, 0xf7, 0x07, 0xfe, - 0xb4, 0xf9, 0x24, 0x60, 0xb4, 0xf9, 0x26, 0x90, 0x20, 0x88, 0x04, 0xf1, - 0x3c, 0x02, 0x04, 0xf1, 0x28, 0x01, 0xff, 0xf7, 0xb3, 0xfc, 0x27, 0x6c, - 0x38, 0x46, 0x00, 0x21, 0xf1, 0xf7, 0xa0, 0xfe, 0x38, 0xbf, 0x87, 0xf0, - 0x00, 0x47, 0xe0, 0x6b, 0xf1, 0xf7, 0x9a, 0xfe, 0x38, 0xbf, 0x80, 0xf0, - 0x00, 0x40, 0x39, 0x46, 0xf1, 0xf7, 0x0a, 0xfe, 0xf8, 0xf7, 0xa4, 0xfd, - 0x05, 0x46, 0x21, 0x46, 0x00, 0x20, 0x00, 0xf0, 0x59, 0xf8, 0x21, 0x46, - 0x01, 0x20, 0x00, 0xf0, 0x55, 0xf8, 0xb4, 0xf9, 0x26, 0x00, 0xb0, 0xf5, - 0x00, 0x5f, 0xa8, 0xbf, 0x41, 0xf6, 0xff, 0x70, 0x03, 0xda, 0x10, 0xf5, - 0x00, 0x5f, 0x01, 0xda, 0x66, 0x48, 0xe0, 0x84, 0xb4, 0xf9, 0x24, 0x00, - 0xb0, 0xf5, 0x80, 0x6f, 0xa8, 0xbf, 0x40, 0xf2, 0xff, 0x30, 0x02, 0xda, - 0x00, 0x28, 0x01, 0xd5, 0x00, 0x20, 0xa0, 0x84, 0xff, 0xf7, 0xce, 0xfe, - 0x07, 0x46, 0xb4, 0xf9, 0x26, 0x00, 0x48, 0x45, 0x04, 0xbf, 0xb4, 0xf9, - 0x24, 0x00, 0xb0, 0x42, 0x13, 0xd0, 0x04, 0xf1, 0x24, 0x00, 0x00, 0x90, - 0x03, 0x22, 0x60, 0x69, 0x03, 0x6b, 0xe1, 0x68, 0x20, 0x88, 0xff, 0xf7, - 0x8c, 0xfd, 0x22, 0x88, 0x20, 0x6a, 0x01, 0x21, 0x91, 0x40, 0x08, 0x43, - 0x20, 0x62, 0xe0, 0x69, 0x01, 0x69, 0x49, 0x1c, 0x01, 0x61, 0x64, 0x20, - 0xe1, 0x69, 0x48, 0x60, 0xe0, 0x69, 0x85, 0x60, 0xe0, 0x69, 0xc1, 0x68, - 0x49, 0x1c, 0xc1, 0x60, 0xe0, 0x69, 0xc1, 0x8a, 0x01, 0x83, 0x87, 0xf3, - 0x11, 0x88, 0x20, 0x69, 0xff, 0xf7, 0xaa, 0xfb, 0x60, 0x69, 0xff, 0xf7, - 0xa7, 0xfb, 0x0d, 0xf5, 0x08, 0x7d, 0xbd, 0xe8, 0xf0, 0x87, 0xe2, 0x68, - 0x20, 0x88, 0x00, 0x21, 0xff, 0xf7, 0x80, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, - 0x8e, 0x68, 0x00, 0x28, 0xb0, 0x7c, 0x07, 0xbf, 0xcd, 0x6b, 0x01, 0xf1, - 0x24, 0x04, 0x0d, 0x6c, 0x01, 0xf1, 0x26, 0x04, 0x80, 0xb1, 0x28, 0x46, - 0x00, 0x21, 0xf1, 0xf7, 0x3d, 0xff, 0x38, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, - 0x04, 0xd3, 0xf1, 0xf7, 0x1d, 0xfe, 0x05, 0xd2, 0x4f, 0xf0, 0x3f, 0x40, - 0x29, 0x46, 0xf1, 0xf7, 0x8d, 0xfd, 0x05, 0x46, 0x36, 0x7c, 0x27, 0x88, - 0x30, 0x09, 0xf1, 0xf7, 0x85, 0xfc, 0x80, 0x46, 0x06, 0xf0, 0x0f, 0x00, - 0xf1, 0xf7, 0x76, 0xfc, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0x8c, 0xfc, - 0x29, 0x46, 0xf1, 0xf7, 0x17, 0xfe, 0xf1, 0xf7, 0x81, 0xfe, 0xc0, 0x19, - 0x20, 0x80, 0xbd, 0xe8, 0xf0, 0x81, 0xfe, 0xb5, 0x0d, 0x46, 0x06, 0x46, - 0x28, 0x68, 0x00, 0x28, 0x41, 0xd0, 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, - 0x9e, 0xf9, 0x30, 0x88, 0x69, 0x46, 0xf0, 0xf7, 0xfc, 0xfe, 0x28, 0x68, - 0xc0, 0xf3, 0x07, 0x20, 0xc0, 0xb1, 0x95, 0xf9, 0x01, 0x00, 0x1e, 0x49, - 0x01, 0xfb, 0x00, 0xf4, 0x30, 0x88, 0x02, 0x21, 0xc0, 0xb2, 0xf0, 0xf7, - 0xe5, 0xfa, 0x30, 0x88, 0x1a, 0x49, 0x00, 0x28, 0x14, 0xbf, 0x02, 0x20, - 0x01, 0x20, 0xd1, 0xe9, 0x08, 0x67, 0x32, 0x19, 0x47, 0xeb, 0xe4, 0x73, - 0xf8, 0xf7, 0x79, 0xfc, 0xf8, 0xf7, 0x54, 0xfc, 0x14, 0x48, 0x04, 0x78, - 0x40, 0xf6, 0x41, 0x46, 0x00, 0x22, 0xc0, 0x21, 0x30, 0x46, 0xf0, 0xf7, - 0xfb, 0xf8, 0x01, 0x20, 0x68, 0x60, 0x28, 0x68, 0x18, 0xb1, 0xef, 0xf7, - 0xee, 0xf9, 0x00, 0x28, 0xf9, 0xd0, 0x00, 0x20, 0x68, 0x60, 0x21, 0x46, - 0x30, 0x46, 0xf0, 0xf7, 0xc6, 0xf8, 0x68, 0x46, 0xf0, 0xf7, 0x15, 0xff, - 0x00, 0x20, 0xee, 0xf7, 0xbd, 0xf9, 0x00, 0x20, 0xfe, 0xbd, 0x00, 0x00, - 0x00, 0x00, 0xc8, 0x42, 0xb7, 0x43, 0xba, 0x51, 0x00, 0xe0, 0xff, 0xff, - 0x40, 0x42, 0x0f, 0x00, 0x00, 0xf2, 0x00, 0x20, 0x41, 0x0c, 0x00, 0x46, - 0x2d, 0xe9, 0xf0, 0x47, 0xc0, 0x48, 0x04, 0x78, 0x45, 0x78, 0x86, 0x78, - 0xc7, 0x78, 0x90, 0xf8, 0x08, 0x80, 0x90, 0xf8, 0x09, 0x90, 0xbd, 0x48, - 0x00, 0x6a, 0xf1, 0xf7, 0x0d, 0xfc, 0x01, 0x46, 0xbb, 0x48, 0xf1, 0xf7, - 0x19, 0xfc, 0x82, 0x46, 0x07, 0xf0, 0x0f, 0x00, 0x06, 0xeb, 0x00, 0x20, - 0xf1, 0xf7, 0x02, 0xfc, 0x06, 0x46, 0x09, 0xf0, 0x0f, 0x00, 0x08, 0xeb, - 0x00, 0x20, 0xf1, 0xf7, 0xfb, 0xfb, 0x01, 0x46, 0x30, 0x46, 0xf1, 0xf7, - 0x07, 0xfc, 0x06, 0x46, 0x04, 0xeb, 0x05, 0x20, 0xf1, 0xf7, 0xe8, 0xfb, - 0x4f, 0xf0, 0x76, 0x51, 0xf1, 0xf7, 0x8c, 0xfd, 0x31, 0x46, 0xf1, 0xf7, - 0x89, 0xfd, 0x51, 0x46, 0xf1, 0xf7, 0x86, 0xfd, 0xf1, 0xf7, 0xf0, 0xfd, - 0x80, 0xf3, 0x09, 0x04, 0xa0, 0x05, 0x01, 0x0e, 0x40, 0xf6, 0xad, 0x10, - 0xed, 0xf7, 0xbe, 0xfe, 0x04, 0xf0, 0x03, 0x01, 0xbd, 0xe8, 0xf0, 0x47, - 0x40, 0xf6, 0xae, 0x10, 0xed, 0xf7, 0xb6, 0xbe, 0x10, 0xb5, 0xf1, 0xf7, - 0xe3, 0xfb, 0x4f, 0xf0, 0x81, 0x44, 0x21, 0x46, 0xf1, 0xf7, 0xe3, 0xff, - 0x4f, 0xf0, 0x7e, 0x51, 0xf1, 0xf7, 0xcc, 0xfc, 0x01, 0x21, 0xf8, 0xf7, - 0x6f, 0xfe, 0x9a, 0x49, 0xf1, 0xf7, 0x62, 0xfd, 0x99, 0x49, 0xf1, 0xf7, - 0xc3, 0xfc, 0x99, 0x49, 0xf1, 0xf7, 0xce, 0xfb, 0xf1, 0xf7, 0xc6, 0xfd, - 0xc0, 0xb2, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x0d, 0x46, 0x85, 0xb0, - 0x00, 0x21, 0x00, 0x20, 0xee, 0xf7, 0xe7, 0xf8, 0x92, 0x48, 0x00, 0x78, - 0x00, 0x24, 0xc0, 0x07, 0x00, 0xf1, 0x0c, 0x81, 0x8a, 0x4f, 0x97, 0xf8, - 0x10, 0x80, 0xb8, 0xf1, 0x03, 0x0f, 0xa8, 0xbf, 0x03, 0x24, 0x80, 0xf2, - 0x03, 0x81, 0x0f, 0xf2, 0x68, 0x21, 0x4c, 0xc9, 0x02, 0xa8, 0x40, 0xf2, - 0x01, 0x1a, 0x4c, 0xc0, 0x78, 0x6a, 0xf1, 0xf7, 0x99, 0xfb, 0x87, 0x49, - 0xf1, 0xf7, 0xa6, 0xfb, 0x06, 0x46, 0x86, 0x48, 0x00, 0x6b, 0xf1, 0xf7, - 0x91, 0xfb, 0x81, 0x46, 0x02, 0xa8, 0x84, 0x49, 0x50, 0xf8, 0x28, 0x00, - 0xf1, 0xf7, 0x28, 0xfd, 0x01, 0x46, 0x48, 0x46, 0xf1, 0xf7, 0x96, 0xfb, - 0x80, 0x46, 0xb8, 0x7a, 0x7f, 0x49, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x90, - 0x40, 0xf2, 0xca, 0x2b, 0x40, 0x46, 0xf1, 0xf7, 0x19, 0xfd, 0x31, 0x46, - 0xf1, 0xf7, 0x04, 0xfd, 0x81, 0x46, 0x28, 0xbf, 0xb1, 0x46, 0x48, 0x46, - 0xff, 0xf7, 0x9c, 0xff, 0x8d, 0xf8, 0x04, 0x00, 0x4f, 0xf0, 0x7d, 0x51, - 0x48, 0x46, 0xf1, 0xf7, 0x09, 0xfd, 0x31, 0x46, 0xff, 0xf7, 0x92, 0xff, - 0x07, 0x46, 0x4f, 0xf0, 0x88, 0x41, 0x48, 0x46, 0xf1, 0xf7, 0x00, 0xfd, - 0x41, 0x46, 0xf1, 0xf7, 0x6f, 0xfb, 0xf1, 0xf7, 0x67, 0xfd, 0x80, 0x46, - 0x6c, 0x48, 0x00, 0x78, 0x05, 0xf5, 0x80, 0x79, 0x89, 0xf8, 0x00, 0x00, - 0x6a, 0x48, 0x00, 0x78, 0x89, 0xf8, 0x01, 0x00, 0x69, 0x48, 0x00, 0x78, - 0x89, 0xf8, 0x02, 0x00, 0x00, 0x98, 0x80, 0x01, 0x40, 0xf0, 0x11, 0x01, - 0xc9, 0xb2, 0x50, 0x46, 0xed, 0xf7, 0x26, 0xfe, 0x64, 0x48, 0x00, 0x57, - 0x06, 0x28, 0x0c, 0xbf, 0x01, 0x21, 0x00, 0x21, 0x4f, 0xf4, 0x11, 0x60, - 0xed, 0xf7, 0x1c, 0xfe, 0x6e, 0x21, 0x40, 0xf6, 0xc1, 0x10, 0xed, 0xf7, - 0x17, 0xfe, 0x03, 0x21, 0x40, 0xf6, 0xc2, 0x10, 0xed, 0xf7, 0x12, 0xfe, - 0x03, 0x21, 0x40, 0xf6, 0xac, 0x10, 0xed, 0xf7, 0x0d, 0xfe, 0x12, 0x21, - 0x58, 0x46, 0xed, 0xf7, 0x09, 0xfe, 0x30, 0x46, 0x56, 0x49, 0xf1, 0xf7, - 0xb1, 0xfc, 0x34, 0xbf, 0x02, 0x26, 0x01, 0x26, 0x31, 0x46, 0x4f, 0xf4, - 0x1a, 0x60, 0xed, 0xf7, 0xfd, 0xfd, 0x31, 0x46, 0x40, 0xf6, 0xa1, 0x10, - 0xed, 0xf7, 0xf8, 0xfd, 0x9d, 0xf8, 0x04, 0x10, 0x40, 0xf6, 0xc3, 0x10, - 0xed, 0xf7, 0xf2, 0xfd, 0x39, 0x46, 0x40, 0xf6, 0xc4, 0x10, 0xed, 0xf7, - 0xed, 0xfd, 0x3c, 0x21, 0x40, 0xf6, 0xc5, 0x10, 0xed, 0xf7, 0xe8, 0xfd, - 0x5f, 0xfa, 0x88, 0xf1, 0x40, 0xf6, 0xc6, 0x10, 0xed, 0xf7, 0xe2, 0xfd, - 0x00, 0x21, 0x40, 0xf6, 0xa4, 0x10, 0xed, 0xf7, 0xdd, 0xfd, 0x00, 0x21, - 0x40, 0xf6, 0xa5, 0x10, 0xed, 0xf7, 0xd8, 0xfd, 0x00, 0x21, 0x40, 0xf6, - 0xa8, 0x10, 0xed, 0xf7, 0xd3, 0xfd, 0x00, 0x21, 0x40, 0xf6, 0xa9, 0x10, - 0xed, 0xf7, 0xce, 0xfd, 0x00, 0x26, 0x01, 0x20, 0x00, 0x99, 0xb0, 0x40, - 0x01, 0x42, 0x34, 0xd0, 0x47, 0x1e, 0xf8, 0xb2, 0xff, 0xf7, 0xac, 0xfc, - 0x80, 0x46, 0xfa, 0xb2, 0x1f, 0xfa, 0x88, 0xf1, 0x28, 0x46, 0xff, 0xf7, - 0x24, 0xfc, 0xf8, 0xb2, 0xff, 0xf7, 0x7a, 0xfc, 0x18, 0xbb, 0xfa, 0xb2, - 0x10, 0x21, 0x2f, 0x48, 0xff, 0xf7, 0x41, 0xfc, 0xe8, 0xb9, 0x00, 0x2e, - 0x0c, 0xbf, 0x2d, 0x21, 0x2c, 0x21, 0x4f, 0xf4, 0x1c, 0x60, 0xed, 0xf7, - 0xab, 0xfd, 0x01, 0x22, 0x00, 0xf0, 0x54, 0xf8, 0x28, 0x4b, 0x00, 0x22, - 0x01, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xf4, 0xf7, 0x65, 0xfa, 0x18, 0xb1, - 0x00, 0x22, 0x00, 0xf0, 0x49, 0xf8, 0x02, 0x24, 0xfa, 0xb2, 0x1f, 0xfa, - 0x88, 0xf1, 0x28, 0x46, 0xff, 0xf7, 0x23, 0xfc, 0x08, 0xb1, 0x04, 0x24, - 0x02, 0xe0, 0x76, 0x1c, 0x02, 0x2e, 0xc2, 0xd3, 0x99, 0xf8, 0x00, 0x10, - 0x50, 0x46, 0xed, 0xf7, 0x8b, 0xfd, 0x99, 0xf8, 0x01, 0x10, 0x4f, 0xf4, - 0x11, 0x60, 0xed, 0xf7, 0x85, 0xfd, 0x99, 0xf8, 0x02, 0x10, 0x58, 0x46, - 0xed, 0xf7, 0x80, 0xfd, 0x00, 0x20, 0xee, 0xf7, 0x2f, 0xf8, 0x20, 0x46, - 0x05, 0xb0, 0xbd, 0xe8, 0xf0, 0x8f, 0x00, 0x00, 0xd3, 0x05, 0x00, 0x46, - 0x78, 0x29, 0x00, 0x20, 0xc6, 0xe3, 0x33, 0x4c, 0x00, 0x00, 0x20, 0x41, - 0x00, 0x00, 0x40, 0x40, 0xcd, 0xcc, 0x4c, 0x3d, 0xe8, 0xf2, 0x00, 0x20, - 0x00, 0x00, 0x7a, 0x44, 0x00, 0xf2, 0x00, 0x20, 0x00, 0x00, 0xfa, 0x44, - 0x4e, 0x62, 0xd0, 0x3e, 0x01, 0x01, 0x00, 0x46, 0x10, 0x09, 0x00, 0x46, - 0xca, 0x02, 0x00, 0x46, 0xb8, 0x2a, 0x00, 0x20, 0x00, 0x40, 0x9c, 0x47, - 0xba, 0x2a, 0x00, 0x20, 0x20, 0xa1, 0x07, 0x00, 0x01, 0x21, 0x4f, 0xf4, - 0xd9, 0x70, 0xed, 0xf7, 0x59, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, - 0x00, 0x00, 0x20, 0x40, 0x00, 0x00, 0x80, 0x40, 0x70, 0x47, 0xf0, 0xb5, - 0x0d, 0x46, 0x83, 0xb0, 0x00, 0x21, 0x00, 0x20, 0xed, 0xf7, 0x95, 0xff, - 0x69, 0x46, 0x28, 0x46, 0x00, 0xf0, 0x54, 0xf8, 0x04, 0x00, 0x4c, 0xd1, - 0x00, 0x26, 0x69, 0x4f, 0x07, 0xeb, 0x46, 0x12, 0xf1, 0xb2, 0x28, 0x46, - 0x00, 0xf0, 0xe8, 0xf8, 0x76, 0x1c, 0x04, 0x2e, 0xf6, 0xdb, 0x07, 0xf1, - 0x80, 0x05, 0x40, 0xf2, 0xdd, 0x50, 0x29, 0x78, 0xed, 0xf7, 0x28, 0xfd, - 0x69, 0x78, 0x40, 0xf2, 0xde, 0x50, 0xed, 0xf7, 0x23, 0xfd, 0xa9, 0x78, - 0x40, 0xf2, 0xdf, 0x50, 0xed, 0xf7, 0x1e, 0xfd, 0xe9, 0x78, 0x4f, 0xf4, - 0xbc, 0x60, 0xed, 0xf7, 0x19, 0xfd, 0x29, 0x79, 0x40, 0xf2, 0xe1, 0x50, - 0xed, 0xf7, 0x14, 0xfd, 0x57, 0x48, 0x58, 0x4a, 0x01, 0x78, 0x40, 0x78, - 0x93, 0x78, 0xd5, 0x78, 0x43, 0xea, 0x05, 0x23, 0x15, 0x78, 0x52, 0x78, - 0x41, 0xea, 0x00, 0x20, 0x45, 0xea, 0x02, 0x21, 0xc0, 0x1a, 0xc9, 0x1a, - 0x00, 0x01, 0x49, 0x1c, 0x90, 0xfb, 0xf1, 0xf1, 0x89, 0xb2, 0x10, 0x29, - 0xa8, 0xbf, 0x0f, 0x21, 0xc9, 0xb2, 0x4f, 0xf4, 0x09, 0x70, 0xed, 0xf7, - 0xf7, 0xfc, 0x4b, 0x48, 0x80, 0x7a, 0x03, 0x21, 0x08, 0x42, 0x04, 0xd0, - 0xff, 0xf7, 0xf4, 0xfd, 0x68, 0x46, 0xf0, 0xf7, 0xe2, 0xf8, 0x00, 0x20, - 0xed, 0xf7, 0x9c, 0xff, 0x20, 0x46, 0xfe, 0xbd, 0x2d, 0xe9, 0xf0, 0x41, - 0x04, 0x46, 0x0d, 0x46, 0x00, 0x22, 0x03, 0x21, 0x40, 0xf2, 0xd1, 0x50, - 0xed, 0xf7, 0xe8, 0xfc, 0x4f, 0xf4, 0x7a, 0x70, 0xf1, 0xf7, 0x1e, 0xf9, - 0xc0, 0x22, 0xc0, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xed, 0xf7, 0xde, 0xfc, - 0x41, 0xf2, 0x88, 0x33, 0x00, 0x22, 0xc0, 0x21, 0x4f, 0xf4, 0xd9, 0x70, - 0xf4, 0xf7, 0x90, 0xf9, 0x08, 0xb1, 0x01, 0x20, 0x60, 0xe0, 0x35, 0x4e, - 0x70, 0x79, 0xb1, 0x79, 0xf2, 0x79, 0x33, 0x7a, 0x37, 0x78, 0x01, 0xf0, - 0x07, 0x01, 0x40, 0xea, 0x01, 0x20, 0x03, 0xf0, 0x07, 0x01, 0x42, 0xea, - 0x01, 0x21, 0x08, 0x18, 0x80, 0xb2, 0x07, 0xf0, 0x3f, 0x01, 0xc1, 0xeb, - 0x50, 0x07, 0x2c, 0x48, 0x2c, 0x49, 0x00, 0x78, 0x09, 0x6b, 0x40, 0x07, - 0x4c, 0xbf, 0x2b, 0x48, 0x2b, 0x48, 0xb1, 0xfb, 0xf0, 0xf0, 0x00, 0x04, - 0xc0, 0x0a, 0xf1, 0xf7, 0xbd, 0xf9, 0x80, 0x46, 0xb8, 0xb2, 0xf1, 0xf7, - 0xc3, 0xf9, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0xcf, 0xf9, 0x07, 0x46, - 0x2f, 0x60, 0xf1, 0xf7, 0xc5, 0xfb, 0x80, 0x46, 0xa4, 0xf8, 0x00, 0x80, - 0x4f, 0xf0, 0x76, 0x50, 0x39, 0x46, 0xf1, 0xf7, 0x51, 0xfb, 0x28, 0x60, - 0x5f, 0xfa, 0x88, 0xf1, 0x40, 0xf2, 0xd3, 0x50, 0xed, 0xf7, 0x8c, 0xfc, - 0x20, 0x88, 0x01, 0x0a, 0x40, 0xf2, 0xd4, 0x50, 0xed, 0xf7, 0x86, 0xfc, - 0x70, 0x7a, 0xb1, 0x7a, 0xf7, 0x78, 0x36, 0x79, 0x40, 0xea, 0x01, 0x20, - 0x00, 0x03, 0xf1, 0xf7, 0x93, 0xf9, 0x80, 0x46, 0x47, 0xea, 0x06, 0x20, - 0xf1, 0xf7, 0x98, 0xf9, 0x01, 0x46, 0x40, 0x46, 0xf1, 0xf7, 0xa4, 0xf9, - 0x06, 0x46, 0x6e, 0x60, 0xf1, 0xf7, 0x9a, 0xfb, 0x60, 0x80, 0x31, 0x46, - 0x4f, 0xf0, 0x66, 0x50, 0xf1, 0xf7, 0x28, 0xfb, 0x68, 0x60, 0x00, 0x20, - 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x02, 0x00, 0x20, 0xdb, 0x05, 0x00, 0x46, - 0x20, 0x02, 0x00, 0x46, 0x78, 0x29, 0x00, 0x20, 0xd2, 0x05, 0x00, 0x46, - 0x02, 0x01, 0x00, 0x46, 0x00, 0xf2, 0x00, 0x20, 0x40, 0x4b, 0x4c, 0x00, - 0x00, 0x09, 0x3d, 0x00, 0x01, 0x22, 0x40, 0x1c, 0x02, 0xfa, 0x00, 0xf0, - 0x40, 0x1e, 0x80, 0xb2, 0x88, 0x42, 0x88, 0xbf, 0x08, 0x46, 0x70, 0x47, - 0x2d, 0xe9, 0xf0, 0x4f, 0x91, 0x46, 0x0f, 0xf2, 0xe0, 0x02, 0x83, 0xb0, - 0x04, 0x46, 0xb2, 0xe8, 0x08, 0x04, 0x68, 0x46, 0x00, 0x25, 0xa0, 0xe8, - 0x08, 0x04, 0x01, 0xf0, 0x07, 0x00, 0x40, 0xf0, 0x20, 0x01, 0x40, 0xf2, - 0xdd, 0x50, 0xed, 0xf7, 0x35, 0xfc, 0x00, 0x21, 0x40, 0xf2, 0xe2, 0x50, - 0xed, 0xf7, 0x30, 0xfc, 0x00, 0x27, 0x40, 0xf2, 0xe4, 0x5a, 0x40, 0xf2, - 0xe3, 0x5b, 0x0f, 0xf2, 0xc8, 0x08, 0x20, 0x88, 0x39, 0xf8, 0x17, 0x10, - 0x48, 0x43, 0x3d, 0xf8, 0x17, 0x10, 0xc1, 0xeb, 0x10, 0x11, 0x15, 0xf8, - 0x08, 0x00, 0x89, 0xb2, 0xff, 0xf7, 0xc8, 0xff, 0x00, 0xf0, 0x3e, 0xf8, - 0x00, 0xf0, 0x38, 0xf8, 0x6d, 0x1c, 0x7f, 0x1c, 0x04, 0x2f, 0xea, 0xdb, - 0x00, 0x27, 0x09, 0xeb, 0x47, 0x01, 0x60, 0x88, 0x09, 0x89, 0x48, 0x43, - 0x01, 0x01, 0x15, 0xf8, 0x08, 0x00, 0x09, 0x0c, 0xff, 0xf7, 0xb4, 0xff, - 0x00, 0xf0, 0x2a, 0xf8, 0x00, 0xf0, 0x24, 0xf8, 0x6d, 0x1c, 0x7f, 0x1c, - 0x07, 0x2f, 0xec, 0xdb, 0x00, 0x24, 0x09, 0xeb, 0x44, 0x00, 0x64, 0x1c, - 0xc1, 0x8a, 0x15, 0xf8, 0x08, 0x00, 0xff, 0xf7, 0xa3, 0xff, 0x00, 0xf0, - 0x19, 0xf8, 0x00, 0xf0, 0x13, 0xf8, 0x6d, 0x1c, 0x05, 0x2c, 0xf0, 0xdb, - 0x0f, 0xf2, 0x38, 0x05, 0x00, 0x24, 0x00, 0x21, 0x58, 0x46, 0xed, 0xf7, - 0xe9, 0xfb, 0x61, 0x5d, 0x50, 0x46, 0xed, 0xf7, 0xe5, 0xfb, 0x64, 0x1c, - 0x15, 0x2c, 0xf4, 0xdb, 0xbd, 0xe8, 0xf7, 0x8f, 0xf1, 0xb2, 0x50, 0x46, - 0xed, 0xf7, 0xdc, 0xbb, 0x06, 0x46, 0x30, 0x04, 0x01, 0x0e, 0x58, 0x46, - 0xed, 0xf7, 0xd6, 0xbb, 0x30, 0x01, 0xa0, 0x00, 0x70, 0x00, 0x40, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x33, 0x00, 0x00, 0x00, 0x2c, 0x00, 0x00, 0x00, - 0x2a, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, - 0x0a, 0x08, 0x06, 0x05, 0x0a, 0x0a, 0x0b, 0x09, 0x0a, 0x09, 0x0a, 0x05, - 0x05, 0x05, 0x05, 0x07, 0xb3, 0x49, 0x4f, 0xf4, 0x82, 0x72, 0x02, 0xfb, - 0x00, 0x11, 0x01, 0xf5, 0x21, 0x71, 0xff, 0xf7, 0x74, 0xb9, 0x38, 0xb5, - 0xae, 0x4c, 0x00, 0x20, 0x20, 0x70, 0x00, 0x21, 0x01, 0x20, 0xed, 0xf7, - 0xec, 0xfc, 0x00, 0x20, 0xf0, 0xf7, 0x9c, 0xf8, 0x00, 0x20, 0x01, 0x25, - 0x60, 0x70, 0x01, 0x21, 0x04, 0xe0, 0x00, 0x20, 0x28, 0x55, 0x29, 0x00, - 0x18, 0xbf, 0x01, 0x21, 0xc9, 0xb2, 0x01, 0x20, 0xed, 0xf7, 0xdb, 0xfc, - 0x28, 0x46, 0xf0, 0xf7, 0x8b, 0xf8, 0x6d, 0x1c, 0x02, 0x2d, 0xf0, 0xd3, - 0x31, 0xbd, 0x2d, 0xe9, 0xf0, 0x47, 0x9f, 0x4e, 0xdf, 0xf8, 0x7c, 0x82, - 0x70, 0x69, 0xdf, 0xf8, 0x70, 0x92, 0x0c, 0x46, 0xb1, 0x69, 0x00, 0x25, - 0x81, 0x42, 0x38, 0xbf, 0x08, 0x46, 0xf1, 0xf7, 0xa5, 0xf8, 0x4f, 0xf0, - 0x7c, 0x51, 0xf1, 0xf7, 0x3f, 0xfa, 0x98, 0x49, 0xf1, 0xf7, 0xae, 0xf8, - 0xf1, 0xf7, 0xa6, 0xfa, 0x96, 0x49, 0xb1, 0xf9, 0x0e, 0x20, 0x00, 0xb2, - 0x90, 0x42, 0xc8, 0xbf, 0x10, 0x46, 0xc8, 0x81, 0x00, 0x27, 0xb0, 0x7a, - 0x21, 0x61, 0x00, 0xf0, 0x03, 0x06, 0x08, 0x8a, 0x00, 0xf0, 0x03, 0xf9, - 0x60, 0x60, 0x26, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x3e, 0xd5, 0x01, 0x20, - 0xb8, 0x40, 0xed, 0xf7, 0xcd, 0xfb, 0x08, 0xb9, 0x02, 0x25, 0x3a, 0xe0, - 0x39, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0x73, 0xfe, 0x08, 0xb9, 0x03, 0x25, - 0x33, 0xe0, 0x27, 0x60, 0x39, 0x46, 0x00, 0xf0, 0xe7, 0xf8, 0xe0, 0x60, - 0x4f, 0xf4, 0xa0, 0x70, 0x00, 0xfb, 0x07, 0x9a, 0x0a, 0xf1, 0x04, 0x00, - 0xa0, 0x60, 0xed, 0xf7, 0x8d, 0xfc, 0x4f, 0xf0, 0x7e, 0x51, 0x38, 0x46, - 0xfe, 0xf7, 0xf7, 0xff, 0x4f, 0xf4, 0x82, 0x70, 0x00, 0xfb, 0x07, 0x90, - 0x00, 0xf5, 0x21, 0x71, 0x20, 0x46, 0xfe, 0xf7, 0x73, 0xfd, 0x05, 0x46, - 0x0a, 0xf1, 0x04, 0x00, 0xfe, 0xf7, 0x4e, 0xff, 0x0a, 0xf1, 0x54, 0x00, - 0xfe, 0xf7, 0x4a, 0xff, 0x43, 0x46, 0x01, 0x22, 0xf9, 0xb2, 0x01, 0x20, - 0xed, 0xf7, 0x5a, 0xfc, 0xed, 0xf7, 0x71, 0xfc, 0x15, 0xb9, 0x01, 0x20, - 0x07, 0xf8, 0x09, 0x00, 0x7f, 0x1c, 0x02, 0x2f, 0xb9, 0xd3, 0x28, 0x46, - 0xbd, 0xe8, 0xf0, 0x87, 0x38, 0x21, 0x6a, 0x48, 0xf2, 0xf7, 0x8c, 0xb8, - 0x2d, 0xe9, 0xfc, 0x4e, 0x81, 0x46, 0x68, 0x4e, 0x1c, 0x20, 0x00, 0xfb, - 0x09, 0x60, 0x0d, 0x46, 0x00, 0xf1, 0x28, 0x07, 0xef, 0xf3, 0x11, 0x80, - 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x00, 0x21, 0xb9, 0x82, 0x39, 0x60, - 0x64, 0x21, 0x79, 0x60, 0x00, 0x21, 0xf9, 0x82, 0x80, 0xf3, 0x11, 0x88, - 0x06, 0xeb, 0xc9, 0x00, 0x01, 0x90, 0x34, 0x78, 0xdf, 0xf8, 0x54, 0xb1, - 0x20, 0x07, 0x44, 0xbf, 0x01, 0x98, 0x84, 0x69, 0x4f, 0xf4, 0x82, 0x70, - 0x00, 0xfb, 0x09, 0xb0, 0x00, 0xf5, 0x21, 0x7a, 0xe0, 0x07, 0x0a, 0xd5, - 0x01, 0x20, 0xb8, 0x82, 0x29, 0x46, 0x48, 0x46, 0x00, 0xf0, 0x3a, 0xf9, - 0x30, 0xb3, 0xb9, 0x8a, 0x40, 0xea, 0x01, 0x40, 0x38, 0x60, 0x38, 0x68, - 0x60, 0xb9, 0xa0, 0x07, 0x0d, 0xd5, 0x02, 0x20, 0xb8, 0x82, 0x29, 0x46, - 0x48, 0x46, 0x00, 0xf0, 0xd1, 0xf9, 0xc8, 0xb1, 0xb9, 0x8a, 0x40, 0xea, - 0x01, 0x40, 0x38, 0x60, 0x38, 0x68, 0x00, 0x28, 0x4d, 0xd1, 0x60, 0x07, - 0x4d, 0xd5, 0x03, 0x20, 0xb8, 0x82, 0x19, 0xf8, 0x0b, 0x00, 0x20, 0xb1, - 0x49, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0xe3, 0xfd, 0x40, 0xb9, 0xb8, 0x8a, - 0x00, 0x04, 0x40, 0xf0, 0x03, 0x00, 0x3b, 0xe0, 0x38, 0x60, 0xdc, 0xe7, - 0x38, 0x60, 0xea, 0xe7, 0xa5, 0xf8, 0x00, 0x90, 0x30, 0x1d, 0xa8, 0x60, - 0xf0, 0x88, 0x00, 0xf0, 0x52, 0xf8, 0x68, 0x60, 0xc5, 0xf8, 0x0c, 0xa0, - 0x4f, 0xf4, 0xa0, 0x70, 0x00, 0xfb, 0x09, 0xb0, 0x01, 0x1d, 0xa4, 0x30, - 0x29, 0x61, 0x68, 0x61, 0x00, 0xf0, 0x3e, 0xf8, 0xa8, 0x61, 0x00, 0x20, - 0x28, 0x62, 0xee, 0xf7, 0x99, 0xfb, 0x83, 0x46, 0xbb, 0xf1, 0x2e, 0x0f, - 0x16, 0xd3, 0x00, 0xf0, 0x48, 0xf8, 0x29, 0x49, 0xf0, 0xf7, 0xd0, 0xff, - 0x00, 0x90, 0xab, 0xf1, 0x2d, 0x00, 0xf0, 0xf7, 0xbb, 0xff, 0x00, 0x99, - 0xf1, 0xf7, 0x56, 0xf9, 0xf8, 0xf7, 0x54, 0xf8, 0x40, 0x08, 0xf0, 0xf7, - 0x75, 0xf8, 0xa8, 0x70, 0x28, 0x46, 0xff, 0xf7, 0xa1, 0xf9, 0x04, 0xe0, - 0xb8, 0x8a, 0x00, 0x04, 0x40, 0xf0, 0x04, 0x00, 0x38, 0x60, 0x38, 0x68, - 0x98, 0xb9, 0x20, 0x07, 0x11, 0xd5, 0xa5, 0xf8, 0x00, 0x90, 0x30, 0x1d, - 0xa8, 0x60, 0xc5, 0xf8, 0x0c, 0xa0, 0x00, 0xf0, 0x0d, 0xf8, 0xa8, 0x61, - 0x00, 0x20, 0x28, 0x62, 0x01, 0x98, 0x00, 0xf1, 0x18, 0x01, 0x28, 0x46, - 0xff, 0xf7, 0x21, 0xfb, 0x38, 0x60, 0x38, 0x68, 0xbd, 0xe8, 0xf6, 0x8e, - 0xef, 0x61, 0x49, 0x46, 0x01, 0x20, 0xf1, 0xf7, 0x87, 0xbd, 0x00, 0xf0, - 0xc0, 0xb8, 0x10, 0xb5, 0xf0, 0xf7, 0x86, 0xff, 0x04, 0x46, 0x00, 0xf0, - 0x08, 0xf8, 0x21, 0x46, 0xf1, 0xf7, 0x1e, 0xf9, 0xbd, 0xe8, 0x10, 0x40, - 0x0a, 0x49, 0xf0, 0xf7, 0x8b, 0xbf, 0x03, 0x48, 0x00, 0x6c, 0xf0, 0xf7, - 0x77, 0xbf, 0x00, 0x00, 0x48, 0xa8, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, - 0xa5, 0x58, 0x01, 0x01, 0x00, 0x24, 0x74, 0x49, 0x68, 0x2b, 0x00, 0x20, - 0xb4, 0x2b, 0x00, 0x20, 0x8c, 0x2b, 0x00, 0x20, 0x00, 0x7c, 0x92, 0x4d, - 0x53, 0x48, 0x41, 0x89, 0x03, 0x22, 0x11, 0x42, 0x00, 0xd1, 0x70, 0x47, - 0x80, 0xb5, 0xc1, 0xf3, 0x01, 0x11, 0x61, 0xb1, 0x01, 0x6c, 0x80, 0x69, - 0xfc, 0xf7, 0x82, 0xfb, 0x05, 0x28, 0x28, 0xbf, 0x05, 0x20, 0x01, 0x21, - 0x01, 0xfa, 0x00, 0xf0, 0x4a, 0x49, 0x88, 0x60, 0xc8, 0x60, 0x01, 0xbd, - 0xc1, 0x68, 0xca, 0x07, 0x01, 0xd5, 0x04, 0x20, 0x70, 0x47, 0x8a, 0x07, - 0x01, 0xd5, 0x03, 0x20, 0x70, 0x47, 0x49, 0x07, 0x01, 0xd5, 0x05, 0x20, - 0x70, 0x47, 0x00, 0x69, 0x00, 0xb1, 0x06, 0x20, 0x70, 0x47, 0x2d, 0xe9, - 0xf0, 0x41, 0x04, 0x46, 0x0d, 0x46, 0xdf, 0xf8, 0xf8, 0x80, 0x08, 0xf1, - 0x08, 0x00, 0x68, 0x60, 0x00, 0x26, 0x00, 0x20, 0xee, 0xf7, 0x00, 0xfb, - 0x32, 0x28, 0x28, 0xd3, 0x6b, 0x68, 0x37, 0x49, 0x9f, 0x89, 0x93, 0xf8, - 0x0e, 0xc0, 0x5b, 0x8a, 0x09, 0x6c, 0x1b, 0x0a, 0x0c, 0xf0, 0x07, 0x0c, - 0x03, 0xf0, 0x07, 0x03, 0x01, 0x22, 0x63, 0x44, 0x9a, 0x40, 0x32, 0x38, - 0x92, 0xb2, 0xb0, 0xfb, 0xf2, 0xf0, 0xef, 0xf7, 0x8b, 0xf8, 0x4f, 0xf6, - 0xc0, 0x71, 0x39, 0x40, 0x01, 0x43, 0x29, 0x81, 0xef, 0xf7, 0xab, 0xf8, - 0xf0, 0xf7, 0x10, 0xff, 0x01, 0x46, 0x4f, 0xf0, 0x8f, 0x40, 0xf0, 0xf7, - 0x1b, 0xff, 0x00, 0xf0, 0xb5, 0xf9, 0xf7, 0xf7, 0xa5, 0xff, 0x68, 0x81, - 0x00, 0xe0, 0x07, 0x26, 0x00, 0x27, 0x86, 0xb9, 0x24, 0xfa, 0x07, 0xf0, - 0xc0, 0x07, 0x0c, 0xd5, 0x2f, 0x60, 0x28, 0x46, 0x00, 0xf0, 0xc7, 0xf9, - 0x28, 0x46, 0xff, 0xf7, 0xa9, 0xff, 0x06, 0x00, 0x03, 0xd1, 0x68, 0x69, - 0x08, 0xeb, 0x87, 0x01, 0x08, 0x62, 0x7f, 0x1c, 0x02, 0x2f, 0xea, 0xd3, - 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x38, 0xb5, 0x0c, 0x46, 0x16, 0x48, - 0x14, 0x49, 0x00, 0x68, 0x89, 0x7a, 0x80, 0x08, 0x01, 0xf0, 0x03, 0x01, - 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, 0x03, 0x00, 0xed, 0xf7, 0x26, 0xfa, - 0x08, 0xb9, 0x02, 0x20, 0x32, 0xbd, 0x21, 0x46, 0x28, 0x46, 0xbd, 0xe8, - 0x34, 0x40, 0x96, 0xe7, 0x0b, 0x4a, 0x52, 0x68, 0x01, 0x23, 0x00, 0xf0, - 0x01, 0x00, 0x92, 0x08, 0x03, 0xfa, 0x00, 0xf0, 0x40, 0xea, 0x82, 0x00, - 0x8b, 0xe7, 0x02, 0x28, 0x06, 0xd2, 0x01, 0x46, 0x04, 0x4a, 0x02, 0xeb, - 0x80, 0x00, 0x00, 0x6a, 0x00, 0xf0, 0x2b, 0xba, 0x70, 0x47, 0x00, 0x00, - 0x78, 0x29, 0x00, 0x20, 0xf8, 0x28, 0x00, 0x20, 0xef, 0xf3, 0x11, 0x80, - 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, 0x70, 0x47, 0x80, 0xb5, 0x8a, 0x48, - 0xc1, 0x6a, 0x40, 0x6b, 0xfc, 0xf7, 0xd8, 0xfa, 0x88, 0x49, 0x4a, 0xe0, - 0x2d, 0xe9, 0xf8, 0x43, 0x0c, 0x46, 0x00, 0x27, 0x61, 0x68, 0x8d, 0x89, - 0x8e, 0x7d, 0x61, 0x78, 0x01, 0x29, 0x08, 0xbf, 0x01, 0x28, 0x32, 0xd1, - 0x00, 0x20, 0xee, 0xf7, 0x6d, 0xfa, 0x0f, 0x28, 0x38, 0xbf, 0x01, 0x27, - 0x2b, 0xd3, 0x62, 0x68, 0x7c, 0x49, 0x92, 0xf8, 0x0e, 0xc0, 0x52, 0x8a, - 0x09, 0x6c, 0x12, 0x0a, 0x0c, 0xf0, 0x07, 0x0c, 0x02, 0xf0, 0x07, 0x02, - 0x01, 0x23, 0x62, 0x44, 0x03, 0xfa, 0x02, 0xf2, 0x0f, 0x38, 0x92, 0xb2, - 0xb0, 0xfb, 0xf2, 0xf0, 0xee, 0xf7, 0xf6, 0xff, 0x80, 0x46, 0x05, 0xf0, - 0x3f, 0x00, 0xef, 0xf7, 0x18, 0xf8, 0x81, 0x46, 0x40, 0x46, 0xef, 0xf7, - 0x14, 0xf8, 0x48, 0x45, 0x0b, 0xd2, 0xb9, 0xfb, 0xf0, 0xf6, 0xb6, 0xb2, - 0x4f, 0xf6, 0xc0, 0x71, 0x70, 0x43, 0x29, 0x40, 0x48, 0x45, 0x48, 0xea, - 0x01, 0x05, 0x38, 0xbf, 0x76, 0x1c, 0x25, 0x81, 0x66, 0x81, 0x38, 0x46, - 0xbd, 0xe8, 0xf2, 0x83, 0x80, 0xb5, 0x64, 0x48, 0x01, 0x6c, 0x80, 0x69, - 0xfc, 0xf7, 0x8c, 0xfa, 0x63, 0x49, 0x81, 0xf8, 0x21, 0x00, 0x01, 0xbd, - 0x38, 0xb5, 0x0c, 0x46, 0x5f, 0x48, 0x5e, 0x49, 0x00, 0x68, 0x49, 0x89, - 0x80, 0x08, 0xc1, 0xf3, 0x81, 0x01, 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, - 0x03, 0x00, 0xed, 0xf7, 0x8b, 0xf9, 0x08, 0xb9, 0x01, 0x20, 0x32, 0xbd, - 0x22, 0x46, 0x29, 0x46, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x20, 0x22, 0xe0, - 0x38, 0xb5, 0x0c, 0x46, 0x54, 0x48, 0x52, 0x49, 0x00, 0x68, 0x89, 0x7a, - 0x80, 0x08, 0x01, 0xf0, 0x03, 0x01, 0x41, 0xea, 0x80, 0x05, 0x05, 0xf0, - 0x03, 0x00, 0xed, 0xf7, 0x81, 0xf9, 0x08, 0xb9, 0x02, 0x20, 0x32, 0xbd, - 0x22, 0x46, 0x29, 0x46, 0xbd, 0xe8, 0x38, 0x40, 0x00, 0x20, 0x54, 0xe0, - 0x0a, 0x46, 0x49, 0x49, 0x01, 0x23, 0x49, 0x68, 0x00, 0xf0, 0x01, 0x00, - 0x03, 0xfa, 0x00, 0xf0, 0x01, 0x43, 0x01, 0x20, 0x49, 0xe0, 0x2d, 0xe9, - 0xf8, 0x43, 0x0c, 0x46, 0x04, 0xf0, 0x04, 0x01, 0xdf, 0xf8, 0x00, 0x81, - 0x15, 0x46, 0x00, 0x26, 0xa9, 0x70, 0x6e, 0x70, 0x04, 0xf0, 0x08, 0x01, - 0xe9, 0x70, 0x2e, 0x61, 0x08, 0xf1, 0x08, 0x01, 0x69, 0x60, 0x29, 0x46, - 0xff, 0xf7, 0x62, 0xff, 0x00, 0xb1, 0x08, 0x26, 0x00, 0x27, 0x00, 0x20, - 0x02, 0xe0, 0x38, 0x00, 0x18, 0xbf, 0x01, 0x20, 0x2e, 0xbb, 0x24, 0xfa, - 0x07, 0xf1, 0xc9, 0x07, 0x21, 0xd5, 0x34, 0x49, 0x2f, 0x70, 0x4f, 0xf4, - 0x7c, 0x72, 0x02, 0xfb, 0x00, 0x16, 0x06, 0xf1, 0xe0, 0x00, 0xe8, 0x60, - 0x30, 0x1d, 0x68, 0x61, 0x14, 0x20, 0x00, 0xfb, 0x07, 0x89, 0x09, 0xf1, - 0x28, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x58, 0xf8, 0x28, 0x46, 0x00, 0xf0, - 0x09, 0xfa, 0x6b, 0x6a, 0xaa, 0x6a, 0x29, 0x7e, 0x30, 0x46, 0xfa, 0xf7, - 0x37, 0xf9, 0x09, 0xf1, 0x28, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x58, 0xf8, - 0x06, 0x46, 0x7f, 0x1c, 0x02, 0x2f, 0xd2, 0xd3, 0x30, 0x46, 0xbd, 0xe8, - 0xf2, 0x83, 0x2d, 0xe9, 0xf0, 0x41, 0x0c, 0x46, 0x15, 0x46, 0x01, 0x21, - 0x69, 0x70, 0x04, 0xf0, 0x04, 0x01, 0xa9, 0x70, 0x04, 0xf0, 0x08, 0x01, - 0xe9, 0x70, 0x00, 0x26, 0xdf, 0xf8, 0x60, 0x80, 0x6e, 0x61, 0x08, 0xf1, - 0x08, 0x01, 0x69, 0x60, 0x2e, 0x61, 0x05, 0xf5, 0xde, 0x71, 0xe9, 0x60, - 0x29, 0x46, 0xff, 0xf7, 0x13, 0xff, 0x00, 0xb1, 0x08, 0x26, 0x00, 0x27, - 0xae, 0xb9, 0x24, 0xfa, 0x07, 0xf0, 0xc0, 0x07, 0x11, 0xd5, 0x14, 0x20, - 0x00, 0xfb, 0x07, 0x86, 0x2f, 0x70, 0x06, 0xf1, 0x24, 0x01, 0x28, 0x46, - 0x00, 0xf0, 0x18, 0xf8, 0x28, 0x46, 0x00, 0xf0, 0xc9, 0xf9, 0x06, 0xf1, - 0x24, 0x01, 0x28, 0x46, 0x00, 0xf0, 0x1e, 0xf8, 0x06, 0x46, 0x7f, 0x1c, - 0x02, 0x2f, 0xe5, 0xd3, 0x30, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, - 0x78, 0x29, 0x00, 0x20, 0xdc, 0x29, 0x00, 0x20, 0x2c, 0x2a, 0x00, 0x20, - 0xc0, 0x92, 0x00, 0x20, 0x10, 0xb5, 0x0c, 0x46, 0xff, 0xf7, 0xd8, 0xfe, - 0x01, 0x21, 0x61, 0x60, 0x00, 0x21, 0x21, 0x60, 0xa1, 0x60, 0xe1, 0x60, - 0x21, 0x61, 0x80, 0xf3, 0x11, 0x88, 0x10, 0xbd, 0x70, 0xb5, 0x04, 0x46, - 0x0d, 0x46, 0x20, 0x6a, 0xc1, 0x07, 0x48, 0xbf, 0x04, 0x26, 0x1b, 0xd4, - 0x81, 0x07, 0x48, 0xbf, 0x03, 0x26, 0x17, 0xd4, 0x40, 0x07, 0x48, 0xbf, - 0x07, 0x26, 0x13, 0xd4, 0x60, 0x7e, 0x08, 0xb1, 0x0a, 0x26, 0x0f, 0xe0, - 0xa0, 0x7e, 0x81, 0x07, 0x48, 0xbf, 0x09, 0x26, 0x0a, 0xd4, 0xc0, 0x07, - 0x05, 0xd4, 0xe0, 0x7e, 0x08, 0xb1, 0x05, 0x26, 0x04, 0xe0, 0x20, 0x7f, - 0x08, 0xb1, 0x06, 0x26, 0x00, 0xe0, 0x00, 0x26, 0xff, 0xf7, 0xa8, 0xfe, - 0x2e, 0x60, 0xa1, 0x6a, 0xa9, 0x60, 0x61, 0x6a, 0xe9, 0x60, 0x21, 0x7e, - 0x29, 0x61, 0x00, 0x21, 0x69, 0x60, 0x80, 0xf3, 0x11, 0x88, 0x30, 0x46, - 0x70, 0xbd, 0x00, 0x00, 0xc0, 0xf3, 0xc7, 0x52, 0x7e, 0x3a, 0xcc, 0xbf, - 0xd2, 0xf1, 0x18, 0x0c, 0x07, 0xe0, 0x6f, 0xf0, 0x7f, 0x41, 0xd1, 0x40, - 0x00, 0x42, 0x58, 0xbf, 0x40, 0x18, 0x88, 0x43, 0x70, 0x47, 0x18, 0x2a, - 0x06, 0xda, 0x41, 0x00, 0x18, 0xbf, 0x4f, 0xf0, 0x7e, 0x50, 0x28, 0xbf, - 0x4f, 0xf0, 0x00, 0x40, 0x70, 0x47, 0x00, 0x00, 0x00, 0x21, 0xc0, 0xf8, - 0x98, 0x10, 0x40, 0xf8, 0x0c, 0x1f, 0x41, 0x60, 0x70, 0x47, 0x10, 0xb5, - 0x04, 0x46, 0xff, 0xf7, 0xf5, 0xff, 0x00, 0x21, 0x01, 0x20, 0xfe, 0xf7, - 0x4b, 0xf9, 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x2d, 0xe9, 0xf0, 0x41, - 0x05, 0x46, 0x4f, 0xf4, 0x80, 0x70, 0x29, 0x68, 0x00, 0xf0, 0x8b, 0xf8, - 0x00, 0xf0, 0x87, 0xf8, 0x04, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, - 0x7a, 0xd1, 0x29, 0x68, 0x4f, 0xf4, 0x40, 0x70, 0x00, 0xf0, 0x7f, 0xf8, - 0x00, 0xf0, 0x7b, 0xf8, 0x01, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, - 0x6e, 0xd1, 0x20, 0x46, 0xf0, 0xf7, 0x98, 0xfd, 0x01, 0x46, 0x4f, 0xf0, - 0x44, 0x40, 0xf0, 0xf7, 0x15, 0xfd, 0x80, 0x46, 0x20, 0x46, 0x41, 0x46, - 0xf0, 0xf7, 0x9e, 0xfe, 0x00, 0x21, 0xf0, 0xf7, 0xa3, 0xff, 0x94, 0xbf, - 0x4f, 0xf0, 0x7c, 0x51, 0x4f, 0xf0, 0x3f, 0x41, 0xf0, 0xf7, 0xf8, 0xfd, - 0xf0, 0xf7, 0xfe, 0xfe, 0xc0, 0xf5, 0x80, 0x70, 0x00, 0xf0, 0x54, 0xf8, - 0x00, 0xf0, 0x57, 0xf8, 0x07, 0x46, 0xd5, 0xf8, 0x98, 0x00, 0x00, 0x28, - 0x4a, 0xd1, 0x4f, 0xf0, 0x40, 0x40, 0x39, 0x46, 0xf0, 0xf7, 0x82, 0xfe, - 0x41, 0x46, 0xf0, 0xf7, 0x7f, 0xfe, 0x00, 0x21, 0xf0, 0xf7, 0x84, 0xff, - 0x04, 0x46, 0x94, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, 0x4f, 0xf0, 0x3f, 0x40, - 0x21, 0x46, 0xf0, 0xf7, 0xd7, 0xfd, 0xf0, 0xf7, 0xdd, 0xfe, 0x00, 0x28, - 0x54, 0xbf, 0x08, 0x20, 0x6f, 0xf0, 0x07, 0x00, 0x84, 0x19, 0xb4, 0xf5, - 0x80, 0x6f, 0x28, 0xbf, 0x34, 0x1a, 0x29, 0x68, 0x20, 0x46, 0x00, 0xf0, - 0x30, 0xf8, 0x00, 0xf0, 0x2c, 0xf8, 0x80, 0x46, 0xd5, 0xf8, 0x98, 0x00, - 0x00, 0xbb, 0xa0, 0x1b, 0xf0, 0xf7, 0xb2, 0xfc, 0x39, 0x46, 0xf0, 0xf7, - 0x57, 0xfe, 0x04, 0x46, 0x40, 0x46, 0x39, 0x46, 0xf0, 0xf7, 0x42, 0xfd, - 0x01, 0x46, 0x20, 0x46, 0xf0, 0xf7, 0xc0, 0xfc, 0x00, 0x21, 0xf0, 0xf7, - 0x53, 0xff, 0x04, 0x46, 0x94, 0xbf, 0x4f, 0xf0, 0x7c, 0x50, 0x4f, 0xf0, - 0x3f, 0x40, 0x21, 0x46, 0xf0, 0xf7, 0xa6, 0xfd, 0xf0, 0xf7, 0xac, 0xfe, - 0x30, 0x1a, 0x00, 0xf0, 0x03, 0xf8, 0x6e, 0x61, 0xbd, 0xe8, 0xf0, 0x81, - 0x80, 0xf3, 0x0a, 0x06, 0x29, 0x68, 0x30, 0x46, 0x01, 0xe0, 0x28, 0x46, - 0x38, 0xe0, 0x70, 0xb5, 0x04, 0x46, 0x00, 0x29, 0x07, 0xbf, 0x40, 0xf2, - 0xe1, 0x65, 0x4f, 0xf4, 0xdc, 0x60, 0x40, 0xf2, 0xe3, 0x65, 0x40, 0xf2, - 0xe2, 0x60, 0xef, 0xf3, 0x11, 0x86, 0x60, 0x21, 0x81, 0xf3, 0x11, 0x88, - 0xa1, 0x05, 0x09, 0x0e, 0xec, 0xf7, 0x60, 0xff, 0x04, 0xf0, 0x03, 0x04, - 0x00, 0xf0, 0x0f, 0xf8, 0x44, 0xf0, 0x80, 0x01, 0x00, 0xf0, 0x0c, 0xf8, - 0x00, 0xf0, 0x09, 0xf8, 0x00, 0xf0, 0x07, 0xf8, 0x05, 0xf1, 0x8c, 0x40, - 0x01, 0x78, 0x00, 0x78, 0x86, 0xf3, 0x11, 0x88, 0x70, 0xbd, 0x21, 0x46, - 0x28, 0x46, 0xec, 0xf7, 0x49, 0xbf, 0x00, 0x21, 0x01, 0x22, 0x20, 0xfa, - 0x02, 0xf3, 0xdb, 0x07, 0x01, 0xd5, 0x11, 0x46, 0x02, 0xe0, 0x52, 0x1c, - 0x18, 0x2a, 0xf6, 0xd3, 0x08, 0x46, 0x70, 0x47, 0x70, 0xb5, 0x04, 0x46, - 0x60, 0x68, 0x40, 0x68, 0xff, 0xf7, 0xed, 0xff, 0x05, 0xb2, 0x20, 0x68, - 0x20, 0x76, 0x01, 0x20, 0x60, 0x76, 0x00, 0x20, 0xa0, 0x76, 0x60, 0x68, - 0xe0, 0x61, 0x04, 0xf1, 0x08, 0x00, 0x20, 0x62, 0x00, 0x20, 0x60, 0x62, - 0x04, 0xf1, 0x18, 0x00, 0xfd, 0xf7, 0x80, 0xfe, 0xe0, 0x6a, 0xe0, 0x60, - 0x08, 0xb1, 0x01, 0x20, 0x07, 0xe0, 0xa0, 0x6b, 0xa8, 0x42, 0x04, 0xbf, - 0xe0, 0x6b, 0xe8, 0x42, 0x03, 0xd0, 0x01, 0x20, 0x20, 0x61, 0xc4, 0xf8, - 0x98, 0x00, 0x00, 0x20, 0xd4, 0xf8, 0x98, 0x10, 0x00, 0x29, 0x41, 0xd1, - 0xd4, 0xe9, 0x12, 0x01, 0xf0, 0xf7, 0xf0, 0xfb, 0x05, 0x46, 0xd4, 0xe9, - 0x10, 0x01, 0xf0, 0xf7, 0xeb, 0xfb, 0x01, 0x46, 0x28, 0x46, 0xf0, 0xf7, - 0x33, 0xfc, 0x05, 0x46, 0xd4, 0xe9, 0x16, 0x01, 0xf0, 0xf7, 0xe2, 0xfb, - 0x06, 0x46, 0xd4, 0xe9, 0x14, 0x01, 0xf0, 0xf7, 0xdd, 0xfb, 0x01, 0x46, - 0x30, 0x46, 0xf0, 0xf7, 0x25, 0xfc, 0x04, 0x46, 0x28, 0x46, 0x29, 0x46, - 0xf0, 0xf7, 0xae, 0xfd, 0x29, 0x46, 0xf0, 0xf7, 0xab, 0xfd, 0x10, 0x49, - 0xf0, 0xf7, 0x1a, 0xfc, 0x01, 0x46, 0x28, 0x46, 0xf0, 0xf7, 0x94, 0xfc, - 0x05, 0x46, 0x20, 0x46, 0x21, 0x46, 0xf0, 0xf7, 0x9f, 0xfd, 0x21, 0x46, - 0xf0, 0xf7, 0x9c, 0xfd, 0x08, 0x49, 0xf0, 0xf7, 0x0b, 0xfc, 0x01, 0x46, - 0x20, 0x46, 0xf0, 0xf7, 0x85, 0xfc, 0x29, 0x46, 0xf0, 0xf7, 0xf6, 0xfc, - 0xbd, 0xe8, 0x70, 0x40, 0x4f, 0xf0, 0x7c, 0x51, 0xf0, 0xf7, 0x8c, 0xbd, - 0x70, 0xbd, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x00, 0x21, 0x41, 0x63, - 0x01, 0x62, 0x41, 0x76, 0x81, 0x76, 0xc1, 0x76, 0x01, 0x77, 0x70, 0x47, - 0x10, 0xb5, 0x04, 0x46, 0xff, 0xf7, 0xf4, 0xff, 0x20, 0x46, 0x00, 0xf0, - 0x8f, 0xf8, 0x20, 0x6a, 0x60, 0xb9, 0xa0, 0x78, 0x02, 0x28, 0x09, 0xd0, - 0xe0, 0x78, 0x00, 0x28, 0x04, 0xbf, 0x60, 0x6b, 0x00, 0x28, 0x03, 0xd1, - 0x20, 0x46, 0xbd, 0xe8, 0x10, 0x40, 0x13, 0xe0, 0x10, 0xbd, 0x10, 0xb5, - 0xb4, 0xb0, 0x04, 0x46, 0x00, 0x20, 0x00, 0x90, 0x69, 0x46, 0x20, 0x46, - 0xfc, 0xf7, 0x74, 0xfa, 0x6b, 0x46, 0x01, 0xaa, 0x04, 0xf5, 0x79, 0x71, - 0x04, 0xf5, 0x96, 0x60, 0xfb, 0xf7, 0xfb, 0xff, 0x34, 0xb0, 0x10, 0xbd, - 0xf8, 0xb5, 0x04, 0x46, 0x6a, 0x46, 0x60, 0x78, 0x25, 0x78, 0x00, 0x28, - 0x0c, 0xbf, 0x2e, 0x46, 0x02, 0x26, 0x00, 0x21, 0x00, 0x20, 0xed, 0xf7, - 0x92, 0xfa, 0x00, 0x98, 0x10, 0xb9, 0x01, 0x20, 0x60, 0x76, 0xf1, 0xbd, - 0x00, 0x99, 0x2b, 0x4a, 0x00, 0x20, 0x08, 0x60, 0x00, 0x99, 0x48, 0x71, - 0x00, 0x99, 0x94, 0xf8, 0xb8, 0x01, 0x08, 0x71, 0x00, 0x99, 0x60, 0x6a, - 0xc8, 0x60, 0x00, 0x99, 0xa0, 0x6a, 0x08, 0x61, 0x00, 0x99, 0x00, 0x98, - 0x00, 0xf5, 0x96, 0x60, 0x48, 0x61, 0x04, 0xf1, 0x38, 0x00, 0x00, 0x99, - 0x88, 0x60, 0x60, 0x68, 0x00, 0x99, 0x18, 0x30, 0x88, 0x61, 0x00, 0x21, - 0x00, 0x20, 0xed, 0xf7, 0xf8, 0xfa, 0x00, 0x98, 0x00, 0x7f, 0xa0, 0x76, - 0x60, 0x69, 0x28, 0xb1, 0x00, 0x99, 0xcc, 0x22, 0x01, 0xf5, 0x79, 0x71, - 0xf3, 0xf7, 0x92, 0xfc, 0xe0, 0x68, 0x28, 0xb1, 0x00, 0x99, 0xcc, 0x22, - 0x01, 0xf5, 0x96, 0x61, 0xf3, 0xf7, 0x8a, 0xfc, 0xef, 0xf3, 0x11, 0x87, - 0x60, 0x20, 0x80, 0xf3, 0x11, 0x88, 0x30, 0x46, 0xee, 0xf7, 0x23, 0xff, - 0x00, 0x99, 0x01, 0xf5, 0x79, 0x71, 0xee, 0xf7, 0xbd, 0xfe, 0x10, 0xb9, - 0x01, 0x20, 0xe0, 0x76, 0x0b, 0xe0, 0x00, 0x2d, 0x0c, 0xbf, 0x0a, 0x21, - 0x0e, 0x21, 0x30, 0x46, 0xee, 0xf7, 0x1f, 0xff, 0x60, 0x78, 0x10, 0xb9, - 0x28, 0x46, 0xf8, 0xf7, 0xf4, 0xf9, 0x87, 0xf3, 0x11, 0x88, 0x00, 0x20, - 0xed, 0xf7, 0x7f, 0xfa, 0xf1, 0xbd, 0x00, 0x00, 0xcb, 0x62, 0x01, 0x01, - 0x10, 0xb5, 0x04, 0x46, 0xa0, 0xb0, 0x20, 0x78, 0x8d, 0xf8, 0x00, 0x00, - 0x60, 0x78, 0x8d, 0xf8, 0x01, 0x00, 0xa0, 0x78, 0x8d, 0xf8, 0x02, 0x00, - 0x60, 0x68, 0x01, 0x90, 0x04, 0xf1, 0x08, 0x00, 0x02, 0x90, 0x04, 0xf1, - 0x38, 0x00, 0x03, 0x90, 0xa1, 0x78, 0x60, 0x78, 0xfd, 0xf7, 0x54, 0xff, - 0x68, 0x46, 0xfd, 0xf7, 0x6d, 0xfd, 0x20, 0x69, 0x20, 0xb1, 0x03, 0x99, - 0x4f, 0xf4, 0xc0, 0x72, 0xf3, 0xf7, 0x42, 0xfc, 0x9d, 0xf9, 0x10, 0x00, - 0x40, 0x42, 0x84, 0xf8, 0xb8, 0x01, 0x9d, 0xf8, 0x11, 0x00, 0x20, 0x76, - 0x05, 0x98, 0x20, 0x62, 0x06, 0x98, 0x60, 0x62, 0x07, 0x98, 0xa0, 0x62, - 0x20, 0xb0, 0x10, 0xbd, 0x00, 0x21, 0x00, 0x20, 0x10, 0xb5, 0xed, 0xf7, - 0x4a, 0xf8, 0x60, 0x48, 0x01, 0x78, 0x00, 0x24, 0x39, 0xb1, 0x41, 0x78, - 0x90, 0xf9, 0x02, 0x00, 0x40, 0x18, 0xc0, 0xb2, 0x00, 0xf0, 0x00, 0xf9, - 0x0d, 0xe0, 0x5b, 0x48, 0x80, 0x7a, 0x10, 0xf0, 0x03, 0x00, 0x08, 0xbf, - 0x01, 0x24, 0x06, 0xd0, 0x00, 0xf0, 0x01, 0x00, 0x80, 0xf0, 0x01, 0x00, - 0x00, 0xf0, 0x06, 0xf8, 0x04, 0x46, 0x00, 0x20, 0xed, 0xf7, 0x8a, 0xf8, - 0x20, 0x46, 0x10, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x89, 0xb0, 0x05, 0x46, - 0x04, 0xa8, 0xef, 0xf7, 0x7c, 0xfa, 0x69, 0x46, 0x28, 0x46, 0xf0, 0xf7, - 0x15, 0xff, 0xdd, 0xe9, 0x00, 0x01, 0xcd, 0xe9, 0x02, 0x01, 0x02, 0xaa, - 0x02, 0x21, 0x28, 0x46, 0xf0, 0xf7, 0x43, 0xff, 0x00, 0x21, 0x00, 0x20, - 0x00, 0xf0, 0xd4, 0xf8, 0x01, 0x21, 0xe8, 0xb2, 0xef, 0xf7, 0x68, 0xf9, - 0x44, 0x4a, 0x0f, 0xf2, 0xc0, 0x19, 0xd2, 0xe9, 0x08, 0x01, 0xef, 0xf7, - 0x11, 0xfa, 0x01, 0x46, 0xe8, 0xb2, 0xef, 0xf7, 0x2b, 0xfa, 0x3e, 0x48, - 0xc0, 0x69, 0x40, 0x00, 0x05, 0x21, 0xb0, 0xfb, 0xf1, 0xf2, 0x00, 0x23, - 0x28, 0x46, 0xfe, 0xf7, 0x91, 0xf9, 0x3b, 0x48, 0x3b, 0x49, 0x00, 0x78, - 0x08, 0x70, 0x06, 0x23, 0x0f, 0xf2, 0x84, 0x12, 0x80, 0x08, 0x06, 0x21, - 0x90, 0xfb, 0xf1, 0xf1, 0x03, 0xfb, 0x11, 0x00, 0x88, 0x46, 0x10, 0xf8, - 0x02, 0xa0, 0x00, 0x26, 0x01, 0xe0, 0x00, 0x2c, 0x46, 0xd1, 0x00, 0x27, - 0x5f, 0xfa, 0x87, 0xfb, 0x19, 0xf8, 0x1b, 0x10, 0x40, 0xf2, 0x32, 0x70, - 0xec, 0xf7, 0x88, 0xfd, 0x09, 0xeb, 0x4b, 0x00, 0x00, 0x24, 0x41, 0x78, - 0x40, 0xf2, 0x34, 0x70, 0xec, 0xf7, 0x80, 0xfd, 0x01, 0x21, 0x40, 0xf2, - 0x33, 0x70, 0xec, 0xf7, 0x7b, 0xfd, 0x00, 0x21, 0x40, 0xf2, 0x35, 0x70, - 0xec, 0xf7, 0x76, 0xfd, 0x51, 0x46, 0x40, 0xf2, 0x36, 0x70, 0xec, 0xf7, - 0x71, 0xfd, 0xff, 0x21, 0x40, 0xf2, 0x31, 0x70, 0xec, 0xf7, 0x6c, 0xfd, - 0x00, 0x2d, 0x0c, 0xbf, 0x4f, 0xf0, 0x01, 0x0b, 0x4f, 0xf0, 0x02, 0x0b, - 0x4b, 0xea, 0x48, 0x11, 0xc9, 0xb2, 0x4f, 0xf4, 0xe6, 0x60, 0xec, 0xf7, - 0x5f, 0xfd, 0x42, 0xf2, 0x10, 0x73, 0x00, 0x22, 0x59, 0x46, 0x4f, 0xf4, - 0xe6, 0x60, 0xf3, 0xf7, 0x1b, 0xfa, 0x00, 0xb1, 0x03, 0x24, 0x4c, 0xb9, - 0x14, 0x48, 0x00, 0x78, 0x06, 0xa9, 0x71, 0x18, 0x07, 0xeb, 0x47, 0x02, - 0x7f, 0x1c, 0x50, 0x54, 0x02, 0x2f, 0xb9, 0xd3, 0x76, 0x1c, 0x03, 0x2e, - 0xb3, 0xd3, 0x1c, 0xb9, 0x06, 0xa8, 0x00, 0xf0, 0x1b, 0xf8, 0x04, 0x46, - 0x69, 0x46, 0x28, 0x46, 0xf0, 0xf7, 0xa8, 0xfe, 0xfe, 0xf7, 0xe8, 0xf8, - 0x04, 0xa8, 0xef, 0xf7, 0xf3, 0xf9, 0x20, 0x46, 0x09, 0xb0, 0xbd, 0xe8, - 0xf0, 0x8f, 0x00, 0x00, 0xb4, 0x2a, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, - 0x00, 0xf2, 0x00, 0x20, 0xe6, 0x04, 0x00, 0x46, 0x9f, 0xf3, 0x00, 0x20, - 0x37, 0x07, 0x00, 0x46, 0x70, 0xb5, 0x00, 0x24, 0x00, 0x22, 0x00, 0xeb, - 0x42, 0x03, 0x00, 0x21, 0xd9, 0x80, 0x02, 0xeb, 0x42, 0x06, 0x36, 0x18, - 0xdd, 0x88, 0x8e, 0x5d, 0x49, 0x1c, 0x75, 0x19, 0x03, 0x29, 0xdd, 0x80, - 0xf5, 0xd3, 0xad, 0xb2, 0x03, 0x21, 0x52, 0x1c, 0xb5, 0xfb, 0xf1, 0xf1, - 0x02, 0x2a, 0xd9, 0x80, 0xe9, 0xd3, 0x00, 0x22, 0x00, 0x21, 0x02, 0xeb, - 0x42, 0x03, 0x1b, 0x18, 0xcb, 0x5c, 0x5b, 0xb1, 0x80, 0x2b, 0x09, 0xda, - 0x00, 0xeb, 0x42, 0x06, 0xf6, 0x88, 0x9d, 0x1b, 0x4c, 0xbf, 0xf3, 0x1a, - 0x9b, 0x1b, 0x9b, 0xb2, 0x04, 0x2b, 0x00, 0xd3, 0x02, 0x24, 0x49, 0x1c, - 0x03, 0x29, 0xea, 0xd3, 0x52, 0x1c, 0x02, 0x2a, 0xe6, 0xd3, 0x3c, 0xb9, - 0xc1, 0x88, 0x00, 0x89, 0x09, 0x1a, 0xc9, 0xb2, 0x48, 0x1e, 0xc0, 0xb2, - 0x00, 0xf0, 0x02, 0xf8, 0x20, 0x46, 0x70, 0xbd, 0x10, 0xb5, 0x0c, 0x46, - 0x01, 0x46, 0x40, 0xf6, 0x65, 0x10, 0xec, 0xf7, 0xe3, 0xfc, 0x21, 0x46, - 0xbd, 0xe8, 0x10, 0x40, 0x40, 0xf6, 0x66, 0x10, 0xec, 0xf7, 0xdc, 0xbc, - 0xcb, 0xb5, 0xa1, 0x8f, 0x80, 0x72, 0x00, 0x00, 0x78, 0x00, 0x01, 0x28, - 0x3e, 0x48, 0x0f, 0xf2, 0x10, 0x12, 0x2d, 0xe9, 0xf0, 0x4f, 0x44, 0x68, - 0xef, 0xf3, 0x08, 0x80, 0x20, 0x60, 0x00, 0x21, 0xef, 0xf3, 0x09, 0x80, - 0x60, 0x60, 0xef, 0xf3, 0x03, 0x80, 0xe0, 0x60, 0x04, 0xf1, 0x10, 0x00, - 0x52, 0xf8, 0x21, 0x30, 0x1b, 0x68, 0x40, 0xf8, 0x21, 0x30, 0x49, 0x1c, - 0x13, 0x29, 0xf7, 0xd3, 0x15, 0x22, 0x04, 0xf1, 0x5c, 0x01, 0x0f, 0xf2, - 0x24, 0x10, 0xec, 0xf7, 0xe6, 0xfc, 0x20, 0x68, 0x41, 0x6c, 0xa1, 0x60, - 0x11, 0xf1, 0x0f, 0x0f, 0x18, 0xbf, 0x11, 0xf1, 0x07, 0x0f, 0x06, 0xd1, - 0xc1, 0x6d, 0x61, 0x67, 0x00, 0x6e, 0xa0, 0x67, 0x20, 0x68, 0x40, 0x6e, - 0x02, 0xe0, 0x00, 0x20, 0x60, 0x67, 0xa0, 0x67, 0xe0, 0x67, 0x25, 0x48, - 0x00, 0x68, 0x90, 0xf8, 0x32, 0x00, 0xc4, 0xf8, 0x80, 0x00, 0xbd, 0xe8, - 0xf0, 0x4f, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x20, 0x4c, 0x4f, 0xf0, - 0xee, 0x31, 0x20, 0x46, 0xec, 0xf7, 0xd9, 0xfc, 0x1b, 0x4d, 0x1e, 0x49, - 0xef, 0xf3, 0x08, 0x80, 0xa8, 0x60, 0x88, 0x42, 0x24, 0xbf, 0x1c, 0x4a, - 0x82, 0x42, 0x04, 0xd2, 0x1b, 0x48, 0x08, 0x18, 0x40, 0x08, 0x80, 0xf3, - 0x08, 0x88, 0x05, 0xf1, 0x0c, 0x00, 0x68, 0x60, 0xff, 0xf7, 0xa6, 0xff, - 0x0d, 0x20, 0xf1, 0xf7, 0x56, 0xfc, 0x4f, 0xf0, 0xff, 0x31, 0x20, 0x46, - 0xec, 0xf7, 0xbd, 0xfc, 0x80, 0x22, 0x00, 0x23, 0x80, 0x20, 0x00, 0x21, - 0xf1, 0xf7, 0xd6, 0xfc, 0x0a, 0x20, 0xf7, 0xf7, 0xc1, 0xf8, 0xf8, 0xf7, - 0x77, 0xfe, 0x00, 0xb1, 0x01, 0x20, 0x28, 0x70, 0xf8, 0xf7, 0x5a, 0xfe, - 0x20, 0x68, 0x00, 0x28, 0xfc, 0xd1, 0x28, 0x78, 0x08, 0xb1, 0xf8, 0xf7, - 0x4d, 0xfe, 0xf7, 0xf7, 0xbb, 0xf8, 0xbd, 0xe8, 0xf0, 0x4f, 0x70, 0x47, - 0xe8, 0xb7, 0x00, 0x20, 0x40, 0xbd, 0x00, 0x20, 0xf0, 0x7f, 0x01, 0x01, - 0x90, 0xb8, 0x00, 0x20, 0x6c, 0xbc, 0x00, 0x20, 0x90, 0xbc, 0x00, 0x20, - 0x00, 0xe3, 0x00, 0xe0, 0x04, 0xe3, 0x00, 0xe0, 0x04, 0xed, 0x00, 0xe0, - 0x24, 0xed, 0x00, 0xe0, 0x28, 0xed, 0x00, 0xe0, 0x2c, 0xed, 0x00, 0xe0, - 0x38, 0xed, 0x00, 0xe0, 0x40, 0x00, 0x00, 0x50, 0x44, 0x00, 0x00, 0x50, - 0x48, 0x00, 0x00, 0x50, 0x40, 0x00, 0x00, 0x58, 0x44, 0x00, 0x00, 0x58, - 0x00, 0x00, 0x00, 0x49, 0x04, 0x00, 0x00, 0x49, 0x08, 0x00, 0x00, 0x49, - 0x0c, 0x00, 0x00, 0x49, 0x10, 0x00, 0x00, 0x49, 0x14, 0x00, 0x00, 0x49, - 0x18, 0x00, 0x00, 0x49, 0x00, 0x0d, 0x01, 0x0d, 0x08, 0x0d, 0x09, 0x0d, - 0x50, 0x0c, 0x51, 0x0c, 0x52, 0x0c, 0x53, 0x0c, 0x54, 0x0c, 0x55, 0x0c, - 0x56, 0x0c, 0x57, 0x0c, 0x58, 0x0c, 0x59, 0x0c, 0x5a, 0x0c, 0x5b, 0x0c, - 0x5c, 0x0c, 0x5d, 0x0c, 0x5e, 0x0c, 0x5f, 0x0c, 0x60, 0x0c, 0x00, 0x00, - 0xb8, 0x2a, 0x00, 0x20, 0x22, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, - 0x86, 0x00, 0x00, 0x00, 0x88, 0xf3, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb4, 0x2a, 0x00, 0x20, - 0x03, 0x00, 0x00, 0x00, 0x70, 0x29, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, - 0x68, 0xf3, 0x00, 0x20, 0x01, 0x00, 0x00, 0x00, 0x20, 0x29, 0x00, 0x20, - 0x2c, 0x00, 0x00, 0x00, 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, - 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, 0x68, 0x2b, 0x00, 0x20, - 0x24, 0x00, 0x00, 0x00, 0xf8, 0x28, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, - 0x2c, 0x2a, 0x00, 0x20, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xdc, 0x29, 0x00, 0x20, 0x28, 0x00, 0x00, 0x00, - 0x9c, 0x28, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x26, 0x00, 0x20, - 0x18, 0x00, 0x00, 0x00, 0x2c, 0x2c, 0x00, 0x20, 0x2c, 0x00, 0x00, 0x00, - 0x70, 0xf3, 0x00, 0x20, 0x02, 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, 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, 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, 0x50, 0x2a, 0x00, 0x20, - 0x64, 0x2a, 0x00, 0x20, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x2a, 0x00, 0x20, - 0x18, 0x2a, 0x00, 0x20, 0x14, 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, 0x70, 0x47, 0x2d, 0xe9, - 0xf8, 0x46, 0x89, 0x46, 0x00, 0x21, 0x00, 0x20, 0xec, 0xf7, 0x9f, 0xfd, - 0x48, 0x46, 0x00, 0xf0, 0x8d, 0xf8, 0x42, 0x4d, 0x42, 0x4c, 0x68, 0x89, - 0x00, 0x26, 0xc0, 0xf3, 0x01, 0x10, 0x00, 0x28, 0x40, 0xf2, 0x99, 0x6a, - 0x2c, 0xd0, 0xe8, 0x6c, 0x00, 0xf0, 0x6f, 0xf8, 0x10, 0xb1, 0xf7, 0xf7, - 0x63, 0xf8, 0x08, 0xb9, 0x01, 0x26, 0x42, 0xe0, 0xe8, 0x6c, 0x00, 0xf0, - 0x4e, 0xf8, 0xa8, 0xbf, 0x64, 0x20, 0x00, 0xf0, 0x45, 0xf8, 0x00, 0xf0, - 0x5b, 0xf8, 0x9c, 0x21, 0x00, 0xf0, 0x59, 0xf8, 0x00, 0xf0, 0x49, 0xf8, - 0x00, 0xf0, 0x4c, 0xf8, 0x08, 0xb1, 0x02, 0x26, 0x2f, 0xe0, 0x31, 0x4f, - 0x39, 0x78, 0x40, 0xf6, 0x93, 0x00, 0xec, 0xf7, 0x1b, 0xfb, 0x7a, 0x78, - 0x1f, 0x21, 0x40, 0xf6, 0x94, 0x00, 0xec, 0xf7, 0x1f, 0xfb, 0x39, 0x79, - 0x40, 0xf6, 0x95, 0x00, 0xec, 0xf7, 0x10, 0xfb, 0x68, 0x89, 0xc0, 0xf3, - 0x81, 0x00, 0xd0, 0xb1, 0xa8, 0x6b, 0x00, 0xf0, 0x3e, 0xf8, 0x10, 0xb1, - 0xf7, 0xf7, 0x32, 0xf8, 0x08, 0xb9, 0x03, 0x26, 0x11, 0xe0, 0xa8, 0x6b, - 0x00, 0xf0, 0x1d, 0xf8, 0xa8, 0xbf, 0x64, 0x20, 0x00, 0xf0, 0x14, 0xf8, - 0x00, 0xf0, 0x2a, 0xf8, 0x9c, 0x21, 0x00, 0xf0, 0x28, 0xf8, 0x00, 0xf0, - 0x18, 0xf8, 0x00, 0xf0, 0x1b, 0xf8, 0x00, 0xb1, 0x04, 0x26, 0x48, 0x46, - 0x00, 0xf0, 0x43, 0xf8, 0x00, 0x20, 0xec, 0xf7, 0x9d, 0xfd, 0x30, 0x46, - 0xbd, 0xe8, 0xf2, 0x86, 0x00, 0xf0, 0x7f, 0x01, 0x50, 0x46, 0xec, 0xf7, - 0xe3, 0xba, 0x13, 0x49, 0xb0, 0xfb, 0xf1, 0xf0, 0xc0, 0xb2, 0x65, 0x28, - 0x70, 0x47, 0x20, 0x21, 0x4f, 0xf4, 0xd9, 0x70, 0xec, 0xf7, 0xd8, 0xba, - 0x4f, 0xf4, 0x7a, 0x73, 0x00, 0x22, 0x20, 0x21, 0x4f, 0xf4, 0xd9, 0x70, - 0xf2, 0xf7, 0x94, 0xbf, 0x1c, 0x21, 0x4f, 0xf4, 0xd2, 0x60, 0xec, 0xf7, - 0xcb, 0xba, 0xa4, 0xfb, 0x00, 0x23, 0x12, 0x0f, 0x42, 0xea, 0x03, 0x12, - 0x1b, 0x0f, 0x00, 0x20, 0xf7, 0xf7, 0x11, 0xb8, 0x78, 0x29, 0x00, 0x20, - 0x22, 0x18, 0x09, 0x91, 0x93, 0x06, 0x00, 0x46, 0x40, 0x42, 0x0f, 0x00, - 0x80, 0xb5, 0x00, 0x21, 0xff, 0xf7, 0xda, 0xff, 0x00, 0xf0, 0x18, 0xf8, - 0x1b, 0x21, 0x40, 0xf2, 0x91, 0x60, 0xec, 0xf7, 0xaf, 0xfa, 0xbd, 0xe8, - 0x04, 0x40, 0x7c, 0x21, 0x0a, 0xe0, 0x80, 0xb5, 0x00, 0xf0, 0x0c, 0xf8, - 0xdb, 0x21, 0x40, 0xf2, 0x91, 0x60, 0xec, 0xf7, 0xa3, 0xfa, 0xbd, 0xe8, - 0x04, 0x40, 0x7e, 0x21, 0x40, 0xf2, 0x0b, 0x20, 0xec, 0xf7, 0x9c, 0xba, - 0x07, 0x21, 0x40, 0xf2, 0x83, 0x10, 0xec, 0xf7, 0x97, 0xba, 0x00, 0x00, - 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, - 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, - 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, - 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, - 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, 0xfe, 0xe7, - 0xfe, 0xe7, 0xfe, 0xe7, 0x2e, 0x4c, 0x2f, 0x48, 0x2f, 0x4d, 0x30, 0x49, - 0x20, 0x60, 0x20, 0x60, 0x01, 0x22, 0x00, 0x20, 0x28, 0x60, 0x08, 0x60, - 0x2d, 0x49, 0x08, 0x60, 0x0f, 0xf2, 0xd0, 0x01, 0x0f, 0xf2, 0xc8, 0x00, - 0x00, 0xf0, 0x66, 0xf8, 0x2a, 0x49, 0x28, 0x60, 0x09, 0x68, 0x88, 0x42, - 0x00, 0xd0, 0xfe, 0xe7, 0x00, 0x20, 0x20, 0x60, 0x20, 0x60, 0x27, 0x49, - 0x27, 0x48, 0x01, 0x60, 0x4f, 0xf4, 0xe0, 0x21, 0xc1, 0x61, 0x00, 0xf0, - 0x02, 0xf8, 0x00, 0xf0, 0xab, 0xb8, 0x1c, 0x48, 0x23, 0x4c, 0x4f, 0xf6, - 0xfe, 0x61, 0x01, 0x60, 0x01, 0x60, 0x22, 0x49, 0x0a, 0x78, 0x0b, 0x78, - 0x43, 0xf0, 0x08, 0x03, 0x0b, 0x70, 0x23, 0x46, 0x1d, 0x68, 0x1d, 0x60, - 0x1e, 0x68, 0xae, 0x42, 0x03, 0xd0, 0x17, 0x48, 0x00, 0x68, 0x03, 0x60, - 0xfe, 0xe7, 0x1b, 0x1d, 0x04, 0xf5, 0x80, 0x75, 0xab, 0x42, 0xf1, 0xd3, - 0x18, 0x4d, 0xab, 0x42, 0x14, 0xd2, 0x4f, 0xf0, 0xff, 0x35, 0x1d, 0x60, - 0x1d, 0x68, 0x15, 0xf1, 0x01, 0x0f, 0x03, 0xd0, 0x0d, 0x48, 0x00, 0x68, - 0x03, 0x60, 0xfe, 0xe7, 0x00, 0x25, 0x1d, 0x60, 0x1d, 0x68, 0x1d, 0xb1, - 0x09, 0x48, 0x00, 0x68, 0x03, 0x60, 0xfe, 0xe7, 0x1b, 0x1d, 0xe7, 0xe7, - 0x0a, 0x70, 0x00, 0x21, 0x01, 0x60, 0x01, 0x60, 0x70, 0x47, 0x00, 0x00, - 0x48, 0x00, 0x00, 0x50, 0x00, 0x00, 0xab, 0xab, 0xe4, 0x7f, 0x01, 0x01, - 0xf0, 0x7f, 0x01, 0x01, 0xf4, 0x7f, 0x01, 0x01, 0xe0, 0x7f, 0x01, 0x01, - 0x00, 0x00, 0x00, 0x01, 0x08, 0xed, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x20, - 0x00, 0x0d, 0x00, 0x46, 0xff, 0xff, 0x00, 0x20, 0x00, 0x00, 0x00, 0x01, - 0xdf, 0x7f, 0x01, 0x01, 0x2d, 0xe9, 0xf0, 0x41, 0x00, 0x23, 0x00, 0x25, - 0x0f, 0xf2, 0x64, 0x08, 0x15, 0xe0, 0x17, 0xf8, 0x06, 0xe0, 0x4f, 0xea, - 0x1e, 0x14, 0x44, 0xea, 0x03, 0x14, 0x1b, 0x0f, 0x58, 0xf8, 0x23, 0x30, - 0x63, 0x40, 0x0e, 0xf0, 0x0f, 0x04, 0x44, 0xea, 0x03, 0x14, 0x1b, 0x0f, - 0x58, 0xf8, 0x23, 0x30, 0x63, 0x40, 0x7f, 0x1c, 0x67, 0x45, 0xea, 0xd3, - 0x6d, 0x1c, 0x95, 0x42, 0x08, 0xd2, 0x50, 0xf8, 0x25, 0x60, 0x51, 0xf8, - 0x25, 0x70, 0xbf, 0x1b, 0x07, 0xf1, 0x01, 0x0c, 0x00, 0x27, 0xf1, 0xe7, - 0x04, 0x20, 0x19, 0x0f, 0x58, 0xf8, 0x21, 0x10, 0x81, 0xea, 0x03, 0x11, - 0x0a, 0x0f, 0x58, 0xf8, 0x22, 0x20, 0x40, 0x1e, 0x82, 0xea, 0x01, 0x13, - 0xf3, 0xd1, 0x18, 0x46, 0xbd, 0xe8, 0xf0, 0x81, 0x00, 0x00, 0x00, 0x00, - 0xb7, 0x1d, 0xc1, 0x04, 0x6e, 0x3b, 0x82, 0x09, 0xd9, 0x26, 0x43, 0x0d, - 0xdc, 0x76, 0x04, 0x13, 0x6b, 0x6b, 0xc5, 0x17, 0xb2, 0x4d, 0x86, 0x1a, - 0x05, 0x50, 0x47, 0x1e, 0xb8, 0xed, 0x08, 0x26, 0x0f, 0xf0, 0xc9, 0x22, - 0xd6, 0xd6, 0x8a, 0x2f, 0x61, 0xcb, 0x4b, 0x2b, 0x64, 0x9b, 0x0c, 0x35, - 0xd3, 0x86, 0xcd, 0x31, 0x0a, 0xa0, 0x8e, 0x3c, 0xbd, 0xbd, 0x4f, 0x38, - 0x01, 0x20, 0xc0, 0x46, 0x00, 0x28, 0x01, 0xd0, 0x00, 0xf0, 0x08, 0xf8, - 0x00, 0x20, 0xc0, 0x46, 0xc0, 0x46, 0x00, 0xf0, 0x17, 0xf8, 0x00, 0xf0, - 0x6f, 0xf8, 0x00, 0x00, 0x10, 0xb5, 0x07, 0x49, 0x79, 0x44, 0x18, 0x31, - 0x06, 0x4c, 0x7c, 0x44, 0x16, 0x34, 0x04, 0xe0, 0x0a, 0x68, 0x08, 0x1d, - 0x51, 0x18, 0x88, 0x47, 0x01, 0x46, 0xa1, 0x42, 0xf8, 0xd1, 0x10, 0xbd, - 0x20, 0x0a, 0x00, 0x00, 0xfc, 0x0a, 0x00, 0x00, 0x00, 0xb5, 0x87, 0xb0, - 0xf1, 0xf7, 0x12, 0xf9, 0xc0, 0x46, 0xc0, 0x46, 0xc0, 0x46, 0xc0, 0x46, - 0xea, 0xf7, 0x74, 0xff, 0x03, 0x21, 0x04, 0x91, 0x00, 0x21, 0x03, 0x91, - 0x64, 0x21, 0x02, 0x91, 0x05, 0x21, 0x1e, 0x48, 0x01, 0x90, 0x00, 0x91, - 0x00, 0xf5, 0xc6, 0x72, 0x05, 0x23, 0x00, 0x21, 0x0f, 0xf2, 0x1d, 0x00, - 0xeb, 0xf7, 0xdd, 0xfd, 0x05, 0xaa, 0x0f, 0xf2, 0x70, 0x01, 0x05, 0x20, - 0xeb, 0xf7, 0x8e, 0xfe, 0xeb, 0xf7, 0x2b, 0xf8, 0x00, 0x20, 0x07, 0xb0, - 0x00, 0xbd, 0x00, 0x00, 0x80, 0xb5, 0xf0, 0xf7, 0x71, 0xff, 0x40, 0x1e, - 0x80, 0x41, 0xc0, 0x0f, 0xf1, 0xf7, 0x6d, 0xf8, 0xf7, 0xf7, 0x54, 0xf8, - 0x0e, 0x48, 0x00, 0x6c, 0x40, 0x1e, 0xb0, 0xf1, 0x80, 0x7f, 0x08, 0xd2, - 0x0c, 0x49, 0x0d, 0x4a, 0x48, 0x60, 0xf0, 0x20, 0x10, 0x70, 0x00, 0x20, - 0x88, 0x60, 0x07, 0x20, 0x08, 0x60, 0xea, 0xf7, 0xe1, 0xff, 0x68, 0x46, - 0xf2, 0xf7, 0xba, 0xfb, 0xea, 0xf7, 0xf1, 0xff, 0xf2, 0xf7, 0xec, 0xff, - 0xf2, 0xf7, 0xb2, 0xff, 0xfc, 0xe7, 0x00, 0x00, 0x48, 0x80, 0x00, 0x20, - 0x00, 0xf2, 0x00, 0x20, 0x10, 0xe0, 0x00, 0xe0, 0x23, 0xed, 0x00, 0xe0, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0xb8, - 0x07, 0x46, 0x38, 0x46, 0x00, 0xf0, 0x02, 0xf8, 0xfb, 0xe7, 0x00, 0x00, - 0x80, 0xb5, 0xc0, 0x46, 0xc0, 0x46, 0x02, 0x4a, 0x11, 0x00, 0x18, 0x20, - 0xab, 0xbe, 0xfb, 0xe7, 0x26, 0x00, 0x02, 0x00, 0x49, 0x6e, 0x69, 0x74, - 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, - 0x52, 0x78, 0x31, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0x52, 0x78, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0x54, 0x78, 0x31, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0x54, 0x78, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0x54, 0x78, 0x31, 0x20, 0x4c, 0x4f, 0x4c, 0x20, 0x43, 0x61, 0x6c, 0x54, - 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, 0x4c, 0x4f, 0x4c, 0x20, - 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x4f, 0x52, 0x58, 0x31, - 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, - 0x4f, 0x52, 0x58, 0x32, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, 0x44, 0x50, 0x44, 0x20, - 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, - 0x44, 0x50, 0x44, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0x54, 0x78, 0x31, 0x20, 0x43, 0x4c, 0x47, 0x43, 0x20, 0x43, 0x61, 0x6c, - 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x32, 0x20, - 0x43, 0x4c, 0x47, 0x43, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, - 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, 0x56, 0x53, 0x57, 0x52, - 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, - 0x54, 0x78, 0x32, 0x20, 0x56, 0x53, 0x57, 0x52, 0x20, 0x43, 0x61, 0x6c, - 0x54, 0x61, 0x73, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x54, 0x78, 0x31, 0x20, - 0x50, 0x41, 0x20, 0x42, 0x49, 0x41, 0x53, 0x20, 0x43, 0x61, 0x6c, 0x54, - 0x61, 0x73, 0x6b, 0x00, 0x54, 0x78, 0x32, 0x20, 0x50, 0x41, 0x20, 0x42, - 0x49, 0x41, 0x53, 0x20, 0x43, 0x61, 0x6c, 0x54, 0x61, 0x73, 0x6b, 0x00, - 0xc5, 0xfe, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x31, 0x16, 0x00, 0x01, 0x38, 0x00, 0x00, 0x00, - 0xdd, 0x59, 0x01, 0x01, 0xe5, 0x59, 0x01, 0x01, 0x38, 0x00, 0x00, 0x00, - 0xc7, 0xdc, 0x00, 0x01, 0xe5, 0xdc, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xf5, 0x61, 0x00, 0x01, 0xf7, 0x61, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, - 0x4b, 0x34, 0x00, 0x01, 0x4d, 0x34, 0x00, 0x01, 0xf8, 0x00, 0x00, 0x00, - 0x98, 0x02, 0x00, 0x20, 0x10, 0x01, 0x00, 0x00, 0xa8, 0x03, 0x00, 0x20, - 0x10, 0x01, 0x00, 0x00, 0xdc, 0x2a, 0x00, 0x20, 0x48, 0x00, 0x00, 0x00, - 0x8c, 0x2b, 0x00, 0x20, 0x18, 0x00, 0x00, 0x00, 0x30, 0x27, 0x00, 0x20, - 0x44, 0x00, 0x01, 0x00, 0xd8, 0x26, 0x00, 0x20, 0x3a, 0x00, 0x01, 0x00, - 0xf8, 0x2b, 0x00, 0x20, 0x1a, 0x00, 0x00, 0x00, 0x74, 0xf3, 0x00, 0x20, - 0x02, 0x00, 0x00, 0x00, 0x04, 0xea, 0x00, 0x20, 0xa0, 0xea, 0x00, 0x20, - 0x9c, 0x00, 0x00, 0x00, 0x3c, 0xeb, 0x00, 0x20, 0xd8, 0xeb, 0x00, 0x20, - 0x9c, 0x00, 0x00, 0x00, 0x98, 0xf1, 0x00, 0x20, 0xcc, 0xf1, 0x00, 0x20, - 0x34, 0x00, 0x00, 0x00, 0xb4, 0x2b, 0x00, 0x20, 0xd0, 0x2b, 0x00, 0x20, - 0x1c, 0x00, 0x00, 0x00, 0x74, 0x27, 0x00, 0x20, 0x08, 0x28, 0x00, 0x20, - 0x94, 0x00, 0x00, 0x00, 0xa8, 0xef, 0x00, 0x20, 0xec, 0xef, 0x00, 0x20, - 0x44, 0x00, 0x00, 0x00, 0x94, 0xed, 0x00, 0x20, 0xe8, 0xed, 0x00, 0x20, - 0x54, 0x00, 0x00, 0x00, 0x40, 0xf3, 0x00, 0x20, 0x44, 0xf3, 0x00, 0x20, - 0x04, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, - 0x83, 0xb0, 0x07, 0x46, 0xed, 0xf7, 0x12, 0xf9, 0xed, 0xf7, 0xe6, 0xf8, - 0x00, 0x2f, 0x04, 0x46, 0x0c, 0xbf, 0x02, 0x25, 0x03, 0x25, 0x35, 0x4e, - 0xdf, 0xf8, 0xd4, 0x80, 0xed, 0xf7, 0x13, 0xf9, 0xb8, 0x55, 0x4f, 0xf0, - 0x6c, 0x0a, 0x28, 0x46, 0xf8, 0xf7, 0x65, 0xff, 0x07, 0xf1, 0x1f, 0x00, - 0x8d, 0xf8, 0x04, 0x00, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, 0xed, 0xf7, - 0x27, 0xf9, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xed, 0xf7, - 0x81, 0xf9, 0xb8, 0x5d, 0x03, 0x21, 0xed, 0xf7, 0x1d, 0xf9, 0xb8, 0x5d, - 0x00, 0x21, 0xed, 0xf7, 0x19, 0xf9, 0x9d, 0xf8, 0x04, 0x00, 0x01, 0x21, - 0xf0, 0xf7, 0xc3, 0xff, 0xed, 0xf7, 0x48, 0xf9, 0xed, 0xf7, 0xed, 0xf8, - 0x0a, 0xfb, 0x00, 0x89, 0xeb, 0xf7, 0x56, 0xfd, 0xc9, 0xf8, 0x38, 0x00, - 0x4f, 0xf4, 0x60, 0x71, 0x06, 0xf1, 0x08, 0x00, 0x01, 0xfb, 0x07, 0x02, - 0x01, 0x21, 0x28, 0x46, 0xf8, 0xf7, 0x3c, 0xff, 0x81, 0x46, 0x00, 0x20, - 0xec, 0xf7, 0xb5, 0xfa, 0xed, 0xf7, 0xd7, 0xf8, 0x83, 0x46, 0xeb, 0xf7, - 0x41, 0xfd, 0x0a, 0xfb, 0x0b, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, - 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, - 0x00, 0x21, 0x9d, 0xf8, 0x04, 0x00, 0xf0, 0xf7, 0x96, 0xff, 0xb8, 0x5d, - 0xb9, 0xf1, 0x00, 0x0f, 0xb8, 0xd0, 0x02, 0x21, 0xed, 0xf7, 0xe0, 0xf8, - 0xb8, 0x5d, 0x01, 0x21, 0xed, 0xf7, 0xdc, 0xf8, 0xed, 0xf7, 0xbe, 0xf8, - 0x0d, 0xf1, 0x05, 0x01, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, - 0xeb, 0xf7, 0xbe, 0xf8, 0xa9, 0xe7, 0x00, 0x00, 0x48, 0xc8, 0x00, 0x20, - 0x8c, 0x09, 0x00, 0x20, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, - 0x83, 0xb0, 0x07, 0x46, 0xed, 0xf7, 0x94, 0xf8, 0xed, 0xf7, 0x68, 0xf8, - 0x04, 0x46, 0x38, 0x00, 0x18, 0xbf, 0x01, 0x20, 0x8d, 0xf8, 0x04, 0x00, - 0xed, 0xf7, 0x97, 0xf8, 0x32, 0x4d, 0xdf, 0xf8, 0xcc, 0x80, 0x78, 0x55, - 0x07, 0xf1, 0x1d, 0x06, 0x9d, 0xf8, 0x04, 0x00, 0xf8, 0xf7, 0xe5, 0xfe, - 0x4f, 0xf0, 0x6c, 0x0a, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, 0xed, 0xf7, - 0xa9, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xed, 0xf7, - 0x03, 0xf9, 0x78, 0x5d, 0x03, 0x21, 0xed, 0xf7, 0x9f, 0xf8, 0x78, 0x5d, - 0x00, 0x21, 0xed, 0xf7, 0x9b, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, - 0x46, 0xff, 0xed, 0xf7, 0xcb, 0xf8, 0xed, 0xf7, 0x70, 0xf8, 0x0a, 0xfb, - 0x00, 0x89, 0xeb, 0xf7, 0xd9, 0xfc, 0xc9, 0xf8, 0x38, 0x00, 0x4f, 0xf4, - 0x60, 0x71, 0x05, 0xf1, 0x08, 0x00, 0x01, 0xfb, 0x07, 0x02, 0x9d, 0xf8, - 0x04, 0x00, 0x01, 0x21, 0xf8, 0xf7, 0xbd, 0xfe, 0x81, 0x46, 0x00, 0x20, - 0xec, 0xf7, 0x37, 0xfa, 0xed, 0xf7, 0x59, 0xf8, 0x83, 0x46, 0xeb, 0xf7, - 0xc3, 0xfc, 0x0a, 0xfb, 0x0b, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, - 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, - 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x19, 0xff, 0x78, 0x5d, 0xb9, 0xf1, - 0x00, 0x0f, 0xb9, 0xd0, 0x02, 0x21, 0xed, 0xf7, 0x63, 0xf8, 0x78, 0x5d, - 0x01, 0x21, 0xed, 0xf7, 0x5f, 0xf8, 0xed, 0xf7, 0x41, 0xf8, 0x0d, 0xf1, - 0x05, 0x01, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xeb, 0xf7, - 0x41, 0xf8, 0xaa, 0xe7, 0x50, 0xcf, 0x00, 0x20, 0x8c, 0x09, 0x00, 0x20, - 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xfe, 0x4f, 0x05, 0x46, 0xed, 0xf7, - 0x19, 0xf8, 0xec, 0xf7, 0xed, 0xff, 0x04, 0x46, 0x02, 0x95, 0xed, 0xf7, - 0x20, 0xf8, 0x81, 0x46, 0x02, 0x98, 0xdf, 0xf8, 0xb8, 0x80, 0x01, 0x27, - 0x00, 0xf1, 0x25, 0x06, 0x4f, 0xf0, 0x6c, 0x0a, 0x44, 0xb9, 0x05, 0xe0, - 0x00, 0xf0, 0x56, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, - 0xed, 0xf7, 0x90, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x4e, 0xf8, 0x01, 0x21, - 0xf0, 0xb2, 0xf0, 0xf7, 0xd8, 0xfe, 0xed, 0xf7, 0x5d, 0xf8, 0xed, 0xf7, - 0x02, 0xf8, 0x0a, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0x6b, 0xfc, 0xa8, 0x63, - 0xc8, 0x23, 0x02, 0x99, 0x1d, 0x48, 0x03, 0xfb, 0x01, 0x01, 0x02, 0x98, - 0x3a, 0x46, 0xf6, 0xf7, 0x3b, 0xfd, 0x05, 0x46, 0x00, 0x21, 0xf0, 0xb2, - 0xf0, 0xf7, 0xc1, 0xfe, 0x00, 0x20, 0xec, 0xf7, 0xc8, 0xf9, 0xec, 0xf7, - 0xea, 0xff, 0x83, 0x46, 0xeb, 0xf7, 0x54, 0xfc, 0x0a, 0xfb, 0x0b, 0x81, - 0x00, 0x27, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, - 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, 0x01, 0x2d, 0x18, 0xbf, - 0x02, 0x2d, 0x04, 0xd0, 0x03, 0x2d, 0x1c, 0xbf, 0x04, 0x2d, 0x0c, 0x2d, - 0xbc, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x13, 0xf8, 0x00, 0xf0, 0x10, 0xf8, - 0xec, 0xf7, 0xd2, 0xff, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, - 0x20, 0x21, 0xea, 0xf7, 0xd3, 0xff, 0xaf, 0xe7, 0x00, 0x00, 0x00, 0x00, - 0x8c, 0x09, 0x00, 0x20, 0x74, 0xe8, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, - 0xec, 0xf7, 0xdc, 0xbf, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, - 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, 0xa4, 0xff, 0xec, 0xf7, 0x78, 0xff, - 0x04, 0x46, 0xec, 0xf7, 0xac, 0xff, 0x81, 0x46, 0x0b, 0xf1, 0x29, 0x06, - 0x6c, 0x27, 0xdf, 0xf8, 0xac, 0x80, 0x4c, 0xb9, 0x06, 0xe0, 0x01, 0x21, - 0x00, 0xf0, 0x54, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, - 0xed, 0xf7, 0x1e, 0xf8, 0x00, 0x21, 0x00, 0xf0, 0x4b, 0xf8, 0x01, 0x21, - 0xf0, 0xb2, 0xf0, 0xf7, 0x66, 0xfe, 0xec, 0xf7, 0xeb, 0xff, 0xec, 0xf7, - 0x90, 0xff, 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0xf9, 0xfb, 0xa8, 0x63, - 0x1d, 0x48, 0x00, 0xeb, 0x4b, 0x11, 0x58, 0x46, 0xee, 0xf7, 0x55, 0xff, - 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x5d, 0xf9, 0xec, 0xf7, 0x7f, 0xff, - 0x82, 0x46, 0xeb, 0xf7, 0xe9, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, - 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, - 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x3f, 0xfe, - 0x01, 0x2d, 0x18, 0xbf, 0x02, 0x2d, 0x04, 0xd0, 0x04, 0x2d, 0x1c, 0xbf, - 0x05, 0x2d, 0x0b, 0x2d, 0xbf, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x14, 0xf8, - 0x01, 0x21, 0x00, 0xf0, 0x11, 0xf8, 0xec, 0xf7, 0x63, 0xff, 0x01, 0xa9, - 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x64, 0xff, - 0x03, 0x21, 0xaf, 0xe7, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, - 0x48, 0xf2, 0x00, 0x20, 0x48, 0x46, 0xec, 0xf7, 0x6d, 0xbf, 0x00, 0x00, - 0x80, 0xb5, 0x01, 0x29, 0x08, 0xbf, 0xfe, 0xf7, 0xbe, 0xfb, 0x00, 0x20, - 0x02, 0xbd, 0x2d, 0xe9, 0xf0, 0x4f, 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, - 0x2f, 0xff, 0xec, 0xf7, 0x03, 0xff, 0x04, 0x46, 0xec, 0xf7, 0x37, 0xff, - 0x81, 0x46, 0x0b, 0xf1, 0x23, 0x06, 0x6c, 0x27, 0xdf, 0xf8, 0x98, 0x80, - 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, 0x4c, 0xf8, 0x14, 0xb1, 0x14, 0xf1, - 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, 0xaa, 0xff, 0x00, 0x21, 0x00, 0xf0, - 0x44, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xf2, 0xfd, 0xec, 0xf7, - 0x77, 0xff, 0xec, 0xf7, 0x1c, 0xff, 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, - 0x85, 0xfb, 0xa8, 0x63, 0x4f, 0xf4, 0x22, 0x71, 0x18, 0x48, 0x01, 0xfb, - 0x0b, 0x01, 0x58, 0x46, 0xfe, 0xf7, 0xd6, 0xfa, 0x05, 0x46, 0x00, 0x20, - 0xec, 0xf7, 0xe7, 0xf8, 0xec, 0xf7, 0x09, 0xff, 0x82, 0x46, 0xeb, 0xf7, - 0x73, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, 0x82, 0x42, 0x23, 0xbf, - 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, 0x80, 0x1a, 0xc8, 0x63, - 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xc9, 0xfd, 0x00, 0x2d, 0xc5, 0xd0, - 0x02, 0x21, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, 0x0f, 0xf8, 0xec, 0xf7, - 0xf5, 0xfe, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, - 0xea, 0xf7, 0xf6, 0xfe, 0xb8, 0xe7, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, - 0x58, 0xd6, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, 0xec, 0xf7, 0x00, 0xbf, - 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, 0x83, 0xb0, 0x83, 0x46, - 0xec, 0xf7, 0xc8, 0xfe, 0xec, 0xf7, 0x9c, 0xfe, 0x04, 0x46, 0xec, 0xf7, - 0xd0, 0xfe, 0x81, 0x46, 0x0b, 0xf1, 0x27, 0x06, 0x6c, 0x27, 0xdf, 0xf8, - 0xa0, 0x80, 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, 0x4d, 0xf8, 0x14, 0xb1, - 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, 0x43, 0xff, 0x00, 0x21, - 0x00, 0xf0, 0x45, 0xf8, 0x01, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x8b, 0xfd, - 0xec, 0xf7, 0x10, 0xff, 0xec, 0xf7, 0xb5, 0xfe, 0x07, 0xfb, 0x00, 0x85, - 0xeb, 0xf7, 0x1e, 0xfb, 0xa8, 0x63, 0x58, 0x46, 0xf3, 0xf7, 0xea, 0xf8, - 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x85, 0xf8, 0xec, 0xf7, 0xa7, 0xfe, - 0x82, 0x46, 0xeb, 0xf7, 0x11, 0xfb, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, - 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, - 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0x67, 0xfd, - 0x05, 0x2d, 0x18, 0xbf, 0x01, 0x2d, 0x04, 0xd0, 0x06, 0x2d, 0x1c, 0xbf, - 0x02, 0x2d, 0x0e, 0x2d, 0xc3, 0xd1, 0x02, 0x21, 0x00, 0xf0, 0x11, 0xf8, - 0x00, 0xf0, 0x0e, 0xf8, 0xec, 0xf7, 0x8c, 0xfe, 0x01, 0xa9, 0x00, 0x91, - 0x00, 0x23, 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x8d, 0xfe, 0xb6, 0xe7, - 0x00, 0x00, 0x00, 0x00, 0x8c, 0x09, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, - 0xec, 0xf7, 0x98, 0xbe, 0x00, 0x20, 0x70, 0x47, 0x2d, 0xe9, 0xf0, 0x4f, - 0x83, 0xb0, 0x83, 0x46, 0xec, 0xf7, 0x60, 0xfe, 0xec, 0xf7, 0x34, 0xfe, - 0x04, 0x46, 0xec, 0xf7, 0x68, 0xfe, 0x81, 0x46, 0x0b, 0xf1, 0x21, 0x06, - 0x6c, 0x27, 0xdf, 0xf8, 0x98, 0x80, 0x44, 0xb9, 0x05, 0xe0, 0x00, 0xf0, - 0x4b, 0xf8, 0x14, 0xb1, 0x14, 0xf1, 0x01, 0x0f, 0x01, 0xd0, 0xec, 0xf7, - 0xdb, 0xfe, 0x00, 0x21, 0x00, 0xf0, 0x43, 0xf8, 0x01, 0x21, 0xf0, 0xb2, - 0xf0, 0xf7, 0x23, 0xfd, 0xec, 0xf7, 0xa8, 0xfe, 0xec, 0xf7, 0x4d, 0xfe, - 0x07, 0xfb, 0x00, 0x85, 0xeb, 0xf7, 0xb6, 0xfa, 0xa8, 0x63, 0x38, 0x21, - 0x18, 0x48, 0x01, 0xfb, 0x0b, 0x01, 0x58, 0x46, 0xea, 0xf7, 0x2e, 0xf8, - 0x05, 0x46, 0x00, 0x20, 0xec, 0xf7, 0x19, 0xf8, 0xec, 0xf7, 0x3b, 0xfe, - 0x82, 0x46, 0xeb, 0xf7, 0xa5, 0xfa, 0x07, 0xfb, 0x0a, 0x81, 0x8a, 0x6b, - 0x82, 0x42, 0x23, 0xbf, 0x4f, 0xf0, 0xff, 0x33, 0x9a, 0x1a, 0x80, 0x18, - 0x80, 0x1a, 0xc8, 0x63, 0x00, 0x21, 0xf0, 0xb2, 0xf0, 0xf7, 0xfb, 0xfc, - 0x00, 0x2d, 0xc6, 0xd0, 0x02, 0x21, 0x00, 0xf0, 0x12, 0xf8, 0x00, 0xf0, - 0x0f, 0xf8, 0xec, 0xf7, 0x27, 0xfe, 0x01, 0xa9, 0x00, 0x91, 0x00, 0x23, - 0x82, 0x22, 0x20, 0x21, 0xea, 0xf7, 0x28, 0xfe, 0xb9, 0xe7, 0x00, 0x00, - 0x8c, 0x09, 0x00, 0x20, 0x28, 0xf1, 0x00, 0x20, 0x01, 0x21, 0x48, 0x46, - 0xec, 0xf7, 0x32, 0xbe, 0x78, 0x29, 0x00, 0x20, 0x64, 0x00, 0x00, 0x00, - 0x4c, 0x1f, 0x00, 0x20, 0x84, 0x00, 0x00, 0x00, 0xd4, 0x28, 0x00, 0x20, - 0x21, 0x00, 0x00, 0x00, 0x1c, 0x08, 0x00, 0x20, 0x5c, 0x00, 0x00, 0x00, - 0x84, 0xf3, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x1c, 0x1f, 0x00, 0x20, - 0x14, 0x00, 0x00, 0x00, 0x30, 0x1f, 0x00, 0x20, 0x08, 0x00, 0x00, 0x00, - 0x88, 0x02, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x19, 0xe0, 0x50, 0xf8, - 0x04, 0x1b, 0xcb, 0x07, 0x44, 0xbf, 0xa9, 0xf1, 0x01, 0x03, 0x59, 0x18, - 0x12, 0x1f, 0x00, 0x23, 0x04, 0x2a, 0x41, 0xf8, 0x04, 0x3b, 0xf9, 0xd2, - 0x5f, 0xea, 0x82, 0x7c, 0x0b, 0x46, 0x04, 0xd5, 0x4f, 0xf0, 0x00, 0x0c, - 0xa1, 0xf8, 0x00, 0xc0, 0x9b, 0x1c, 0xd1, 0x07, 0x44, 0xbf, 0x00, 0x21, - 0x19, 0x70, 0x50, 0xf8, 0x04, 0x2b, 0x00, 0x2a, 0xe1, 0xd1, 0x70, 0x47, - 0x80, 0xb5, 0x01, 0x29, 0x04, 0xd0, 0x02, 0x29, 0x08, 0xbf, 0xf2, 0xf7, - 0x8d, 0xf8, 0x01, 0xe0, 0xf2, 0xf7, 0xce, 0xf8, 0x00, 0x20, 0x02, 0xbd, - 0x10, 0xb5, 0x07, 0x4c, 0x02, 0x21, 0x21, 0x60, 0x00, 0x21, 0x61, 0x60, - 0xf2, 0xf7, 0xd9, 0xf8, 0x08, 0x21, 0x60, 0x60, 0x21, 0x60, 0x20, 0x46, - 0xeb, 0xf7, 0xbe, 0xff, 0xfe, 0xe7, 0x00, 0x00, 0x28, 0xf3, 0x00, 0x20, - 0x38, 0xb5, 0x0c, 0x4c, 0x0c, 0x49, 0x20, 0x68, 0xc9, 0x6a, 0x88, 0x42, - 0x34, 0xbf, 0x65, 0x79, 0x25, 0x79, 0x2a, 0x46, 0x7f, 0x21, 0x4f, 0xf4, - 0x9e, 0x60, 0xeb, 0xf7, 0x91, 0xfc, 0x94, 0xf9, 0x06, 0x00, 0x41, 0x19, - 0xc9, 0xb2, 0x4f, 0xf4, 0xe2, 0x60, 0xeb, 0xf7, 0x7f, 0xfc, 0x00, 0x20, - 0x32, 0xbd, 0x00, 0x00, 0x70, 0x29, 0x00, 0x20, 0x78, 0x29, 0x00, 0x20, - 0x49, 0xff, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x00, 0x68, 0x2c, 0x00, 0x20, - 0x00, 0x08, 0x00, 0x00, 0x68, 0x36, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, - 0x68, 0x76, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x68, 0x4e, 0x00, 0x20, - 0x00, 0x06, 0x00, 0x00, 0x68, 0x54, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, - 0x68, 0x5a, 0x00, 0x20, 0x00, 0x06, 0x00, 0x00, 0x68, 0x60, 0x00, 0x20, - 0x00, 0x04, 0x00, 0x00, 0x68, 0x66, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, - 0x68, 0x6a, 0x00, 0x20, 0x00, 0x04, 0x00, 0x00, 0x68, 0x6e, 0x00, 0x20, - 0x00, 0x04, 0x00, 0x00, 0x68, 0x72, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, - 0x68, 0x3e, 0x00, 0x20, 0x00, 0x08, 0x00, 0x00, 0x68, 0x46, 0x00, 0x20, - 0xf0, 0x01, 0x00, 0x00, 0x68, 0x7c, 0x00, 0x20, 0xf0, 0x01, 0x00, 0x00, - 0x58, 0x7e, 0x00, 0x20, 0x70, 0x00, 0x00, 0x00, 0xd8, 0x81, 0x00, 0x20, - 0x70, 0x00, 0x00, 0x00, 0x48, 0x82, 0x00, 0x20, 0x00, 0x02, 0x00, 0x00, - 0x68, 0x78, 0x00, 0x20, 0x90, 0x01, 0x00, 0x00, 0x48, 0x80, 0x00, 0x20, - 0x00, 0x02, 0x00, 0x00, 0x68, 0x7a, 0x00, 0x20, 0x80, 0x36, 0x00, 0x00, - 0x20, 0xbd, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0xcb, 0xb7, 0xfe, 0xff, - 0xc8, 0x00, 0x00, 0x00, 0x72, 0x0c, 0x00, 0x00, 0x00, 0x02, 0x00, 0x20, - 0x59, 0x51, 0xff, 0xff, 0x0c, 0x00, 0x00, 0x00, 0x70, 0x89, 0xfe, 0xff, - 0x90, 0xbc, 0x00, 0x20, 0x84, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, - 0x9c, 0xbc, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, 0x47, - 0x80, 0xb5, 0xec, 0xf7, 0x11, 0xfd, 0xec, 0xf7, 0xe5, 0xfc, 0xbd, 0xe8, - 0x01, 0x40, 0xec, 0xf7, 0x18, 0xbd, 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, 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, - 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, 0x10, 0x25, 0xe0, 0x02, - 0xd4, 0x01, 0xbf, 0x00, 0x63, 0x00, 0x00, 0x05, 0x4b, 0x01, 0xc4, 0x07, - 0x32, 0x01, 0xf8, 0x04, 0x99, 0x00, 0xbc, 0x03, 0x24, 0x00, 0x30, 0x00, - 0x1e, 0x00, 0x17, 0x00, 0xcd, 0x00, 0xc4, 0x01, 0x80, 0x01, 0xc7, 0x00, - 0x69, 0x20, 0x10, 0x0b, 0xb6, 0x02, 0x22, 0x07, 0x56, 0x03, 0xd5, 0x05, - 0x72, 0x02, 0xe5, 0x03, 0x17, 0x20, 0x10, 0x0b, 0x26, 0x00, 0x1d, 0x00, - 0xe3, 0x00, 0xf0, 0x02, 0xc7, 0x01, 0xc1, 0x00, 0x65, 0x20, 0x10, 0x0b, - 0xbf, 0x00, 0x89, 0x07, 0xa8, 0x00, 0x04, 0x05, 0x56, 0x00, 0xe9, 0x03, - 0x27, 0x20, 0xf0, 0x04, 0x0f, 0x1f, 0x00, 0x18, 0x00, 0xcf, 0x00, 0x60, - 0x80, 0x04, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x52, 0xff, 0x01, - 0x30, 0x01, 0x00, 0x00, 0x64, 0x16, 0x50, 0x01, 0xdf, 0xa2, 0x05, 0x1e, - 0x10, 0x01, 0x03, 0x00, 0x0a, 0x0a, 0xf0, 0x31, 0x00, 0xb8, 0x0c, 0xf6, - 0x0d, 0x42, 0x15, 0x4f, 0x1b, 0xf9, 0x24, 0xb1, 0x2d, 0xb7, 0x39, 0xd5, - 0x44, 0xeb, 0x52, 0xfe, 0x5f, 0x8b, 0x6f, 0xe2, 0x7d, 0x14, 0x8e, 0xc9, - 0x9c, 0x9f, 0xac, 0xa8, 0xba, 0x0e, 0xc9, 0x5d, 0xd5, 0x45, 0xe1, 0xde, - 0xea, 0x5f, 0xf3, 0x79, 0xf9, 0xe7, 0xfd, 0xff, 0xff, 0x1f, 0xe0, 0x00, - 0x01, 0x12, 0x03, 0x71, 0x10, 0x0a, 0x0a, 0xd7, 0xa3, 0x3b, 0x00, 0x00, - 0x80, 0x40, 0xac, 0xc5, 0xa7, 0x38, 0x22, 0x20, 0x0f, 0x3f, 0x6f, 0x12, - 0x83, 0x3a, 0x17, 0xb7, 0xd1, 0x38, 0x95, 0xbf, 0xd6, 0x33, 0x0a, 0xd7, - 0x23, 0x3c, 0x04, 0x11, 0x20, 0x20, 0x5f, 0x3f, 0xed, 0xdf, 0x4b, 0x3e, - 0x33, 0x63, 0x94, 0x35, 0xdc, 0x6e, 0xc8, 0x37, 0x5e, 0x72, 0x0b, 0x37, - 0x1a, 0xd6, 0x38, 0x36, 0x46, 0xf6, 0x71, 0x35, 0x0f, 0xde, 0x8e, 0x34, - 0xc7, 0xb4, 0x6f, 0x33, 0x63, 0x2e, 0x2e, 0x31, 0x06, 0xb1, 0xe7, 0x31, - 0x88, 0x5d, 0x01, 0x33, 0xe2, 0x10, 0x70, 0x33, 0x5b, 0xb5, 0xaf, 0x33, - 0x34, 0x9f, 0xe3, 0x33, 0xb3, 0x7c, 0x07, 0x34, 0xdb, 0x33, 0x1d, 0x34, - 0x6c, 0x83, 0x31, 0x34, 0xa5, 0x95, 0x47, 0x34, 0xae, 0xb5, 0x64, 0x34, - 0xb7, 0xff, 0x8a, 0x34, 0x99, 0x7f, 0xc1, 0x34, 0x10, 0x6f, 0x2e, 0x35, - 0xa0, 0xd0, 0x56, 0x36, 0xbd, 0x37, 0x86, 0x35, 0x9e, 0x21, 0x8c, 0x21, - 0xee, 0x12, 0x06, 0x04, 0x12, 0x08, 0x04, 0x20, 0x02, 0xf9, 0x83, 0x01, - 0x3d, 0x04, 0xc1, 0xba, 0x45, 0x10, 0xf4, 0x01, 0x5c, 0xb6, 0x5c, 0x38, - 0x10, 0x21, 0x04, 0xf5, 0x85, 0x10, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0x21, 0x01, 0xb0, 0x05, 0xff, 0x00, 0x07, 0x00, - 0x01, 0x00, 0x00, 0x04, 0x43, 0x90, 0x01, 0x04, 0x43, 0x70, 0x17, 0x04, - 0xc3, 0x32, 0x00, 0x04, 0x52, 0xc8, 0x04, 0x43, 0xe8, 0x03, 0x04, 0xd2, - 0x20, 0x04, 0x2d, 0xf0, 0x05, 0xf2, 0xff, 0x00, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, - 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0xff, 0x01, 0xf1, 0x20, 0x01, - 0xfc, 0x0d, 0x02, 0x01, 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x08, 0x09, - 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x91, 0x16, 0x2d, 0x76, 0x1c, 0x8f, - 0xa0, 0x0f, 0xc8, 0x16, 0x21, 0x04, 0x2d, 0x00, 0x17, 0x12, 0x5e, 0x05, - 0x33, 0x30, 0x75, 0x31, 0x1e, 0x20, 0xa6, 0x1c, 0x2e, 0x20, 0x17, 0x17, - 0xe0, 0x02, 0xff, 0x7f, 0x01, 0x01, 0x43, 0x12, 0x0c, 0x11, 0x80, 0x06, - 0x3f, 0x0c, 0xc8, 0x16, 0xf0, 0x00, 0x00, 0x00, 0x1d, 0x10, 0x0a, 0x3c, - 0x3c, 0xb3, 0x28, 0x00, 0x00, 0x0f, 0xe0, 0x0f, 0xe0, 0x00, 0x80, 0x0e, - 0x13, 0x00, 0xb1, 0x0e, 0x3c, 0x01, 0x2d, 0xe0, 0x2d, 0x94, 0x1b, 0x1c, - 0x01, 0x30, 0x00, 0xb1, 0xed, 0x1a, 0x30, 0x01, 0x31, 0xe0, 0x31, 0x0e, - 0x43, 0x23, 0x00, 0x84, 0x1e, 0x23, 0x56, 0x17, 0x50, 0x0e, 0x03, 0x00, - 0xb4, 0x2c, 0x10, 0x20, 0x0f, 0xaa, 0x0f, 0xaa, 0x00, 0x89, 0xb7, 0x2d, - 0x00, 0x30, 0x0a, 0x40, 0x01, 0x2e, 0x00, 0x24, 0x0a, 0xfd, 0x07, 0x50, - 0x17, 0x40, 0x03, 0x44, 0x00, 0x00, 0x50, 0x40, 0x04, 0x21, 0x0c, 0x12, - 0x58, 0x08, 0x70, 0x02, 0x58, 0x00, 0x00, 0x10, 0x18, 0xb2, 0x80, 0x18, - 0x92, 0x08, 0x0c, 0xf1, 0x46, 0x01, 0xf2, 0x02, 0x80, 0x5a, 0xf1, 0x36, - 0x14, 0x54, 0x06, 0x01, 0x02, 0x07, 0x08, 0x05, 0x06, 0x03, 0x04, 0xd2, - 0x62, 0x10, 0x1a, 0x6d, 0x5c, 0x1e, 0x2c, 0x02, 0xb9, 0x76, 0x01, 0x01, - 0x5c, 0x1e, 0xf1, 0x13, 0xdc, 0x12, 0x04, 0x25, 0x10, 0x03, 0xf0, 0x6d, - 0x01, 0x01, 0xd1, 0x34, 0x17, 0x68, 0x36, 0xe4, 0x42, 0x02, 0x14, 0x2d, - 0xf0, 0x18, 0x56, 0x01, 0xce, 0x21, 0x58, 0x25, 0xa0, 0xf3, 0x19, 0x05, - 0x71, 0x58, 0x22, 0x12, 0x25, 0x10, 0x02, 0x6e, 0x01, 0x01, 0x09, 0x34, - 0x40, 0x04, 0x68, 0x5a, 0x00, 0x20, 0x80, 0x01, 0x58, 0x21, 0x52, 0x22, - 0x02, 0x65, 0x11, 0x01, 0xf1, 0x0b, 0x58, 0xf2, 0x06, 0x01, 0x65, 0x12, - 0x13, 0x18, 0x62, 0x0c, 0x58, 0xc2, 0x60, 0x58, 0x56, 0x03, 0x02, 0x21, - 0x06, 0x21, 0x14, 0xf3, 0x19, 0xc5, 0x73, 0xb0, 0x12, 0x0e, 0x25, 0x12, - 0x18, 0x58, 0x12, 0xd3, 0x34, 0x17, 0x68, 0x66, 0x08, 0x86, 0x01, 0x08, - 0x32, 0x04, 0x0a, 0xf1, 0x0d, 0x58, 0xf1, 0x07, 0xb0, 0x2d, 0x70, 0x03, - 0x62, 0x24, 0x58, 0xc2, 0x6e, 0x58, 0x32, 0x03, 0xfe, 0x41, 0x58, 0x21, - 0x40, 0xf3, 0x19, 0x6d, 0x75, 0xb0, 0x2d, 0x30, 0x1e, 0x12, 0x30, 0x58, - 0x12, 0x71, 0x34, 0x83, 0x68, 0x6a, 0x58, 0x32, 0x90, 0x08, 0xf2, 0x10, - 0x06, 0x58, 0xf1, 0x07, 0xb0, 0x12, 0x07, 0x18, 0x62, 0x40, 0x58, 0xc2, - 0x72, 0x58, 0x32, 0x05, 0x1e, 0x85, 0xb8, 0xf3, 0x19, 0x09, 0x70, 0xb0, - 0x29, 0xa5, 0x12, 0x50, 0x58, 0x12, 0x0d, 0x34, 0xc7, 0x68, 0x4e, 0xb8, - 0xf0, 0x01, 0x10, 0x06, 0x00, 0x08, 0x58, 0xf1, 0x07, 0xb0, 0x12, 0x11, - 0x18, 0x62, 0x60, 0x58, 0xea, 0x54, 0x10, 0x72, 0x09, 0x58, 0x29, 0x72, - 0xfa, 0x1a, 0xfd, 0xc0, 0x21, 0x92, 0x12, 0x70, 0x58, 0x13, 0x01, 0x72, - 0x58, 0x8e, 0x3e, 0x18, 0x03, 0x2d, 0xf8, 0x1b, 0xf0, 0x01, 0x10, 0x04, - 0x00, 0x0a, 0x58, 0xf1, 0x07, 0xb0, 0x21, 0x92, 0x62, 0x80, 0x58, 0xc2, - 0x46, 0x58, 0xb0, 0x01, 0x03, 0x00, 0x0b, 0x58, 0xf3, 0x19, 0x9d, 0x74, - 0xb0, 0x21, 0x92, 0x12, 0x90, 0x58, 0x12, 0xa1, 0x34, 0x17, 0xcc, 0xe2, - 0x08, 0xa2, 0x00, 0xb0, 0xf2, 0x10, 0x0c, 0x58, 0xf1, 0x07, 0xb0, 0x21, - 0x92, 0x62, 0xa4, 0x58, 0xc2, 0xe4, 0x58, 0x70, 0x01, 0x03, 0x00, 0x0d, - 0x58, 0x21, 0x04, 0xf3, 0x19, 0xe5, 0x72, 0xb0, 0x21, 0x92, 0x12, 0xb8, - 0x58, 0x26, 0xe9, 0x08, 0x50, 0x02, 0x7c, 0x00, 0x20, 0x7c, 0x58, 0x32, - 0xc8, 0x08, 0xf2, 0x10, 0x0e, 0x58, 0xf1, 0x07, 0xb0, 0x21, 0x92, 0x52, - 0xcc, 0x58, 0xc3, 0x58, 0x7e, 0x58, 0x70, 0x01, 0x03, 0x00, 0x0f, 0x58, - 0x25, 0x08, 0xf3, 0x19, 0x11, 0x78, 0x58, 0x12, 0x14, 0x18, 0x12, 0xe0, - 0x58, 0x12, 0x15, 0x34, 0x50, 0x03, 0xd8, 0x81, 0x00, 0x20, 0x1c, 0x58, - 0x2d, 0x2c, 0x07, 0x3a, 0x04, 0xde, 0xf1, 0x25, 0x58, 0x12, 0x15, 0x18, - 0x52, 0xf4, 0x58, 0xc3, 0x48, 0x82, 0x58, 0x81, 0x01, 0x23, 0x80, 0xbf, - 0x04, 0x12, 0x29, 0x13, 0x27, 0x40, 0x7f, 0x1c, 0x1e, 0xff, 0x89, 0x07, - 0x1d, 0x54, 0x03, 0x42, 0x01, 0x04, 0x60, 0x02, 0x30, 0xf8, 0x30, 0xf8, - 0x2e, 0x12, 0x4b, 0x02, 0x12, 0x64, 0x02, 0x3d, 0xbc, 0x05, 0x1d, 0x69, - 0x05, 0x12, 0xde, 0x02, 0x6d, 0xc8, 0x05, 0x50, 0x05, 0x58, 0x02, 0x58, - 0x02, 0x01, 0x01, 0xa4, 0x02, 0x21, 0x1a, 0xf1, 0x01, 0x95, 0xa1, 0xa8, - 0x1c, 0x03, 0x15, 0x07, 0x00, 0x02, 0x64, 0x79, 0x06, 0x70, 0x05, 0x10, - 0x27, 0x00, 0x10, 0x0a, 0x00, 0x40, 0x1a, 0x28, 0x02, 0x05, 0x00, 0x5a, - 0x0f, 0x08, 0xbc, 0x05, 0x3f, 0x3e, 0x3f, 0x1e, 0x04, 0x00, 0xfa, 0xaf, - 0x06, 0x1a, 0x01, 0x1a, 0x11, 0x44, 0x23, 0x01, 0x2c, 0x49, 0xf0, 0x01, - 0xff, 0x02, 0x64, 0x00, 0x01, 0xf1, 0x07, 0x01, 0xf5, 0x07, 0xdc, 0x1e, - 0x09, 0xda, 0x03, 0x1e, 0x0b, 0x2e, 0x03, 0xf2, 0x04, 0x13, 0x02, 0x2d, - 0x00, 0x05, 0x1f, 0x01, 0x02, 0x0b, 0x08, 0xf4, 0x09, 0x11, 0x05, 0x0b, - 0x0e, 0x0c, 0x07, 0x08, 0x0a, 0x11, 0x09, 0x0f, 0x10, 0x73, 0x4c, 0x02, - 0x0a, 0x20, 0x0a, 0x20, 0x8a, 0x04, 0x55, 0xf0, 0x29, 0x08, 0x4a, 0x02, - 0xc0, 0x20, 0x01, 0x20, 0x7f, 0x0b, 0x13, 0x80, 0x01, 0x10, 0x00, 0xf0, - 0x84, 0x11, 0x14, 0xd3, 0x00, 0x00, 0x14, 0x40, 0x04, 0x2e, 0x33, 0x33, - 0x2b, 0x28, 0x1c, 0x06, 0xa0, 0x04, 0x2c, 0x2c, 0x37, 0x20, 0x20, 0x11, - 0x12, 0x51, 0x84, 0xf8, 0x06, 0x5a, 0xe1, 0xf5, 0x05, 0x43, 0x44, 0x02, - 0x00, 0x01, 0x06, 0x1e, 0xfc, 0x77, 0x03, 0x21, 0x04, 0x21, 0xe4, 0x2d, - 0x00, 0x06, 0x11, 0xb3, 0xf0, 0x04, 0x26, 0x07, 0x01, 0xf6, 0x01, 0x00, - 0xff, 0x84, 0xa1, 0x50, 0x5e, 0x0e, 0xf8, 0x05, 0xf0, 0x01, 0x1d, 0x01, - 0x00, 0x01, 0xd4, 0x4d, 0xe7, 0x07, 0x5e, 0x47, 0x97, 0x07, 0x5e, 0x48, - 0x47, 0x07, 0x5e, 0x53, 0xf7, 0x06, 0x30, 0x01, 0x54, 0x00, 0x2f, 0x08, - 0x1e, 0x59, 0x17, 0x0b, 0x11, 0x01, 0x63, 0x10, 0x59, 0x5b, 0x21, 0x64, - 0x10, 0x01, 0x01, 0x1e, 0xff, 0x37, 0x11, 0x82, 0x10, 0x16, 0xff, 0xf7, - 0xff, 0x13, 0x00, 0xdc, 0xff, 0x58, 0x00, 0x9d, 0xfe, 0x45, 0x42, 0x9c, - 0xfe, 0x5a, 0x00, 0xd9, 0xff, 0x17, 0x00, 0xf3, 0xff, 0x05, 0x1c, 0x21, - 0x96, 0x20, 0x02, 0xc8, 0x00, 0xb8, 0x0b, 0x50, 0x32, 0x80, 0x99, 0x30, - 0x03, 0x10, 0x00, 0x30, 0x1b, 0x0f, 0x04, 0x1c, 0x04, 0x58, 0x3e, 0x0f, - 0x00, 0xa0, 0xbb, 0x16, 0x05, 0x3c, 0x04, 0x09, 0x11, 0x02, 0x00, 0x20, - 0x02, 0x1a, 0x04, 0x3e, 0x80, 0xcc, 0x03, 0x37, 0x01, 0x00, 0x9a, 0x34, - 0x02, 0x01, 0x00, 0x2f, 0x02, 0xfa, 0x42, 0x01, 0xde, 0x1c, 0x0c, 0xff, - 0x01, 0xff, 0x02, 0x03, 0xff, 0x04, 0xff, 0x05, 0x06, 0xff, 0x07, 0x08, - 0xff, 0x63, 0x0a, 0x2e, 0xff, 0x64, 0x0a, 0x40, 0x28, 0xff, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0xff, 0x1b, 0x1c, - 0x1d, 0xff, 0x1e, 0xff, 0x1f, 0x20, 0xff, 0x21, 0x22, 0x23, 0x24, 0xff, - 0x25, 0x26, 0x27, 0x28, 0xff, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x9d, 0xbd, 0x11, 0xe2, 0x5c, 0x09, 0x0d, 0x1b, 0x2b, 0x34, - 0x37, 0x39, 0x00, 0x00, 0x28, 0x00, 0x3c, 0x20, 0x05, 0x20, 0x05, 0xa0, - 0x0f, 0x11, 0x3c, 0x3c, 0x14, 0x02, 0x01, 0x55, 0x03, 0x3d, 0x26, 0x04, - 0x13, 0x00, 0xf4, 0x06, 0xf8, 0x03, 0x46, 0xff, 0xe6, 0xdb, 0x2e, 0x12, - 0x2a, 0x96, 0x01, 0xb2, 0x12, 0x32, 0x02, 0x2e, 0x20, 0xcb, 0x0c, 0xff, - 0x0c, 0x02, 0x00, 0x9c, 0x23, 0xfd, 0x07, 0x90, 0x03, 0xf1, 0x03, 0x14, - 0xa1, 0x01, 0x03, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xe7, 0x0c, 0x37, 0xfb, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; -unsigned int firmware_Mykonos_M3_bin_len = 98304; diff --git a/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.h b/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.h deleted file mode 100644 index 30215b8..0000000 --- a/df_datalink_ge/src/hardware/mykonos/Mykonos_M3.h +++ /dev/null @@ -1,13 +0,0 @@ -/** -SOFTWARE LICENSE AGREEMENT -20180301-AD937X-CTSLA -**/ - -// Version 5.2.2 -#ifndef SRC_MYKONOS_BIN_H_ -#define SRC_MYKONOS_BIN_H_ - -unsigned char firmware_Mykonos_M3_bin[]; -unsigned int firmware_Mykonos_M3_bin_len; - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/ad9528.c b/df_datalink_ge/src/hardware/mykonos/ad9528.c deleted file mode 100644 index 645acf6..0000000 --- a/df_datalink_ge/src/hardware/mykonos/ad9528.c +++ /dev/null @@ -1,740 +0,0 @@ -/** - * \file ad9528.c - * \brief Contains source code for configuring and initializing AD9528 clock device - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include "ad9528.h" - -/** - * \brief Performs a hard reset on the AD9528 DUT - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the AD9528 data structure containing settings - * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail - */ -ADI_ERR AD9528_resetDevice(ad9528Device_t *device) -{ - /* toggle RESETB on device with matching spi chip select index */ - CMB_hardReset(device->spiSettings->chipSelectIndex); - return ADIERR_OK; -} - -/** - * \brief Sets the AD9528 device SPI settings (3wire/4wire, MSBFirst, etc). - * - * This function will use the settings in the device->spiSettings structure - * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, - * and 3wire/4wire mode. The AD9528 device always uses SPI MODE 0 (CPHA=0, CPOL=0). - * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and - * longInstructionWord =1 to use a 16bit instruction word. - * - * Dependencies - * - writes device->spiSettings->CPHA = 0 - * - writes device->spiSettings->CPOL = 0 - * - writes device->spiSettings->longInstructionWord = 1 - * - * - device->spiSettings->MSBFirst - * - device->spiSettings->enSpiStreaming - * - device->spiSettings->autoIncAddrUp - * - device->spiSettings->fourWireMode - * - * \param device is structure pointer to the AD9528 data structure containing settings - * - * \return Returns enum ADI_ERR, ADIERR_OK=pass, !ADIERR_OK=fail - */ -ADI_ERR AD9528_setSpiSettings(ad9528Device_t *device) -{ - //device->spiSettings->enSpiStreaming - uint8_t spiReg = 0; - - device->spiSettings->CPHA = 0; - device->spiSettings->CPOL = 0; - device->spiSettings->longInstructionWord = 1; - - if (device->spiSettings->MSBFirst == 0) - { - spiReg |= 0x42; /* SPI bit is 1=LSB first */ - } - - if (device->spiSettings->autoIncAddrUp > 0) - { - spiReg |= 0x24; - } - - if (device->spiSettings->fourWireMode > 0) - { - spiReg |= 0x18; - } - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_A, spiReg); - - if (device->spiSettings->enSpiStreaming > 0) - { - /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); - } - else - { - /* Force single instruction mode */ - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x80); - } - - return ADIERR_OK; -} - - -/** - * \brief Helper function for ADI transceiver eval boards to init the AD9528 data structure - * - * This function inits the AD9528 device data structure with defaults that - * are known to work with the ADI AD9369 and AD9371 evaluation boards. NOTE: This function will - * modify the contents of the AD9528 device data structure. - * - * Dependencies - * - spi->chipSelectIndex - * - spi - * - * \param device Pointer to the AD9528 device data structure to initialize - * \param vcxoFrequency_Hz The VCXO frequency that is connected to the AD9528 - * \param refAFrequency_Hz The reference clock frequency being input into the AD9528 REFCLK A input - * \param outputDeviceClock_Hz Desired output clock frequency to the FPGA and transceiver device - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail -*/ -ADI_ERR AD9528_initDeviceDataStruct(ad9528Device_t *device, uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, uint32_t outputDeviceClock_Hz) -{ -// uint16_t chDiv; -// uint8_t i = 0; -// -// uint32_t pll1PfdFreq_Hz = 0; -// uint8_t pll1Ndiv = 0; -// uint8_t validPll1DivSetting = 0; -// uint8_t refAdiv = 1; -// -// -// uint8_t pll2RfDiv = 3; /* Valid values 3,4,5 */ -// uint16_t pll2Ndiv = 1; /* Valid values 1-256 */ -// uint32_t pll2InputFreq_Hz = 0; -// uint64_t pll2VcoFreq_Hz = 0; -// uint16_t pll2NdivStart = 0; -// uint8_t validPll2DivSetting = 0; -// uint64_t chDivU64 = 0; -// -// static const uint64_t PLL2_MIN_VCO_FREQ_HZ = 3450000000ULL; -// static const uint64_t PLL2_MAX_VCO_FREQ_HZ = 4025000000ULL; -// /******************************************************************* -// * PLL1 Settings -// ******************************************************************* -// */ -// -// /* find valid PLL1 Ndiv and REFA div */ -// for (pll1Ndiv = 1; pll1Ndiv < 20; pll1Ndiv++) -// { -// pll1PfdFreq_Hz = vcxoFrequency_Hz / pll1Ndiv; -// -// if ((pll1PfdFreq_Hz <= 110000000) && (pll1PfdFreq_Hz >= 1000000) && -// (pll1PfdFreq_Hz <= refAFrequency_Hz) && -// (refAFrequency_Hz % pll1PfdFreq_Hz == 0) -// ) -// { -// validPll1DivSetting = 1; -// refAdiv = refAFrequency_Hz / pll1PfdFreq_Hz ; -// break; -// } -// } -// -// if (validPll1DivSetting == 0) -// { -// return ADIERR_INV_PARM; -// } -// -// device->pll1Settings->nDivider = pll1Ndiv; //This init function always runs PLL1 at 30.72MHz Pfd rate -// device->pll1Settings->refA_bufferCtrl = DIFFERENTIAL; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL -// device->pll1Settings->refA_Divider = refAdiv; -// device->pll1Settings->refA_Frequency_Hz = refAFrequency_Hz; -// device->pll1Settings->refB_bufferCtrl = DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL -// device->pll1Settings->refB_Divider = 1; -// device->pll1Settings->refB_Frequency_Hz = 0; -// device->pll1Settings->vcxoBufferCtrl = NEG_SINGLE_ENDED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL -// device->pll1Settings->vcxo_Frequency_Hz = vcxoFrequency_Hz; -// -// /******************************************************************* -// * PLL2 Settings -// ******************************************************************* -// */ -// -// /******************************************************************* -// * Output Distribution Settings -// * 9369CE02A uses the following clock outputs -// * OUT 1: FPGA REFCLK -// * OUT 3: FPGA SYSREF -// * OUT 12: DUT SYSREF -// * OUT 13: DUT REFCLK -// ******************************************************************* -// */ -// -// /* PLL 2 input clock can be several different things. Currently hard coded by this init funciton to use -// * PLL 1 output (VCXO Frequency) with no scaling -// */ -// pll2InputFreq_Hz = device->pll1Settings->vcxo_Frequency_Hz; -// validPll2DivSetting = 0; -// -// /* Sweep PLL2 Divider settings to find something that has a valid integer divide (3,4,5)*/ -// for (pll2RfDiv = 3; pll2RfDiv <= 5; pll2RfDiv++) -// { -// -// pll2NdivStart = (PLL2_MIN_VCO_FREQ_HZ / pll2RfDiv / pll2InputFreq_Hz); -// /* find valid PLL2 Ndiv (1-256) */ -// for (pll2Ndiv = pll2NdivStart; pll2Ndiv <= 256; pll2Ndiv++) -// { -// pll2VcoFreq_Hz = (pll2InputFreq_Hz * pll2RfDiv * pll2Ndiv); -// -// if (pll2VcoFreq_Hz < PLL2_MIN_VCO_FREQ_HZ) -// { -// /* Continue to next PLL2 N div */ -// continue; -// } -// else if (pll2VcoFreq_Hz > PLL2_MAX_VCO_FREQ_HZ) -// { -// /* Break to next PLL2 RF div */ -// break; -// } -// -// if (((pll2VcoFreq_Hz / pll2RfDiv) % outputDeviceClock_Hz) == 0) -// { -// -// device->pll2Settings->rfDivider = pll2RfDiv; -// device->pll2Settings->n2Divider = pll2Ndiv; -// device->pll2Settings->totalNdiv = pll2RfDiv * pll2Ndiv; -// chDivU64 = ((pll2VcoFreq_Hz / pll2RfDiv) / outputDeviceClock_Hz); -// -// if ((chDivU64 < 1) || (chDivU64 > 256)) -// { -// return ADIERR_INV_PARM; -// } -// else -// { -// chDiv = (uint16_t)(chDivU64); -// } -// -// validPll2DivSetting = 1; -// break; -// } -// } -// -// if (validPll2DivSetting == 1) -// { -// break; -// } -// } -// -// if (validPll2DivSetting == 0) -// { -// return ADIERR_INV_PARM; -// } -// -// device->outputSettings->outPowerDown = (uint16_t)(~0x300A); //enable outputs 13,12,3 and 1 -// -// for (i=0; i<14; i++){ -// device->outputSettings->outSource[i] = CHANNEL_DIV; //CHANNEL_DIV , PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT -// device->outputSettings->outBufferCtrl[i] = LVDS; //LVDS, LVDS_BOOST, HSTL -// device->outputSettings->outChannelDiv[i] = chDiv; -// device->outputSettings->outFrequency_Hz[i] = outputDeviceClock_Hz; -// device->outputSettings->outAnalogDelay[i] = 0; -// device->outputSettings->outDigitalDelay[i] = 0; -// } -// -// -// device->outputSettings->outSource[3] = SYSREF; -// device->outputSettings->outSource[12] = SYSREF; -// -// -// device->sysrefSettings->sysrefDivide = 512; //SYSREF frequency = VCXO / 2 / sysrefDivde -// device->sysrefSettings->sysrefNshotMode = ONE_PULSE; //ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 -// device->sysrefSettings->sysrefPatternMode = NSHOT; //NSHOT=0, CONTINUOUS=1, PRBS=2, STOP=3 -// device->sysrefSettings->sysrefPinBufferMode = DISABLED; //DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL -// device->sysrefSettings->sysrefPinEdgeMode = LEVEL_ACTIVE_HIGH; //LEVEL_ACTIVE_HIGH=0, LEVEL_ACTIVE_LOW=1, RISING_EDGE=2, FALLING_EDGE=3 -// device->sysrefSettings->sysrefRequestMethod = SPI; //SPI=0,PIN=1 -// device->sysrefSettings->sysrefSource = INTERNAL; //EXTERNAL=0, EXT_RESAMPLED=1, INTERNAL=2 - return ADIERR_OK; -} - -/** - * \brief Debug function to print out summary of AD9528 setup - * - * \param device AD9528 Device data structure describing setup of device. - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail -***********************************************************************************/ -ADI_ERR AD9528_reportClockRates(ad9528Device_t *device) -{ - - return ADIERR_OK; -} //debug function to help verify data structure is setup correctly. - -/** - * \brief Initializes the AD9528 by writing all SPI registers - * - * Initializes the AD9528 for use with the AD9369 transceiver. Designed to work with - * a reference clock of 122.88MHz. Reference clock is expected to be 30.72MHz. - * The output clocks from the AD9528 can run at 122.88M, 153.6M, 184.32M, 245.76M, or 307.2M. - * Typical setup: REFA frequency = 30.72, VCXO = 122.88MHz - * SYNC(SYSREF) pulses output at rate of 120kHz - * - * Dependencies - * - All parameters in device structure - * - * \param device is structure pointer to AD9528 clock device structure - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - */ -ADI_ERR AD9528_initialize(ad9528Device_t *device) { //writes all registers to desired values, leaves clock outputs off, SYSREF output disabled. - uint8_t pll2_Adiv=0; - uint8_t pll2_Bdiv=0; - uint8_t reg108=0; - uint8_t reg109=0; - uint8_t i = 0; - uint8_t j = 0; - uint8_t reg508; - ADI_ERR retval = ADIERR_OK; - - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, ADIERR_OK, "\n// AD9528_initialize\n"); - - //CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_A, 0x18); //[4] and [3] =1 enable 4 wire SPI - //CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_ADI_SPI_CONFIG_B, 0x00); - retval = AD9528_setSpiSettings(device); - if (retval != ADIERR_OK) - { - return retval; - } - - /********************************************************************** - * Configure PLL1 - ********************************************************************** - */ - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_A_DIVIDER_LSB, - device->pll1Settings->refA_Divider & 0xFF); //REF A div[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_A_DIVIDER_MSB, - (device->pll1Settings->refA_Divider >> 8) & 0x03); //REF A div[9:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_B_DIVIDER_LSB, - device->pll1Settings->refB_Divider & 0xFF); //REF B div[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_REF_B_DIVIDER_MSB, - (device->pll1Settings->refB_Divider >> 8) & 0x03); //REF B div[9:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_N_DIV_LSB, - device->pll1Settings->nDivider & 0xFF); //PLL1 N div[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_N_DIV_MSB, - (device->pll1Settings->nDivider >> 8) & 0x03); //PLL1 N div[9:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_CHARGEPUMP, - 0x0A); //PLL1 Charge Pump control 1 - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_CP_CTRL2, - 0x03); //PLL1 Charge Pump control 2 - - switch (device->pll1Settings->refA_bufferCtrl){ - case DISABLED: - reg108 &= ~0x28; - reg109 &= ~0x01; - break; //clear all REFA enable bits - case SINGLE_ENDED: - reg108 |= 0x08; - reg109 &= ~0x01; - break; //Set REFA receiver enable, clear REFA SE negative input enable - case NEG_SINGLE_ENDED: - reg108 |= 0x08; - reg108 &= ~0x10; - reg109 |= 0x01; - break; //Disable REFA diff receiver, enable REFA receiver and use negative REFA input - case DIFFERENTIAL: - reg108 |= 0x28; - reg109 &= ~0x01; - break; - default: - reg108 |= 0x08; - reg109 &= ~0x01; - break; //default to single ended case - } - switch (device->pll1Settings->refB_bufferCtrl){ - case DISABLED: - reg108 &= ~0x50; - reg109 &= ~0x02; - break; //clear all REFB enable bits - case SINGLE_ENDED: - reg108 |= 0x10; - reg109 &= ~0x02; - break; //Set REFB receiver enable, clear REFB SE negative input enable - case NEG_SINGLE_ENDED: - reg108 |= 0x10; - reg108 &= ~0x40; - reg109 |= 0x02; - break; //Disable REFB diff receiver, enable REFB receiver and use negative REFB input - case DIFFERENTIAL: - reg108 |= 0x50; - reg109 &= ~0x02; - break; - default: - reg108 |= 0x10; - reg109 &= ~0x02; - break; //default to single ended case - } - switch (device->pll1Settings->vcxoBufferCtrl){ - case DISABLED: - reg108 &= ~0x03; - reg108 |= 0x04; - break; //power down VCXO input - case SINGLE_ENDED: - reg108 &= ~0x07; - break; //Clear VCXO receiver power down, defaults to Single ended mode - case NEG_SINGLE_ENDED: - reg108 &= ~0x07; - reg108 |= 0x02; - break; //Clear VCXO power down, enable Negative single ended mode[1] - case DIFFERENTIAL: - reg108 &= ~0x07; - reg108 |= 0x01; - break; //Clear VCXO power down, enable differential input buffer[0] - default: - reg108 &= ~0x07; - break; //default to positive single ended case - } - - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS1, - reg108); //Input receiver settings (single ended or differential clock inputs) - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS2, - reg109); //Input receiver settings - - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_INPUT_RECEIVERS3, - 0x0A); //Reference selection mode - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL1_FASTLOCK, - 0x00); //Disable Fast lock - - /********************************************************************** - * Configure PLL2 - ********************************************************************** - */ - pll2_Bdiv = device->pll2Settings->totalNdiv / 4; - pll2_Adiv = device->pll2Settings->totalNdiv % 4; - - if (pll2_Adiv > 3) { //A div valid range (0 to 3) - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 A Divider out of range (0 to 3)\n"); - return ADIERR_INV_PARM; - } - if (pll2_Bdiv < 3 || pll2_Bdiv > 63) { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 B Divider out of range (3 to 63)\n"); - return ADIERR_INV_PARM; - } - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_CHARGEPUMP, - 0xE6); //PLL2 Charge Pump[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_N_DIV, - ((pll2_Adiv & 0x3) << 6) | (pll2_Bdiv & 0x3F)); //PLL2 A and B divider - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_CTRL, 0x03); //PLL2 control - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_VCO_CTRL, 0x01); //Manual VCO CAL - - if (device->pll2Settings->rfDivider < 3 || device->pll2Settings->rfDivider > 5) { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, ADIERR_INV_PARM, "\n// AD9528 PLL2 RF Divider out of range (3,4, or 5)\n"); - return ADIERR_INV_PARM; - } - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_VCO_DIV, - device->pll2Settings->rfDivider); //VCO divider - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_LF_CTRL1, - 0x3A); //PLL2 Loop filter [7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_LF_CTRL2, - 0x00); //PLL2 Loop filter [8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_RDIV, - 0x00); //R divider - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_REPLICA_CHDIV, - (device->pll2Settings->totalNdiv / device->pll2Settings->rfDivider) - -1 ); //Replica channel divider: Ndivider = rfDivider * R divider - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_PLL2_REPLICA_DIV_PHASE, - 0x00); //Replica Channel Divider phase - - /********************************************************************** - * Configure Output Distribution - ********************************************************************** - */ - for (i=0; i<14; i=i+1){ - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CTRL1 + j, - ((device->outputSettings->outSource[i] & 0x7) << 5) | - (device->outputSettings->outAnalogDelay[i] & 0x1F)); - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CTRL2 + j, - ((device->outputSettings->outBufferCtrl[i] & 0x3) << 6) | - (device->outputSettings->outDigitalDelay[i] & 0x3F)); - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_OUT0_CHDIV + j, - device->outputSettings->outChannelDiv[i]-1); - j = j+3; - } - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_OUTPUT_SYNC, 0x00); //Sync outputs - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_MASK_SYNC1, 0x00); //Mask SYNC[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_MASK_SYNC2, 0x00); //Mask SYNC[13:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_EN_OUTPUT_PATH_SEL1, - 0x00); //Bypass SYSREF resample [6:0], bit0:Enable VCXO to feed output distrubution - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_EN_OUTPUT_PATH_SEL2, - 0x00); //Bypass SYSREF resample [13:7] - - /********************************************************************** - * Configure SYSREF operation - ********************************************************************** - */ - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSERF_DIV_LSB, - device->sysrefSettings->sysrefDivide & 0xFF); //SYSREF divider [7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSERF_DIV_MSB, - (device->sysrefSettings->sysrefDivide >> 8) & 0xFF); //SYSREF divider [7:0] - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL3, - ((device->sysrefSettings->sysrefRequestMethod & 0x1) << 7) | - ((device->sysrefSettings->sysrefPinEdgeMode & 0x3) << 5) ); - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, - ((device->sysrefSettings->sysrefSource & 0x03) << 6) | - ((device->sysrefSettings->sysrefPatternMode & 0x3) << 4 ) | - ((device->sysrefSettings->sysrefNshotMode & 0x7) << 1) ); - - if(device->sysrefSettings->sysrefPinBufferMode == DISABLED) - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, - 0x04); //power down input buffer for external SYSREF - } - else if(device->sysrefSettings->sysrefPinBufferMode == SINGLE_ENDED) - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, - 0x00); //enable positive singled ended input - } - else if(device->sysrefSettings->sysrefPinBufferMode == NEG_SINGLE_ENDED) - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, - 0x02); //enable negative singled ended input - } - else if(device->sysrefSettings->sysrefPinBufferMode == DIFFERENTIAL) - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, - 0x01); //enable differential input buffer - } - else - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL5, - 0x04); //power down input buffer for external SYSREF - } - - /********************************************************************** - * Power down control - ********************************************************************** - */ - - if (device->pll1Settings->bypassPll1 > 0) - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_POWERDOWN_CTRL, - 0x14);// power up PLL2 and output distribution, power down PLL1 - } - else - { - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_POWERDOWN_CTRL, - 0x10);// power up PLL1, PLL2 and output distribution - } - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN1, - device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN2, - ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_LDO_ENABLES1, - 0xFF); //LDO enable per output channel [7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_LDO_ENABLES2, - 0xFF); //LDO enable per output channel [15:8] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS0_CTRL, - 0x07); //STATUS 0 outputs REFA present - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS1_CTRL, - 0x01); //STATUS 1 outputs PLL1 and PLL2 locked - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_STATUS_OE, - 0x0C);// Make Status0 and Status1 outputs after reset. - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, - 0x01); //IO update to make all these settings valid in the 9528 - - CMB_setTimeout_ms(1000); - do{ - CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); - if(CMB_hasTimeoutExpired() > 0) - { - return ADIERR_FAILED; - } - }while((reg508 & 0xA2) != 0xA2); - - return ADIERR_OK; -} - -/// Send a SPI message to request a SYSREF pulse or continuous SYSREF from the AD9528. -/*******************************************************************************//** - * Requests a SYSREF from the AD9528. It will use whatever settings for SYSREF - * that are current configured in the AD9528. This could be a single pulse, - * multiple pulses, or continuous pulses. - * Dependencies - * - device->spiSettings - * - device->sysrefSettings->sysrefPatternMode - * - * \param device is structure pointer to AD9528 clock device structure - * \param enableSYSREF If NSHOT SYSREF mode, this parameter is ignored. If PRBS/CONTINUOUS SYSREF mode, 1= enable SYSREF, 0= disable SYSREF. - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - ***********************************************************************************/ -ADI_ERR AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF){ - uint8_t _enableSYSREF=0; - - if (device->sysrefSettings->sysrefPatternMode == NSHOT || enableSYSREF > 0) - { - _enableSYSREF = 1; - } - else - { - _enableSYSREF = 0; - } - - CMB_SPIWriteField(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, _enableSYSREF, 0x01, 0x00); //Set SPI SYSREF request bit - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 - - return ADIERR_OK; -} - -/// Allow changing the 9528 SYSREF frequency and pattern mode(CONTINUOUS, PRBS vs NSHOT mode) -/*******************************************************************************//** - * NOTE: this function will update the device structure with the parameter values passed - * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, - * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. - * - * Dependencies - * - device->spiSettings - * - * \param device is structure pointer to AD9528 clock device structure - * \param divideFromPll1Out Sets the SYSREF pulse frequency. SYSREF frequency = PLL1_VCXO frequency/divideFromPll1Out - * \param sysrefPatternMode Valid settings: NSHOT, CONTINUOUS, PRBS, STOP - * \param nShotPulses Valid settings: ONE_PULSE=0, TWO_PULSES=2, FOUR_PULSES=3, SIX_PULSES=4, EIGHT_PULSES=5 - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - ***********************************************************************************/ -ADI_ERR AD9528_setupSYSREF(ad9528Device_t *device, uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, sysrefNshotMode_t nShotPulses) -{ - uint8_t reg403=0; - - device->sysrefSettings->sysrefPatternMode = sysrefPatternMode; - device->sysrefSettings->sysrefNshotMode = nShotPulses; - device->sysrefSettings->sysrefDivide = divideFromPll1Out >> 1; //SYSREF frequency is (PLL1)VCXO frequency / 2 / device->sysrefSettings->sysrefDivide - - CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, ®403); - - reg403 = reg403 & ~0x01; //clear bit 0 to stop a continuous sysref if it is on. - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, reg403); - - reg403 = reg403 & ~0x3E; //clear bits for pattern mode and Nshot mode bitfields - reg403 = reg403 | ((sysrefPatternMode & 0x3) << 4) | ((nShotPulses & 0x7) << 1); - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_SYSREF_CTRL4, reg403); //update internal sysref pattern mode and Nshot mode (number of pulses) - - //SYSREF request bit x403[0] is left 0. The next call to AD9528_requestSysref will start the SYSREF - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 - - - return ADIERR_OK; -} - -/// Update the AD9528 clock outputs that are enabled. -/*******************************************************************************//** - * NOTE: this function will update the device structure with the parameter values passed - * into this function. The device->sysrefSettings->sysrefPatternMode, device->sysrefSettings->sysrefNshotMode, - * and device->sysrefSettings->sysrefDivide values will be updated in the device structure. - * - * Dependencies - * - device->spiSettings - * - * \param device is structure pointer to AD9528 clock device structure - * \param clkEnable Sets which clock outputs are enabled. Bit per clock output. bit0 = out0, etc. - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - ***********************************************************************************/ -ADI_ERR AD9528_enableClockOutputs(ad9528Device_t *device, uint16_t clkEnable) -{ //clkEnable: bit per clock output - - device->outputSettings->outPowerDown = ~clkEnable; - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN1, device->outputSettings->outPowerDown & 0xFF); //power down out[7:0] - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_CH_POWERDOWN2, ((device->outputSettings->outPowerDown >> 8) & 0x3F)); //power down out[13:8] - - CMB_SPIWriteByte(device->spiSettings, AD9528_ADDR_IO_UPDATE, 0x01); //IO update to make all these settings valid in the 9528 - return ADIERR_OK; -} - -/// Waits for PLL1 and PLL2 to lock and the REFA and VCXO clocks to be present -/*******************************************************************************//** - * Waits until Reference A clock and VCXO clock input to be detected (present), - * and PLL1 and PLL2 to lock. Will timeout after 1 second and return ADIERR_FAILED. - * If clock are detected and PLLs locked, returns ADIERR_OK. - * - * Dependencies - * - device->spiSettings - * - * \param device is structure pointer to AD9528 clock device structure - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - ***********************************************************************************/ -ADI_ERR AD9528_waitForPllLock(ad9528Device_t *device) -{ - uint8_t reg508; - - CMB_setTimeout_ms(1000); - do{ - CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); - if(CMB_hasTimeoutExpired() > 0) - { - return ADIERR_FAILED; - } - }while((reg508 & 0x27) != 0x27); - - return ADIERR_OK; -} - -/// Reads the Lock Status of the PLLs and present detect of the reference clocks -/*******************************************************************************//** - * NOTE: This is a non blocking function that reads a register to see if PLL1 - * and PLL2 are locked and Reference clock A and the VCXO input clock are - * detected (present). If the *status parameter is not NULL, the status will - * be returned. If *status is NULL, the error return value will denote if - * the PllStatus is locked or not with ADIERR_OK or ADIERR_FAILED. - * - * Dependencies - * - device->spiSettings - * - * \param device is structure pointer to AD9528 clock device structure - * - * \return Returns enum ADI_ERR, 0=pass, >0 = fail - ***********************************************************************************/ -ADI_ERR AD9528_readPllStatus(ad9528Device_t *device, uint8_t *status) -{ - uint8_t reg508; - - //bit5 is VCXO clock detected - //bit2 is REFCLK A detected - //bit1 is PLL2 lock detect - //bit0 is PLL1 lock detect - - /* read twice to refresh status bits */ - CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); - CMB_SPIReadByte(device->spiSettings, AD9528_ADDR_STATUS_READBACK0, ®508); - /* if status is a valid pointer, return the PLL status */ - if (status > 0) - { - *status = reg508; - } - - /* PLLs 1 and 2 are locked and VCXO and REFA detected if reg508 has bits 5,2,1 and 0 set */ - if((reg508 & 0x27) == 0x27) - return ADIERR_OK; - else - return ADIERR_FAILED; -} diff --git a/df_datalink_ge/src/hardware/mykonos/ad9528.h b/df_datalink_ge/src/hardware/mykonos/ad9528.h deleted file mode 100644 index b7e6cfe..0000000 --- a/df_datalink_ge/src/hardware/mykonos/ad9528.h +++ /dev/null @@ -1,44 +0,0 @@ -/** - * \file ad9528.h - * \brief Contains function declarations and ad9528Device_t structure typedef for ad9528.c - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _AD9528_LIB_H_ -#define _AD9528_LIB_H_ - -#include -#include "../common.h" -#include "t_ad9528.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#define CLEMENTE_TDD_AD9528_CLKOUT_INDEX 13 - -//Helper function to setup the 9528 device data structure specifically for the ADI transceiver evaluation cards -ADI_ERR AD9528_initDeviceDataStruct(ad9528Device_t *device, uint32_t vcxoFrequency_Hz, uint32_t refAFrequency_Hz, uint32_t outputDeviceClock_Hz); -ADI_ERR AD9528_reportClockRates(ad9528Device_t *device); //debug function to help verify data structure is setup correctly. - -//AD9528 API functions -ADI_ERR AD9528_resetDevice(ad9528Device_t *device); -ADI_ERR AD9528_setSpiSettings(ad9528Device_t *device); -ADI_ERR AD9528_initialize(ad9528Device_t *device); //writes all registers to desired values, leaves clock outputs off. -ADI_ERR AD9528_waitForPllLock(ad9528Device_t *device); -ADI_ERR AD9528_readPllStatus(ad9528Device_t *device, uint8_t *status); -ADI_ERR AD9528_enableClockOutputs(ad9528Device_t *device, uint16_t clkEnable); //clkEnable: bit per clock output -ADI_ERR AD9528_setupSYSREF(ad9528Device_t *device, uint16_t divideFromPll1Out, sysrefPatternMode_t sysrefPatternMode, sysrefNshotMode_t nShotPulses); -ADI_ERR AD9528_requestSysref(ad9528Device_t *device, uint8_t enableSYSREF); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos.c b/df_datalink_ge/src/hardware/mykonos/mykonos.c deleted file mode 100644 index c8db0e3..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos.c +++ /dev/null @@ -1,18444 +0,0 @@ -/** - *\file mykonos.c - * - *\brief Contains Mykonos APIs for transceiver configuration and control - * - * Mykonos API version: 1.5.2.3566 - */ - -/** - * \mainpage Overview - * - * This document is intended for use by software engineering professionals and - * includes detailed information regarding the data types and function calls - * which comprise the Mykonos ANSI C API. - * References to "Mykonos" in the API refer to the Analog Devices development name for the AD9371 family of devices. - * - */ - -/** - * \page Use Suggested Use - * The purpose of this API library is to add abstraction for the low level - * SPI control and calculations necessary to control the Mykonos family of transceiver devices - * - * Add the included source code as required to your baseband processor software build. Please reference the integration document - * as well for further instructions. - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -#include -#include "../common.h" -#include "mykonos.h" -#include "mykonos_gpio.h" -#include "mykonos_macros.h" -#include "mykonos_user.h" - -/* Private helper functions local to this file */ -static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv); -static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz); -static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable); -static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable); - -/** - * \brief Verifies the Tx profile members are valid (in range) in the init structure - * - * If the Tx profile IQ data rate = 0, it is assumed that the Tx profile is - * not used. If Tx IQ data rate > 0, and Tx profile members are out of range, - * - * \pre This function is private and is not called directly by the user. - * - * Dependencies - * - device->tx->txProfile - * - * \param device Structure pointer to Mykonos device data structure - * \param txProfile txProfile settings to be verified - * \param txHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Tx profile - * - * \retval MYKONOS_ERR_TXPROFILE_IQRATE Profile IQ rate out of range - * \retval MYKONOS_ERR_TXPROFILE_RFBW Tx Profile RF bandwidth out of range - * \retval MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION Filter interpolation not valid - * \retval MYKONOS_ERR_TXPROFILE_FIR_INT FIR filter not valid - * \retval MYKONOS_ERR_OK All profile members are valid - */ -static mykonosErr_t mykVerifyTxProfile(mykonosDevice_t *device, mykonosTxProfile_t *txProfile, uint32_t *txHsDigClk_kHz) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - - *txHsDigClk_kHz = 0; - - /********************************/ - /* Check for a valid Tx profile */ - /********************************/ - - if ((txProfile->iqRate_kHz < MIN_TX_IQRATE_KHZ) || (txProfile->iqRate_kHz > MAX_TX_IQRATE_KHZ)) - { - return MYKONOS_ERR_TXPROFILE_IQRATE; - } - - if ((txProfile->rfBandwidth_Hz < MIN_TX_RFBW_HZ) || (txProfile->rfBandwidth_Hz > MAX_TX_RFBW_HZ)) - { - return MYKONOS_ERR_TXPROFILE_RFBW; - } - - if ((txProfile->thb1Interpolation != 1) && (txProfile->thb1Interpolation != 2)) - { - return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; - } - - if ((txProfile->thb2Interpolation != 1) && (txProfile->thb2Interpolation != 2)) - { - return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; - } - - if ((txProfile->txFirInterpolation != 1) && (txProfile->txFirInterpolation != 2) && (txProfile->txFirInterpolation != 4)) - { - return MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION; - } - - if ((txProfile->txFir->coefs == NULL) && (txProfile->txFirInterpolation != 1)) - { - return MYKONOS_ERR_TXPROFILE_FIR_COEFS; - } - - if ((txProfile->dacDiv != DACDIV_2) && (txProfile->dacDiv != DACDIV_2p5) && (txProfile->dacDiv != DACDIV_4)) - { - return MYKONOS_ERR_TXPROFILE_DACDIV; - } - - *txHsDigClk_kHz = (txProfile->iqRate_kHz * txProfile->txFirInterpolation * txProfile->thb1Interpolation * txProfile->thb2Interpolation * (uint32_t)txProfile->dacDiv); - - device->profilesValid |= TX_PROFILE_VALID; - - return retVal; -} - -/** - * \brief Verifies the Rx profile members are valid (in range) and calculates HS Dig Clock require for the Rx Profile - * - * Private helper function to verify the Rx profile members are valid (in range) - * and calculates HS Dig Clock require for the Rx Profile - * If the Rx profile IQ data rate = 0, it is assumed that the Rx profile is - * not used. If Rx IQ data rate > 0, and Rx profile members are out of range. - * - * \pre This function is private and is not called directly by the user. - * - * Dependencies - * - device->rx->rxProfile - * - * \param device Structure pointer to Talise device data structure - * \param rxChannel receiver channel to be checked - * \param rxProfile rxProfile settings to be verified - * \param rxHsDigClk_kHz Return value of the calculated HS Dig Clock required by the Rx profile - * - * \retval MYKONOS_ERR_RXPROFILE_RXCHANNEL Rx channel is not valid. - * \retval MYKONOS_ERR_RXPROFILE_IQRATE out of range IQ rate - * \retval MYKONOS_ERR_RXPROFILE_RFBW out of range RF bandwidth - * \retval MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION not valid filter decimation setting - * \retval MYKONOS_ERR_RXPROFILE_FIR_COEFS FIR filter not valid - * \retval MYKONOS_ERR_RXPROFILE_ADCDIV not valid ADC divider - * \retval MYKONOS_ERR_OK all profile members are valid - */ -static mykonosErr_t mykVerifyRxProfile(mykonosDevice_t *device, mykonosRxProfType_t rxChannel, mykonosRxProfile_t *rxProfile, uint32_t *rxHsDigClk_kHz) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t minBwHz = 0; - uint32_t maxBwHz = 0; - - *rxHsDigClk_kHz = 0; - - switch (rxChannel) - { - case MYK_RX_PROFILE: - minBwHz = MIN_RX_RFBW_HZ; - maxBwHz = MAX_RX_RFBW_HZ; - break; - case MYK_OBS_PROFILE: - minBwHz = MIN_ORX_RFBW_HZ; - maxBwHz = MAX_ORX_RFBW_HZ; - break; - case MYK_SNIFFER_PROFILE: - minBwHz = MIN_SNIFFER_RFBW_HZ; - maxBwHz = MAX_SNIFFER_RFBW_HZ; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXPROFILE_RXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_RXPROFILE_RXCHANNEL)); - return MYKONOS_ERR_RXPROFILE_RXCHANNEL; - } - - /********************************/ - /* Check for a valid Rx profile */ - /********************************/ - if ((rxProfile->iqRate_kHz < MIN_RX_IQRATE_KHZ) || (rxProfile->iqRate_kHz > MAX_RX_IQRATE_KHZ)) - { - return MYKONOS_ERR_RXPROFILE_IQRATE; - } - - /* check for Rx/Obs or Sniffer BW */ - if ((rxProfile->rfBandwidth_Hz < minBwHz) || (rxProfile->rfBandwidth_Hz > maxBwHz)) - { - return MYKONOS_ERR_RXPROFILE_RFBW; - } - - if ((rxProfile->rhb1Decimation != 1) && (rxProfile->rhb1Decimation != 2)) - { - return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; - } - - if ((rxProfile->rxDec5Decimation != 4) && (rxProfile->rxDec5Decimation != 5)) - { - return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; - } - - if ((rxProfile->rxFirDecimation != 1) && (rxProfile->rxFirDecimation != 2) && (rxProfile->rxFirDecimation != 4)) - { - return MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION; - } - - if ((rxProfile->rxFir->coefs == NULL) && (rxProfile->rxFirDecimation != 1)) - { - return MYKONOS_ERR_RXPROFILE_FIR_COEFS; - } - - if ((rxProfile->adcDiv != 1) && (rxProfile->adcDiv != 2)) - { - return MYKONOS_ERR_RXPROFILE_ADCDIV; - } - - *rxHsDigClk_kHz = (rxProfile->iqRate_kHz * rxProfile->rxFirDecimation * rxProfile->rhb1Decimation * rxProfile->rxDec5Decimation * rxProfile->adcDiv); - - switch (rxChannel) - { - case MYK_RX_PROFILE: - device->profilesValid |= RX_PROFILE_VALID; - break; - case MYK_OBS_PROFILE: - device->profilesValid |= ORX_PROFILE_VALID; - break; - /*case MYK_SNIFFER_PROFILE:*/ - default: - device->profilesValid |= SNIFF_PROFILE_VALID; - break; - } - - return retVal; -} - -/** - * \brief Performs a hard reset on the MYKONOS DUT (Toggles RESETB pin on device) - * - * Toggles the Mykonos devices RESETB pin. Only resets the device with - * the SPI chip select indicated in the device->spiSettings structure. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to Mykonos device data structure containing settings - * - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_resetDevice(mykonosDevice_t *device) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDevice()\n"); -#endif - - /* toggle RESETB on device with matching spi chip select index */ - CMB_hardReset(device->spiSettings->chipSelectIndex); - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads back the silicon revision for the Mykonos Device - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to Mykonos device data structure containing settings - * \param revision Return value of the Mykonos silicon revision - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDeviceRev(mykonosDevice_t *device, uint8_t *revision) -{ -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeviceRev()\n"); -#endif - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, revision, 0x07, 0); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads back the Product ID for the Mykonos Device - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to Mykonos device data structure containing settings - * \param productId Return value of the Mykonos product Id - * - * \retval MYKONOS_ERR_GETPRODUCTID__NULL_PARAM recovery action for bad parameter check - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getProductId(mykonosDevice_t *device, uint8_t *productId) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getProductId()\n"); -#endif - - if (productId == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPRODUCTID_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETPRODUCTID_NULL_PARAM)); - return MYKONOS_ERR_GETPRODUCTID_NULL_PARAM; - } - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PRODUCT_ID, productId, 0xF8, 3); - - return retVal; -} - -/** - * \brief Get API version number - * - * This function reads back the version number of the API - * - * \param device Pointer to the Mykonos data structure - * \param siVer A pointer to the current silicon version number. - * \param majorVer A pointer to the current major version number. - * \param minorVer A pointer to the current minor version number. - * \param buildVer A pointer to the current build version number. - * - * \retval MYKONOS_ERR_GET_API_VERSION_NULL_PARAM Null parameter passed to the function. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getApiVersion(mykonosDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getApiVersion()\n"); -#endif - - if ((siVer == NULL) || (majorVer == NULL) || (minorVer == NULL) || (buildVer == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_API_VERSION_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GET_API_VERSION_NULL_PARAM)); - return MYKONOS_ERR_GET_API_VERSION_NULL_PARAM; - } - - *siVer = (uint32_t)MYKONOS_CURRENT_SI_VERSION; - *majorVer = (uint32_t)MYKONOS_CURRENT_MAJOR_VERSION; - *minorVer = (uint32_t)MYKONOS_CURRENT_MINOR_VERSION; - *buildVer = (uint32_t)MYKONOS_CURRENT_BUILD_VERSION; - return retVal; -} - -/** - * \brief Sets the Mykonos device SPI settings (3wire/4wire, MSBFirst, etc). - * - * This function will use the settings in the device->spiSettings structure - * to set SPI stream mode, address auto increment direction, MSBFirst/LSBfirst, - * and 3wire/4wire mode. The Mykonos device always uses SPI MODE 0 (CPHA=0, CPOL=0). - * This function will update your device->spiSettings to set CHPA=0 and CPOL=0 and - * longInstructionWord =1 to use a 16bit instruction word. - * - * Dependencies - * - writes device->spiSettings->CPHA = 0 - * - writes device->spiSettings->CPOL = 0 - * - writes device->spiSettings->longInstructionWord = 1 - * - * - device->spiSettings->MSBFirst - * - device->spiSettings->enSpiStreaming - * - device->spiSettings->autoIncAddrUp - * - device->spiSettings->fourWireMode - * - * \param device Pointer to Mykonos device data structure containing settings - * - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_setSpiSettings(mykonosDevice_t *device) -{ - //device->spiSettings->enSpiStreaming - uint8_t spiReg = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setSpiSettings()\n"); -#endif - - device->spiSettings->CPHA = 0; - device->spiSettings->CPOL = 0; - device->spiSettings->longInstructionWord = 1; - - if (device->spiSettings->MSBFirst == 0) - { - spiReg |= 0x42; /* SPI bit is 1=LSB first */ - } - - if (device->spiSettings->autoIncAddrUp > 0) - { - spiReg |= 0x24; - } - - if (device->spiSettings->fourWireMode > 0) - { - spiReg |= 0x18; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_0, spiReg); - - if (device->spiSettings->enSpiStreaming > 0) - { - /* Allow SPI streaming mode: SPI message ends when chip select deasserts */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x00); - } - else - { - /* Force single instruction mode */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1, 0x80); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Verifies the integrity of the Mykonos device data structure. - * - * The Mykonos device data structure has many pointers to other structures. The - * main purpose of this function to verify that the necessary pointers within the - * device data structure have non zero pointers. The focus is on the Rx/Tx/ObsRx - * profiles and FIR filters where if a channel is disabled, it may be valid for - * some pointers to be NULL. This function updates device->profileValid to remember - * which profile pointers are valid. - * profileValid[3:0] = {SnifferProfileValid, ObsRxProfileValid, RxProfileValid, TxProfileValid}; - * - * Dependencies - * - device (all variables) - * - * \param device Pointer to Mykonos device data structure containing settings - * - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_verifyDeviceDataStructure(mykonosDevice_t *device) -{ - if (device == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER)); - return MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER; - } - - device->profilesValid = 0; /* Reset */ - - if (device->spiSettings == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CHECKDEVSTRUCT_SPI, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SPI)); - return MYKONOS_ERR_CHECKDEVSTRUCT_SPI; - } - - /* place this writeToLog after verifying the spiSettings structure is not NULL */ -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyDeviceDataStructure()\n"); -#endif - - /************************************************************************** - * Check Rx stucture pointers - ************************************************************************** - */ - if (device->rx == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RX)); - return MYKONOS_ERR_CHECKDEVSTRUCT_RX; - } - else - { - if (device->rx->rxChannels == RXOFF) - {/* If no Rx channel enabled, ok to have null pointers for rx gain control, framer, and Rx profile/Rx FIR Filter */ - } - else - { - if ((device->rx->framer == NULL) || (device->rx->rxGainCtrl == NULL) || (device->rx->rxProfile == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB)); - return MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB; - } - - if ((device->rx->rxProfile->rxFir == NULL) && (device->rx->rxProfile->rxFirDecimation != 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR)); - return MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR; - } - } - } - - /************************************************************************** - * Check Tx stucture pointers - ************************************************************************** - */ - if (device->tx == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TX, getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TX)); - return MYKONOS_ERR_CHECKDEVSTRUCT_TX; - } - else - { - if (device->tx->txChannels == TXOFF) - {/* If no Tx channel enabled, ok to have null pointers for deframer, and Tx profile/Tx FIR filter */ - } - else - { - if ((device->tx->deframer == NULL) || (device->tx->txProfile == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB)); - return MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB; - } - - if ((device->tx->txProfile->txFir == NULL) && (device->tx->txProfile->txFirInterpolation != 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR)); - return MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR; - } - } - } - - /************************************************************************** - * Check ObsRx stucture pointers - ************************************************************************** - */ - if (device->obsRx == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX)); - return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX; - } - else - { - if (device->obsRx->obsRxChannelsEnable == MYK_OBS_RXOFF) - {/* If no ObsRx channel enabled, ok to have null pointers for ObsRx gain control, framer, and ObsRx profile/FIR Filter */ - } - else - { - if ((device->obsRx->framer == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER)); - return MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER; - } - - if (device->obsRx->snifferProfile != NULL) - { - if (device->obsRx->snifferGainCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL)); - return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL; - } - - if ((device->obsRx->snifferProfile->rxFir == NULL) && (device->obsRx->snifferProfile->rxFirDecimation != 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR)); - return MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR; - } - } - - if (device->obsRx->orxProfile != NULL) - { - if (device->obsRx->orxGainCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL)); - return MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL; - } - - if ((device->obsRx->orxProfile->rxFir == NULL) && (device->obsRx->orxProfile->rxFirDecimation != 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR, - getMykonosErrorMessage(MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR)); - return MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR; - } - } - } - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Initializes the Mykonos device based on the desired device settings. - * - * This function initializes the mykonos device, setting up the CLKPLL, digital clocks, - * JESD204b settings, FIR Filters, digital filtering. It does not load the ARM - * or perform any of the ARM init calibrations. It also sets the Rx Manual gain indexes and - * TxAttenuation settings to the initial values found in the device data structure. It leaves the - * Mykonos in a state ready for multichip sync (which can bring up the JESD204 links), the - * ARM to be loaded, and the init calibartions run. - * - * Dependencies - * - device (all variables) - * - * \param device Pointer to Mykonos device data structure containing settings - * - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_initialize(mykonosDevice_t *device) -{ - uint8_t txChannelSettings = 0; - uint8_t rxChannelSettings = 0; - uint8_t orxChannelSettings = 0; - uint8_t sniffChannelSettings = 0; - uint8_t adcDacClockRateSelect = 0; - uint8_t enableDpd = 0; - uint8_t obsRxRealIf = 0; - uint8_t enRxHighRejDec5 = 0; - uint8_t rxRealIfData = 0; - uint8_t txSyncb = 0x00; - uint8_t rxSyncb = 0x00; - uint8_t orxSyncb = 0x00; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initialize()\n"); -#endif - - retVal = MYKONOS_verifyDeviceDataStructure(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Verify Rx/Tx and ObsRx profiles are valid combinations */ - retVal = MYKONOS_verifyProfiles(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Set 3 or 4-wire SPI mode, MSBFirst/LSBfirst in device, pushes CPOL=0, CPHA=0, longInstWord=1 into device->spiSettings */ - retVal = MYKONOS_setSpiSettings(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Increase SPI_DO drive strength */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_IO_CONTROL, 0x10); - - /* Enable Reference clock - Set REFCLK pad common mode voltage */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REF_PAD_CONFIG2, 0x07); - - /* Set Mykonos IO pin settings, GPIO direction, enable relevant LVDS pads */ - /* Enable SYSREF LVDS input pad + 100ohm internal termination */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SYSREF_PAD_CONFIG, 0x12); //Enable SYSREF input buffer - - if ((device->tx > 0) && (device->tx->txProfile > 0)) - { - /* Check for LVDS/CMOS mode */ - if (device->tx->deframer->txSyncbMode > 0) - { - txSyncb = 0xF0; - } - else - { - txSyncb = 0x02; - } - - /* Enable SYNCOUTB output buffer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_SYNC_PAD_CONFIG, txSyncb); - } - - /* Look at each framer and enable the RXSYNCB used for each framer. - * It is possible that they use the same RXSYNCB pin */ - if ((device->rx > 0) && (device->rx->framer > 0)) - { - /* Check for LVDS/CMOS mode */ - if (device->rx->framer->rxSyncbMode > 0) - { - rxSyncb = 0x00; - } - else - { - rxSyncb = 0x12; - } - - if (device->rx->framer->obsRxSyncbSelect == 0) - { - /* Enable SYNCINB0 LVDS/CMOS input buffer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, rxSyncb); - } - else - { - /* Enable SYNCINB1 LVDS/CMOS input buffer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, rxSyncb); - } - } - if ((device->obsRx > 0) && (device->obsRx->framer > 0)) - { - /* Check for LVDS/CMOS mode */ - if (device->obsRx->framer->rxSyncbMode > 0) - { - orxSyncb = 0x00; - } - else - { - orxSyncb = 0x12; - } - - if (device->obsRx->framer->obsRxSyncbSelect == 0) - { - /* Check for rxSyncb and orxSyncb when using the same RXSYNCB */ - if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 0)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE)); - return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE; - } - - /* Enable SYNCINB0 LVDS input buffer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_SYNC_CONFIG, orxSyncb); - } - else - { - /* Check for rxSyncb and orxSyncb when using the same ORXSYNCB */ - if ((orxSyncb != rxSyncb) && (device->rx->framer->obsRxSyncbSelect == 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE)); - return MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE; - } - - /* Enable SYNCINB1 LVDS input buffer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_SYNC_CONFIG, orxSyncb); - } - } - - /* Set number of device clock cycles per microsecond [round(freq/2) - 1] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_REFERENCE_CLOCK_CYCLES, (uint8_t)((((device->clocks->deviceClock_kHz / 1000) + 1) >> 1) - 1)); - - /* Set profile specific digital clock dividers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 0x04); /* Negate Rx2 so phase matches Rx1 */ - - if (device->profilesValid & TX_PROFILE_VALID) - { - txChannelSettings = (((uint8_t)device->tx->txChannels & 0x3) << 6); - switch (device->tx->txProfile->thb2Interpolation) - { - case 1: - break; /* keep bit as 0 in bitfield */ - case 2: - txChannelSettings |= 0x20; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION)); - return MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION; - } - - switch (device->tx->txProfile->thb1Interpolation) - { - case 1: - break; /* keep bit as 0 in bitfield */ - case 2: - txChannelSettings |= 0x10; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION)); - return MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION; - } - - if (device->tx->txProfile->txFir == NULL) - { - /* If invalid pointer to FIR filter, Bypass programmable FIR, keep txChannelSettings[1:0] == 0 */ - } - else - { - switch (device->tx->txProfile->txFirInterpolation) - { - case 1: - txChannelSettings |= 0x01; - break; - case 2: - txChannelSettings |= 0x02; - break; - case 4: - txChannelSettings |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION)); - return MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION; - } - } - - switch (device->tx->txProfile->dacDiv) - { - case DACDIV_2: - break; /* Keep bit [1]=0 */ - case DACDIV_2p5: - break; /* Keep bit [1]=0, div 2.5 is set when Rx DEC5 filter enabled*/ - case DACDIV_4: - adcDacClockRateSelect |= 2; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_DACDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_DACDIV)); - return MYKONOS_ERR_INIT_INV_DACDIV; - } - } - - if (device->profilesValid & RX_PROFILE_VALID) - { - rxChannelSettings = (((uint8_t)device->rx->rxChannels & 0x3) << 6); - switch (device->rx->rxProfile->rxDec5Decimation) - { - case 4: - break; /* keep bit as 0 in bitfield */ - case 5: - rxChannelSettings |= 0x04; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); - return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; - } - - switch (device->rx->rxProfile->rhb1Decimation) - { - case 1: - break; /* keep bit as 0 in bitfield */ - case 2: - rxChannelSettings |= 0x10; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION)); - return MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION; - } - - if (device->rx->rxProfile->rxFir == NULL) - { - /* If invalid pointer to FIR filter, Bypass programmable FIR, keep rxChannelSettings[1:0] == 0 */ - } - else - { - switch (device->rx->rxProfile->rxFirDecimation) - { - case 1: - rxChannelSettings |= 0x01; - break; - case 2: - rxChannelSettings |= 0x02; - break; - case 4: - rxChannelSettings |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION)); - return MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION; - } - } - - switch (device->rx->rxProfile->adcDiv) - { - case 1: - adcDacClockRateSelect |= 0; - break; - case 2: - adcDacClockRateSelect |= 1; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); - return MYKONOS_ERR_INIT_INV_ADCDIV; - } - - rxRealIfData = (device->rx->realIfData > 0) ? 1 : 0; - enRxHighRejDec5 = (device->rx->rxProfile->enHighRejDec5 > 0) ? 1 : 0; - } - else if (device->profilesValid & ORX_PROFILE_VALID) - { - /* if Rx profile not valid, but ORX profile valid, set RX ADC divider and dec5 to match orx profile setting */ - /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */ - switch (device->obsRx->orxProfile->rxDec5Decimation) - { - case 4: - break; /* keep bit as 0 in bitfield */ - case 5: - rxChannelSettings |= 0x04; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); - return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; - } - - switch (device->obsRx->orxProfile->adcDiv) - { - case 1: - adcDacClockRateSelect |= 0; - break; - case 2: - adcDacClockRateSelect |= 1; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); - return MYKONOS_ERR_INIT_INV_ADCDIV; - } - } - else if (device->profilesValid & SNIFF_PROFILE_VALID) - { - /* if Rx profile not valid, and ORX profile not valid, set RX ADC divider and dec5 to match sniffer profile setting */ - /* ARM clock is derived from Rx clocking, so Rx ADC div needs to be set */ - switch (device->obsRx->snifferProfile->rxDec5Decimation) - { - case 4: - break; /* keep bit as 0 in bitfield */ - case 5: - rxChannelSettings |= 0x04; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION)); - return MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION; - } - - switch (device->obsRx->snifferProfile->adcDiv) - { - case 1: - adcDacClockRateSelect |= 0; - break; - case 2: - adcDacClockRateSelect |= 1; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ADCDIV, getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ADCDIV)); - return MYKONOS_ERR_INIT_INV_ADCDIV; - } - } - - /* determine ObsRx ADC Div setting */ - if (device->profilesValid & ORX_PROFILE_VALID) - { - switch (device->obsRx->orxProfile->adcDiv) - { - case 1: - break; /* Keep bit[4]=0 */ - case 2: - adcDacClockRateSelect |= 0x10; - break; /* Set bit[4]=1 */ - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); - return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; - } - } - else if (device->profilesValid & SNIFF_PROFILE_VALID) - { - switch (device->obsRx->snifferProfile->adcDiv) - { - case 1: - break; /* Keep bit[4]=0 */ - case 2: - adcDacClockRateSelect |= 0x10; - break; /* Set bit[4]=1 */ - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); - return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; - } - } - else if (device->profilesValid & RX_PROFILE_VALID) - { /* if OBSRX profiles are not valid, set obsRx ADC div to match Rx ADC divider */ - switch (device->rx->rxProfile->adcDiv) - { - case 1: - break; /* Keep bit[4]=0 */ - case 2: - adcDacClockRateSelect |= 0x10; - break; /* Set bit[4]=1 */ - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV)); - return MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV; - } - } - - /* Determine ORx and Sniffer channel settings */ - if (device->obsRx != NULL) - { - /* verify pointers in data structure are valid (non-zero) */ - if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) - { - if (device->obsRx->realIfData > 0) - { - obsRxRealIf = 1; - } - } - - /* TODO: verify that the decimation matches the given IQ rate in the data structure */ - - /* Set Sniffer profile (digital filter enables) if sniffer profile enabled (valid pointer) */ - if (device->profilesValid & SNIFF_PROFILE_VALID) - { - sniffChannelSettings = 0; - switch (device->obsRx->snifferProfile->rhb1Decimation) - { - case 1: - break; - case 2: - sniffChannelSettings |= 0x10; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RHB1, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RHB1)); - return MYKONOS_ERR_INIT_INV_SNIFFER_RHB1; - } - - if (device->obsRx->snifferProfile->rxFir != NULL) - { - - switch (device->obsRx->snifferProfile->rxFirDecimation) - { - case 1: - sniffChannelSettings |= 0x01; - break; - case 2: - sniffChannelSettings |= 0x02; - break; - case 4: - sniffChannelSettings |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC)); - return MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC; - } - } - } - - /* Set ORx profile (digital filter enables) if ORx profile enabled (valid pointer) */ - if (device->profilesValid & ORX_PROFILE_VALID) - { - orxChannelSettings = 0; - switch (device->obsRx->orxProfile->rhb1Decimation) - { - case 1: - break; - case 2: - orxChannelSettings |= 0x10; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RHB1, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RHB1)); - return MYKONOS_ERR_INIT_INV_ORX_RHB1; - } - - if (device->obsRx->orxProfile->rxFir != NULL) - {/* if pointer to orx rxFIR is valid */ - - switch (device->obsRx->orxProfile->rxFirDecimation) - { - case 1: - orxChannelSettings |= 0x01; - break; - case 2: - orxChannelSettings |= 0x02; - break; - case 4: - orxChannelSettings |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC)); - return MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC; - } - } - } - } - - /************************************************************************ - * Set channel config settings for Rx/Tx/oRx and Sniffer channels - *********************************************************************** - */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_2, txChannelSettings); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_4, rxChannelSettings); - - /* Set option to use new high rejection DEC5 filters in main Rx1/Rx2 path. */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_5, ((uint8_t)(rxRealIfData << 2) | (enRxHighRejDec5 ? 3 : 0))); - - if (rxRealIfData > 0) - { - /* Set Rx1 NCO frequency */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_3, 0x40); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_2, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_1, 0x01); - - /* Set Rx2 NCO frequency */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_3, 0x40); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_2, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_1, 0x01); - - /* Enable NCO for Rx1 and Rx2 to shift data from zero IF to real IF */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_NCO_CONTROL, 3, 0x03, 0); - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_2, obsRxRealIf, 0x40, 6); - - /* if sniffer profile disabled, Sniffer config reg is set to default = 0x80 */ - sniffChannelSettings |= 0x80; /* use PFIR coef set B = bit[7]=1*/ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFFER_CONFIGURATION_CONTROL, sniffChannelSettings); - - /* if orx profile not valid, SPI reg for orx config is set to default = 0x00 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_CONFIGURATION_CONTROL, orxChannelSettings); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_LOOPBACK_CONFIGURATION_CONTROL, orxChannelSettings); - - /* Set ADC divider, DAC divider, and ObsRx/sniffer dividers */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, adcDacClockRateSelect, 0x13, 0); - - /* Disable ORx digital DC offset - bad default SPI setting for ObsRx DC offset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT, 0x60); - - /* Necessary write for ARM init cals to work */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNIFF_RXLOGEN_BYTE1, 0x0E); - - /* Increase Sniffer LNA gain */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SNRX_LNA_BIAS_C, 0x0F); - - /* Set the CLKPLL with the frequency from the device data structure */ - retVal = MYKONOS_initDigitalClocks(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Wait for CLKPLL CP Cal done and CLKPLL Lock or throw error message */ - CMB_wait_ms(500); - retVal = MYKONOS_waitForEvent(device, CLKPLLCP, 1000000); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_waitForEvent(device, CLKPLL_LOCK, 1000000); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Enable digital clocks - this is gated by the CLKPLL being locked */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x14); - - /* Set the Tx PFIR synchronization clock */ - retVal = MYKONOS_setTxPfirSyncClk(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Set the Rx PFIR synchronization clock */ - retVal = MYKONOS_setRxPfirSyncClk(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (device->profilesValid & TX_PROFILE_VALID) - { - /* Set pre TxPFIR Half band filter interpolation */ - if (device->tx->txProfile->txInputHbInterpolation == 1) - { - /* disable TX input half band ([3:2]=00) - but allow DPD to still be enabled for tx profiles with wide BW [1] */ - enableDpd = (device->tx->txProfile->enableDpdDataPath > 0) ? 1 : 0; - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, enableDpd, 0x0E, 1); - } - else if (device->tx->txProfile->txInputHbInterpolation == 2) - { - if (device->tx->txProfile->iqRate_kHz > 160000) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE)); - return MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE; - } - - /* enable TX input half band[2]=1, and Enable DPD[1]=1*/ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 3, 0x0E, 1); - } - else if (device->tx->txProfile->txInputHbInterpolation == 4) - { - if (device->tx->txProfile->iqRate_kHz > 80000) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE)); - return MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE; - } - - /* enable TX input HB0[3]=1 and Tx input HB[2]=1, and Enable DPD[1]=1*/ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, 7, 0x0E, 1); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM)); - return MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM; - } - - /* Enable SPI Tx Atten mode */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x03, 0); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x01, 0x0C, 2); - - /* Set Tx1 Atten step size */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, device->tx->txAttenStepSize, 0x60, 5); - - /* Set Tx2 Atten step size */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, device->tx->txAttenStepSize, 0x60, 5); - } - else - { - /* Power down DACs */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERIDE_7_0, 3, 0x0C, 2); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_PD_OVERRIDE_CONTROL_7_0, 3, 0x0C, 2); - } - - /* Set RxFE LO Common mode */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE1_LOCM, 0xF0); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXFE2_LOCM, 0xF0); - - /* Set Rxloopback LO Common mode */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK1_CNTRL_1, 0xFF); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RXLOOPBACK2_CNTRL_1, 0xFF); - - /* Setup MGC or AGC Rx gain control */ - if ((retVal = MYKONOS_setupRxAgc(device)) != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Default Rx to use manual gain control until AGC enabled by user */ - if ((retVal = MYKONOS_setRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK) - { - return retVal; - } - - - if ((retVal = MYKONOS_setupObsRxAgc(device)) != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Default ObsRx to use manual gain control until AGC enabled by user */ - if ((retVal = MYKONOS_setObsRxGainControlMode(device, MGC)) != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Disable GPIO select bits by setting to b11 */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, 3, 0x30, 4); - - /* Extra settings for ARM calibrations */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT, 0x11); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK1_CNTRL_4, 0x04); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_LOOPBACK2_CNTRL_4, 0x04); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, 0x20, 0x20, 0); - - /* Extra settings for ADC initialisation */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_DELAY, 0x28); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_ADC_FLASH_CTRL, 0x0E); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_DELAY, 0x28); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_ADC_FLASH_CTRL, 0x0E); - - /* Move to Alert ENSM state */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ENSM_CONFIG_7_0, 0x05); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Verifies the init structure profiles are valid combinations - * - * This function checks that the Rx/Tx/ORx/Sniffer profiles have valid clock rates in - * order to operate together. Rx/Tx and ORx/Sniffer share a common high speed digital - * clock. If an invalid combination of profiles is detected, an error will be - * returned. If a profile in the init structure is unused, the user should zero - * out all members of that particular profile structure. If a Rx/Tx/ORx/Sniffer profile - * has an IQ rate = 0, it is assumed that the profile is disabled. - * - * \pre This function is private and is not called directly by the user. - * - * This function uses mykVerifyTxProfile() and mykVerifyRxProfile() as helper functions. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Structure pointer to Mykonos device data structure - * - * \retval MYKONOS_ERR_PROFILES_HSDIGCLK profiles loaded are not valid - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_verifyProfiles(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - - uint32_t rxHsDigClk_kHz = 0; - uint32_t orxHsDigClk_kHz = 0; - uint32_t snifferHsDigClk_kHz = 0; - uint32_t txHsDigClk_kHz = 0; - - mykonosRxProfile_t *rxProfile = NULL; - mykonosTxProfile_t *txProfile = NULL; - mykonosRxProfile_t *orxProfile = NULL; - mykonosRxProfile_t *snifferProfile = NULL; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyProfiles()\n"); -#endif - - device->profilesValid = 0; - - /* Check all loaded profiles */ - if (device->tx->txChannels != TXOFF) - { - txProfile = device->tx->txProfile; - retVal = mykVerifyTxProfile(device, txProfile, &txHsDigClk_kHz); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if (device->rx->rxChannels != RXOFF) - { - rxProfile = device->rx->rxProfile; - retVal = mykVerifyRxProfile(device, MYK_RX_PROFILE, rxProfile, &rxHsDigClk_kHz); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if (device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF) - { - if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_ORX1_ORX2) - { - orxProfile = device->obsRx->orxProfile; - retVal = mykVerifyRxProfile(device, MYK_OBS_PROFILE, orxProfile, &orxHsDigClk_kHz); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if ((uint32_t)device->obsRx->obsRxChannelsEnable & (uint32_t)MYK_SNRXA_B_C) - { - snifferProfile = device->obsRx->snifferProfile; - retVal = mykVerifyRxProfile(device, MYK_SNIFFER_PROFILE, snifferProfile, &snifferHsDigClk_kHz); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - } - - return retVal; -} - -/** - * \brief Write indirect registers (Programmable FIRs, Rx gain tables, JESD204B settings). Must be done after Multi Chip Sync - * - * The BBP should never need to call this function. It is called automatically by the initArm function. - * This function is a continuation of the MYKONOS_initialize() function. This part of initialization must be done after - * the BBP has completed Multi chip Sync. These registers include FIR filters, Rx gain tables, and JESD204B framer/deframer - * config registers. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * an error. - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_initSubRegisterTables(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - - /* ------------------------------------------------------------------------------------------- */ - /* Program submap register tables after digital clocks are up and running and Multi Chip Sync */ - /* has been completed by BBP */ - if (device->profilesValid & TX_PROFILE_VALID) - { - if (device->tx->txProfile->txFir != NULL) - { - retVal = MYKONOS_programFir(device, TX1TX2_FIR, device->tx->txProfile->txFir); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - } - - if (device->profilesValid & RX_PROFILE_VALID) - { - if (device->rx->rxProfile->rxFir != NULL) - { - retVal = MYKONOS_programFir(device, RX1RX2_FIR, device->rx->rxProfile->rxFir); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Load Rx gain table */ - retVal = MYKONOS_programRxGainTable(device, &RxGainTable[0][0], (sizeof(RxGainTable) >> 2), RX1_RX2_GT); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setRx1ManualGain(device, device->rx->rxGainCtrl->rx1GainIndex); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setRx2ManualGain(device, device->rx->rxGainCtrl->rx2GainIndex); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Enable Digital gain for Rx and ObsRx gain tables */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DIGITAL_GAIN_CONFIG, 0x80); - } - } - - if (device->profilesValid & SNIFF_PROFILE_VALID) - { - if (device->obsRx->snifferProfile->rxFir != NULL) - { - retVal = MYKONOS_programFir(device, OBSRX_B_FIR, device->obsRx->snifferProfile->rxFir); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Load Sniffer Rx gain table */ - retVal = MYKONOS_programRxGainTable(device, &SnRxGainTable[0][0], (sizeof(SnRxGainTable) >> 2), SNRX_GT); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setObsRxManualGain(device, OBS_SNIFFER_A, device->obsRx->snifferGainCtrl->gainIndex); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - } - - if (device->profilesValid & ORX_PROFILE_VALID) - { - if (device->obsRx->orxProfile->rxFir != NULL) - {/* if pointer to orx rxFIR is valid */ - retVal = MYKONOS_programFir(device, OBSRX_A_FIR, device->obsRx->orxProfile->rxFir); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Load ORx gain table */ - retVal = MYKONOS_programRxGainTable(device, &ORxGainTable[0][0], (sizeof(ORxGainTable) >> 2), ORX_GT); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setObsRxManualGain(device, OBS_RX1_TXLO, device->obsRx->orxGainCtrl->orx1GainIndex); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setObsRxManualGain(device, OBS_RX2_TXLO, device->obsRx->orxGainCtrl->orx2GainIndex); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - } - - /* Load Loopback Gain Table for ARM calibrations */ - { - uint8_t loopBackGainTable[6][4] = { - /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ - {0, 0, 0, 0}, /* Gain index 255 */ - {7, 0, 0, 0}, /* Gain index 254 */ - {13, 0, 1, 1}, /* Gain index 253 */ - {18, 0, 3, 1}, /* Gain index 252 */ - {23, 0, 3, 1}, /* Gain index 251 */ - {28, 0, 0, 0} /* Gain index 250 */ - }; - retVal = MYKONOS_programRxGainTable(device, &loopBackGainTable[0][0], (sizeof(loopBackGainTable) >> 2), LOOPBACK_GT); - } - - /* Enable Digital gain for ORx/Sniffer/Loopback gain table */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_DIGITAL_GAIN_CONFIG, 0x80); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RCAL_CONTROL, 0x07);/* Set RCAL code to nominal */ - - /* If Valid Rx Profile or valid ObsRx profile, setup serializers */ - if ((device->profilesValid & RX_PROFILE_VALID) || (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) - { - retVal = MYKONOS_setupSerializers(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if ((device->rx->rxChannels != RXOFF) && (device->profilesValid & RX_PROFILE_VALID)) - { - retVal = MYKONOS_setupJesd204bFramer(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if ((device->obsRx->obsRxChannelsEnable != MYK_OBS_RXOFF) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) - { - retVal = MYKONOS_setupJesd204bObsRxFramer(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - if ((device->tx->txChannels != TXOFF) && (device->profilesValid & TX_PROFILE_VALID)) - { - retVal = MYKONOS_setupDeserializers(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setupJesd204bDeframer(device); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setTx1Attenuation(device, device->tx->tx1Atten_mdB); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_setTx2Attenuation(device, device->tx->tx2Atten_mdB); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs a blocking wait for a Mykonos calibration or Pll Lock - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param waitEvent the enum value of the event to wait for - * \param timeout_us If timeout_us time has passed, function will return with - * an error. - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent, uint32_t timeout_us) -{ - uint16_t spiAddr = 0; - uint8_t spiBit = 0; - uint8_t doneBitLevel = 0; - uint8_t data = 0; - mykonosErr_t errCode = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitForEvent()\n"); -#endif - - switch (waitEvent) - { - case CALPLL_LOCK:/* wait for x17F[7]=1 */ - spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL; - spiBit = 7; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK; - break; - case CLKPLLCP: /* wait for x154[5]=1 */ - spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP; - break; - case CLKPLL_LOCK: /* wait for x157[0]=1 */ - spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK; - break; - case RF_RXPLLCP:/* wait for x254[5]=1 */ - spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP; - break; - case RF_RXPLL_LOCK: /* wait for x257[0]=1 */ - spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK; - break; - case RF_TXPLLCP: /* wait for x2C4[5]=1 */ - spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP; - break; - case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */ - spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK; - break; - case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */ - spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP; - break; - case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */ - spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK; - break; - case RXBBF_CALDONE: /* wait for x1B2[5]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 5; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE; - break; - case TXBBF_CALDONE:/* wait for x1B2[0]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 0; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE; - break; - case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 1; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE; - break; - case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 7; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE; - break; - case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */ - spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL; - spiBit = 5; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE; - break; - case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */ - spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL; - spiBit = 5; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE; - break; - case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */ - spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL; - spiBit = 5; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE; - break; - case RCAL_CALDONE: /* wait for x1B2[6]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 6; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE; - break; - case ARMBUSY:/* wait for xD30[7]=0 */ - spiAddr = MYKONOS_ADDR_ARM_CMD; - spiBit = 7; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY; - break; - case INITARM_DONE: - spiAddr = MYKONOS_ADDR_ARM_CMD; - spiBit = 7; - doneBitLevel = 0; - errCode = MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM)); - return MYKONOS_ERR_WAITFOREVENT_INV_PARM; - } - - CMB_setTimeout_us(timeout_us); /* timeout after desired time */ - - do - { - CMB_SPIReadByte(device->spiSettings, spiAddr, &data); - - /* For SW verification tests, allow API to think all cals are complete*/ -#ifdef MYK_CALS_DONE_SWDEBUG - if (doneBitLevel == 0) - { - data = 0x00; - } - else - { - data = 0xFF; - } -#endif - - if ((uint32_t)CMB_hasTimeoutExpired() > 0) - { - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, errCode, getMykonosErrorMessage(errCode)); - return errCode; - } - } while (((data >> spiBit) & 0x01) != doneBitLevel); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs a readback with no wait for a Mykonos calibration or Pll Lock - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param waitEvent the enum value of the event to wait for - * \param eventDone Return value: 1= calibration event is complete. 0 = Event is still pending - * \return Returns enum mykonosErr_t, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_readEventStatus(mykonosDevice_t *device, waitEvent_t waitEvent, uint8_t *eventDone) -{ - uint16_t spiAddr = 0; - uint8_t data = 0; - uint8_t spiBit = 0; - uint8_t doneBitLevel = 0; - - switch (waitEvent) - { - case CALPLL_LOCK:/* wait for x17F[7]=1 */ - spiAddr = MYKONOS_ADDR_CALPLL_SDM_CONTROL; - spiBit = 7; - doneBitLevel = 1; - break; - case CLKPLLCP: /* wait for x154[5]=1 */ - spiAddr = MYKONOS_ADDR_CLK_SYNTH_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - break; - case CLKPLL_LOCK: /* wait for x157[0]=1 */ - spiAddr = MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - break; - case RF_RXPLLCP:/* wait for x254[5]=1 */ - spiAddr = MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - break; - case RF_RXPLL_LOCK: /* wait for x257[0]=1 */ - spiAddr = MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - break; - case RF_TXPLLCP: /* wait for x2C4[5]=1 */ - spiAddr = MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - break; - case RF_TXPLL_LOCK: /* wait for x2C7[0]=1 */ - spiAddr = MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - break; - case RF_SNIFFERPLLCP: /* wait for x354[7]=1 */ - spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT; - spiBit = 5; - doneBitLevel = 1; - break; - case RF_SNIFFERPLL_LOCK: /* wait for x357[0]=1 */ - spiAddr = MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1; - spiBit = 0; - doneBitLevel = 1; - break; - case RXBBF_CALDONE: /* wait for x1B2[5]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 5; - doneBitLevel = 0; - break; - case TXBBF_CALDONE:/* wait for x1B2[0]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 0; - doneBitLevel = 0; - break; - case RX_RFDC_CALDONE: /* wait for x1B2[1]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 1; - doneBitLevel = 0; - break; - case RX_ADCTUNER_CALDONE:/* wait for x1B2[7]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 7; - doneBitLevel = 0; - break; - case RX1_ADCPROFILE:/* wait for x5DD[5]=0 */ - spiAddr = MYKONOS_ADDR_RX_ADC1_PRFL; - spiBit = 5; - doneBitLevel = 0; - break; - case RX2_ADCPROFILE:/* wait for x5DE[5]=0 */ - spiAddr = MYKONOS_ADDR_RX_ADC2_PRFL; - spiBit = 5; - doneBitLevel = 0; - break; - case ORX_ADCPROFILE:/* wait for x5DF[5]=0 */ - spiAddr = MYKONOS_ADDR_ORX_ADC_PRFL; - spiBit = 5; - doneBitLevel = 0; - break; - case RCAL_CALDONE: /* wait for x1B2[6]=0 */ - spiAddr = MYKONOS_ADDR_CALIBRATION_CONTROL; - spiBit = 6; - doneBitLevel = 0; - break; - case ARMBUSY:/* wait for xD30[7]=0 */ - spiAddr = MYKONOS_ADDR_ARM_CMD; - spiBit = 7; - doneBitLevel = 0; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITFOREVENT_INV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_WAITFOREVENT_INV_PARM)); - return MYKONOS_ERR_WAITFOREVENT_INV_PARM; - } - - CMB_SPIReadByte(device->spiSettings, spiAddr, &data); - - if (doneBitLevel) - { - *eventDone = (data >> spiBit) & 0x01; - } - else - { - *eventDone = (~(data >> spiBit) & 0x01); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the CLKPLL output frequency. - * - * This code updates the Synth and Loop filter settings based on a VCO - * frequency LUT. The VCO frequency break points for the Synth LUT can be - * found in an array called vcoFreqArrayMhz. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - device->deviceClock_kHz - * - device->rxSettings->rxProfile->vcoFreq_kHz - * - device->rxSettings->rxProfile->clkPllHsDiv - * - device->rxSettings->rxProfile->clkPllVcoDiv - * - * \param device is structure pointer to the MYKONOS data structure containing settings - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_initDigitalClocks(mykonosDevice_t *device) -{ - /* RF Synth variables */ - /* pull Synth and Loop filter values from a Look Up Table */ - uint8_t vcoOutLvl; - uint8_t vcoVaractor; /* [3:0] */ - uint8_t vcoBiasRef; /* [2:0] */ - uint8_t vcoBiasTcf; /* [1:0] */ - uint8_t vcoCalOffset; /* [3:0] */ - uint8_t vcoVaractorRef; /* [3:0] */ - uint8_t loopFilterIcp; /* Icp[5:0] */ - uint8_t loopFilterC2C1; /* C2[3:0],C1[3:0] */ - uint8_t loopFilterR1C3; /* R1[3:0],C3[3:0] */ - uint8_t loopFilterR3; /* R3[3:0] */ - uint8_t vcoIndex; - uint8_t i; - - /* RF PLL variables */ - uint16_t integerWord; - uint32_t fractionalWord; - uint32_t fractionalRemainder; - uint32_t scaledRefClk_Hz; - - /* common */ - uint64_t hsDigClk_Hz = 0; - uint32_t scaledRefClk_kHz = 0; - uint8_t deviceClkDiv = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - - uint8_t clockControl2 = 0; - uint8_t sdmSettings = 0; - uint8_t hsDiv = 4; - uint8_t vcoDiv = 0; - uint8_t vcoDivTimes10 = 10; - - /******************RF Synth Section************************/ - static const uint8_t icp_46p08[53] = {15, 15, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 27, 27, 28, 29, 30, 31, 32, 33, 32, 33, 32, 33, 33, 34, 27, 28, 29, - 29, 30, 39, 29, 30, 31, 31, 30, 31, 31, 32, 30, 31, 31, 32, 32, 31, 31, 32, 32, 33}; - - static const uint8_t icp_61p44[53] = {13, 13, 13, 14, 15, 16, 16, 17, 18, 19, 20, 21, 22, 22, 23, 24, 24, 25, 25, 26, 27, 28, 29, 28, 29, 28, 29, 29, 30, 24, 25, 25, - 26, 26, 35, 33, 34, 35, 35, 26, 27, 27, 28, 27, 27, 27, 28, 28, 27, 27, 28, 28, 29}; - - static const uint8_t icp_76p8[53] = {7, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 15, 16, 15, 16, 15, 16, 16, 17, 13, 14, 14, 14, 15, - 19, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 16, 15, 15, 15, 16, 16}; - - static const uint32_t vcoFreqArray_kHz[53] = {12605000UL, 12245000UL, 11906000UL, 11588000UL, 11288000UL, 11007000UL, 10742000UL, 10492000UL, 10258000UL, 10036000UL, - 9827800UL, 9631100UL, 9445300UL, 9269800UL, 9103600UL, 8946300UL, 8797000UL, 8655300UL, 8520600UL, 8392300UL, 8269900UL, 8153100UL, 8041400UL, 7934400UL, - 7831800UL, 7733200UL, 7638400UL, 7547100UL, 7459000UL, 7374000UL, 7291900UL, 7212400UL, 7135500UL, 7061000UL, 6988700UL, 6918600UL, 6850600UL, 6784600UL, - 6720500UL, 6658200UL, 6597800UL, 6539200UL, 6482300UL, 6427000UL, 6373400UL, 6321400UL, 6270900UL, 6222000UL, 6174500UL, 6128400UL, 6083600UL, 6040100UL, - 5997700UL}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initDigitalClocks()\n"); -#endif - - retVal = MYKONOS_calculateScaledDeviceClk_kHz(device, &scaledRefClk_kHz, &deviceClkDiv); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - hsDiv = device->clocks->clkPllHsDiv; - vcoDiv = device->clocks->clkPllVcoDiv; - - switch (hsDiv) - { - case 4: - hsDiv = 4; /* clockControl2[3:2] = 00 */ - break; - case 5: - hsDiv = 5; - clockControl2 |= 0x04; /* Set bit[2]=1 */ - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV)); - return MYKONOS_ERR_CLKPLL_INV_HSDIV; - } - - switch (vcoDiv) - { - case VCODIV_1: - vcoDivTimes10 = 10; /* clockControl2[1:0] = 00 */ - break; - case VCODIV_1p5: - vcoDivTimes10 = 15; - clockControl2 |= 0x01; - break; - case VCODIV_2: - vcoDivTimes10 = 20; - clockControl2 |= 0x02; - break; - case VCODIV_3: - vcoDivTimes10 = 30; - clockControl2 |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV)); - return MYKONOS_ERR_CLKPLL_INV_VCODIV; - } - - clockControl2 |= ((deviceClkDiv & 3) << 4); - - /* find vco table index based on vco frequency */ - for (i = 0; device->clocks->clkPllVcoFreq_kHz < vcoFreqArray_kHz[i]; i++) - { - /* Intentionally blank, for loop exits when condition met, index i used below */ - } - vcoIndex = i + 1; - - if (vcoIndex < 1 || vcoIndex > 53) - { - /* vco index out of range */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX, - getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX)); - return MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX; - } - - /* valid for all refclk frequencies */ - vcoOutLvl = (vcoIndex <= 16) ? 13 : (vcoIndex <= 23) ? 12 : (vcoIndex <= 25) ? - 11 : (vcoIndex <= 35) ? 10 : (vcoIndex <= 39) ? 9 : (vcoIndex <= 43) ? - 8 : (vcoIndex <= 48) ? 7 : 6; - vcoVaractor = (vcoIndex <= 29 || vcoIndex == 35) ? 1 : 2; - vcoBiasRef = (vcoIndex <= 7 ) ? 4 : (vcoIndex <= 16) ? 6 : 7; - vcoBiasTcf = (vcoIndex <= 25 || (vcoIndex > 26 && vcoIndex <= 29) || - (vcoIndex > 37 && vcoIndex <= 39)) || (vcoIndex > 40 && vcoIndex <= 43) ? - 2 : 3; - - vcoVaractorRef = (vcoIndex <= 29) ? 12 : (vcoIndex == 35) ? 14 : 13; - - if ((scaledRefClk_kHz >= 40000) && (scaledRefClk_kHz < 53760)) - { /* Settings designed for 46.08 MHz PLL REFCLK */ - vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ? - 14 :(vcoIndex <= 10 || vcoIndex > 44) ? - 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ? - 12 : 13; - - loopFilterIcp = icp_46p08[vcoIndex - 1]; - loopFilterC2C1 = 0xF9; /* C2=0xF0 */ - loopFilterR1C3 = 0xD5; - loopFilterR3 = 0x0E; - } - else if ((scaledRefClk_kHz >= 53760) && (scaledRefClk_kHz < 69120)) - { /* Settings designed for 61.44 MHz PLL REFCLK */ - vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 29 && vcoIndex <= 34) || vcoIndex == 40 || vcoIndex == 44) ? - 14 :(vcoIndex <= 10 || vcoIndex > 44) ? - 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 25) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 34 && vcoIndex <= 37)) ? - 12 : (vcoIndex > 37 && vcoIndex <= 39) ? 11 : 13; - - vcoVaractor = (vcoIndex > 35 && vcoIndex <= 39) ? 1 : vcoVaractor; - vcoBiasRef = (vcoIndex > 4 && vcoIndex <= 7) ? 5 : vcoBiasRef; - vcoVaractorRef = (vcoIndex > 35 && vcoIndex <= 39) ? 14 : vcoVaractorRef; - loopFilterIcp = icp_61p44[vcoIndex-1]; - loopFilterC2C1 = ((vcoIndex > 2 && vcoIndex <= 6) || (vcoIndex > 8 && vcoIndex <= 13) || (vcoIndex > 14)) ? 0xFD : 0xFC; /* C2=0xF0 */ - loopFilterR1C3 = 0xC5; - loopFilterR3 = (vcoIndex <= 2 || (vcoIndex > 6 && vcoIndex <= 8) || vcoIndex == 14) ? 14 : 13 ; - } - else if ((scaledRefClk_kHz >= 69120) && (scaledRefClk_kHz <= 80000)) - { /* Settings designed for 76.8 MHz PLL REFCLK */ - vcoCalOffset = (vcoIndex == 11 || (vcoIndex > 35 && vcoIndex <= 37) || (vcoIndex > 29 && vcoIndex <= 34)|| vcoIndex == 40 || vcoIndex == 44) ? - 14 :(vcoIndex <= 10 || vcoIndex > 44) ? - 15 : ((vcoIndex > 12 && vcoIndex <= 22) || (vcoIndex > 23 && vcoIndex <= 23) || (vcoIndex > 26 && vcoIndex <= 29) || (vcoIndex > 23 && vcoIndex <= 25) || vcoIndex == 35) ? - 12 : 13; - - loopFilterIcp = icp_76p8[vcoIndex-1]; - loopFilterC2C1 = (vcoIndex == 20 ) ? 0xF7 : (vcoIndex == 4 || vcoIndex == 6 || vcoIndex == 8 ) ? 0xE6: 0xF6; /*C2=0xF0, C1=6 or 7 */ - loopFilterR1C3 = (vcoIndex == 4 ) ? 0xE4 : 0xD5; - loopFilterR3 = 0x0E; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_REFCLK, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_REFCLK)); - return MYKONOS_ERR_SETRFPLL_INV_REFCLK; /* invalid ref clk */ - } - - /* Hold CLKPLL digital logic in reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x00); - - /* Set reference clock scaler + HSdiv + VCOdiv */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, clockControl2); - - /*Set VCO cal time */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_CAL_CONTROL, 0x02); - - /* Write Synth Setting regs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_F_VCOTN_BYTE1, ((vcoCalOffset & 0x0F) << 3)); /* Set VCO Cal offset[3:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE1, (0xC0 | (vcoVaractor & 0x0F))); /* Init ALC[3:0], VCO varactor[3:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE2, (0x40 | (vcoOutLvl & 0x0F))); /* VCO output level */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE9, (((vcoBiasTcf & 0x03) << 3) | (vcoBiasRef & 0x07))); /* Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_CAL_REF, 0x30); /* Set VCO cal time (compare length) + Set VCO Cal Ref Tcf[2:0]=0 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL1, 0x70); /* Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL2, (vcoVaractorRef & 0x0F)); /* Set VCO Varactor Reference[3:0] */ - - /* Write Loop filter */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE3, (0x80 | (loopFilterIcp & 0x03F))); /* Set Loop Filter Icp[5:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE6, loopFilterC2C1); /* Set Loop Filter C2[3:0] and C1[3:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE7, loopFilterR1C3); /* Set Loop Filter R1[3:0] and C3[3:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_LF_R3, (loopFilterR3 & 0x0F)); /*Set Loop Filter R3[3:0] */ - - /* Calculate PLL integer and fractional words with integer math */ - scaledRefClk_Hz = scaledRefClk_kHz * 1000; - hsDigClk_Hz = (((uint64_t)(device->clocks->clkPllVcoFreq_kHz) * 10000) / vcoDivTimes10) / hsDiv; - integerWord = (uint16_t)(hsDigClk_Hz / scaledRefClk_Hz); - fractionalRemainder = hsDigClk_Hz % scaledRefClk_Hz; - - /* +1 >> 1 is rounding (add .5) */ - fractionalWord = ((uint32_t)((((uint64_t)fractionalRemainder * 4177920) / (uint64_t)scaledRefClk_Hz) + 1) >> 1); - - /* if fractionalWord rounded up and == PLL modulus, fix it */ - if (fractionalWord == 2088960) - { - fractionalWord = 0; - integerWord = integerWord + 1; - } - - if (fractionalWord > 0) - { /* in normal case, the fractional word should be zero and SDM bypassed */ - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLKPLL_INV_FRACWORD, - getMykonosErrorMessage(MYKONOS_ERR_SETCLKPLL_INV_FRACWORD)); - /* down graded to warning, do not return error code */ - //return MYKONOS_ERR_SETCLKPLL_INV_FRACWORD; - sdmSettings = 0x20; - } - else - { - /* Bypass SDM */ - sdmSettings = 0xE0; - } - - /* Set PLL fractional word[22:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, (fractionalWord & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, ((fractionalWord >> 8) & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, ((fractionalWord >> 16) & 0x7F)); - - /* Write PLL integer word [7:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, (sdmSettings | ((integerWord >> 8) & 0x7))); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, (integerWord & 0xFF)); - - /* Release PLL from reset, and set start VCO cal bit to 0 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x80); - - /* Power up CLKPLL */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_0, 0x00); - CMB_wait_ms(200); /* Allow PLL time to power up */ - - /* Enable Charge pump cal after Charge Pump current set (Icp[5:0]) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_BYTE5, 0x84); - - /* Start VCO Cal */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_4, 0x81); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the RF PLL local oscillator frequency (RF carrier frequency). - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the MYKONOS data structure containing settings - * \param pllName Name of the PLL to configure - * \param rfPllLoFrequency_Hz Desired RF LO frequency - * - * \return MYKONOS_ERR_OK Function completed successfully - * \return MYKONOS_ERR_SETRFPLL_ARMERROR ARM Command to set RF PLL frequency failed - */ -mykonosErr_t MYKONOS_setRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t rfPllLoFrequency_Hz) -{ - const uint8_t SETCMD_OPCODE = 0x0A; - const uint8_t SET_PLL_FREQUENCY = 0x63; - - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[8] = {0}; - uint8_t extData[2] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - - armData[0] = (uint8_t)(rfPllLoFrequency_Hz & 0xFF); - armData[1] = (uint8_t)((rfPllLoFrequency_Hz >> 8) & 0xFF); - armData[2] = (uint8_t)((rfPllLoFrequency_Hz >> 16) & 0xFF); - armData[3] = (uint8_t)((rfPllLoFrequency_Hz >> 24) & 0xFF); - armData[4] = (uint8_t)((rfPllLoFrequency_Hz >> 32) & 0xFF); - armData[5] = (uint8_t)((rfPllLoFrequency_Hz >> 40) & 0xFF); - armData[6] = (uint8_t)((rfPllLoFrequency_Hz >> 48) & 0xFF); - armData[7] = (uint8_t)((rfPllLoFrequency_Hz >> 56) & 0xFF); - - /* write 64-bit frequency to ARM memory */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - extData[0] = SET_PLL_FREQUENCY; - - switch (pllName) - { - case RX_PLL: - extData[1] = 0x00; - break; - case TX_PLL: - extData[1] = 0x01; - break; - case SNIFFER_PLL: - extData[1] = 0x02; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_INV_PLLNAME, - getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_INV_PLLNAME)); - return MYKONOS_ERR_SETRFPLL_INV_PLLNAME; - } - } - - retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR)); - return MYKONOS_ERR_SETRFPLL_ARMERROR; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_ARMERROR)); - return MYKONOS_ERR_SETRFPLL_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Gets the RF PLL local oscillator frequency (RF carrier frequency). - * - * This function is used to get the RF PLL's frequency. It can get the RX PLL, TX PLL - * Sniffer PLL, and CLKPLL. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - device->clocks->deviceClock_kHz - * - * \param device is structure pointer to the MYKONOS data structure containing settings - * \param pllName Name of the PLL for which to read the frequency - * \param rfPllLoFrequency_Hz RF LO frequency currently set for the PLL specified - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV Invalid CLKPLL reference clock divider read from Mykonos device - * \retval MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV Invalid CLKPLL high speed clock divider read from Mykonos device - * \retval MYKONOS_ERR_GETRFPLL_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM. - * \retval MYKONOS_ERR_GETRFPLL_ARMERROR ARM Command to get RF PLL frequency failed - * \retval MYKONOS_ERR_GETRFPLL_NULLPARAM rfPllLoFrequency_Hz function parameter pointer is NULL - */ -mykonosErr_t MYKONOS_getRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t *rfPllLoFrequency_Hz) -{ - const uint8_t RFPLL_LO_FREQUENCY = 0x63; - - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t extData[2] = {0, 0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint8_t getClkPllFrequency = 0; - - uint32_t clkPllIntWord = 0; - uint32_t clkPllFracWord = 0; - uint8_t clkPllRefClkDiv = 0; - uint8_t hsDiv = 0; - uint8_t vcoDivTimes10 = 0; - uint8_t hsDivReg = 0; - uint8_t vcoDivReg = 0; - uint8_t clkPllIntWord7_0 = 0; - uint8_t clkPllIntWord10_8 = 0; - uint8_t clkPllFracWord7_0 = 0; - uint8_t clkPllFracWord15_8 = 0; - uint8_t clkPllFracWord22_16 = 0; - uint64_t refclk_Hz = 0; - - extData[0] = RFPLL_LO_FREQUENCY; - - switch (pllName) - { - case CLK_PLL: - getClkPllFrequency = 1; - break; - case RX_PLL: - extData[1] = 0x00; - break; - case TX_PLL: - extData[1] = 0x01; - break; - case SNIFFER_PLL: - extData[1] = 0x02; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_INV_PLLNAME, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_INV_PLLNAME)); - return MYKONOS_ERR_GETRFPLL_INV_PLLNAME; - } - } - - if (getClkPllFrequency > 0) - { - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &hsDivReg, 0x0C, 2); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &vcoDivReg, 0x03, 0); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_2, &clkPllRefClkDiv, 0x70, 4); - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0, &clkPllIntWord7_0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllIntWord10_8); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0, &clkPllFracWord7_0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1, &clkPllFracWord15_8); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2, &clkPllFracWord22_16); - - clkPllIntWord = (((uint32_t)(clkPllIntWord10_8 & 0x7) << 8) | clkPllIntWord7_0); - clkPllFracWord = (((uint32_t)(clkPllFracWord22_16 & 0x7F) << 16) | ((uint32_t)(clkPllFracWord15_8) << 8) | clkPllFracWord7_0); - - switch (clkPllRefClkDiv) - { - case 0: - refclk_Hz = ((uint64_t)device->clocks->deviceClock_kHz * 1000); - break; - case 1: - refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 1); - break; /* div 2 */ - case 2: - refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) >> 2); - break; /* div 4 */ - case 3: - refclk_Hz = (((uint64_t)device->clocks->deviceClock_kHz * 1000) << 1); - break; /* times 2 */ - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV, - getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV)); - return MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV; - } - } - - switch (vcoDivReg) - { - case 0: - vcoDivTimes10 = 10; - break; - case 1: - vcoDivTimes10 = 15; - break; - case 2: - vcoDivTimes10 = 20; - break; - case 3: - vcoDivTimes10 = 30; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV, - getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV)); - return MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV; - } - } - - switch (hsDivReg) - { - case 0: - hsDiv = 4; - break; - case 1: - hsDiv = 5; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV, - getMykonosErrorMessage(MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV)); - return MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV; - } - } - - /* round to nearest Hz for fractional word (fractional modulus = 2088960) */ - *rfPllLoFrequency_Hz = (uint64_t)(((refclk_Hz * clkPllIntWord) + (((refclk_Hz * clkPllFracWord / 1044480) + 1) >> 1)) * hsDiv * vcoDivTimes10 / 10); - } - else - { - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR)); - return MYKONOS_ERR_GETRFPLL_ARMERROR; - } - - return retVal; - } - - /* read 64-bit frequency from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_ARMERROR, getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_ARMERROR)); - return MYKONOS_ERR_GETRFPLL_ARMERROR; - } - - if (rfPllLoFrequency_Hz == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_NULLPARAM)); - return MYKONOS_ERR_GETRFPLL_NULLPARAM; - } - - *rfPllLoFrequency_Hz = (uint64_t)((uint64_t)(armData[0])) | ((uint64_t)(armData[1]) << 8) | ((uint64_t)(armData[2]) << 16) | ((uint64_t)(armData[3]) << 24) - | ((uint64_t)(armData[4]) << 32) | ((uint64_t)(armData[5]) << 40) | ((uint64_t)(armData[6]) << 48) | ((uint64_t)(armData[7]) << 56); - } - return MYKONOS_ERR_OK; -} - -/** - * \brief Checks if the PLLs are locked - * - * This function updates the pllLockStatus pointer with a lock status it per - * PLL. - * pllLockStatus[0] = CLKPLL Locked - * pllLockStatus[1] = RX_PLL Locked - * pllLockStatus[2] = TX_PLL Locked - * pllLockStatus[3] = SNIFFER_PLL Locked - * pllLockStatus[4] = CAL_PLL Locked - * - * \param device the Mykonos device data structure - * \param pllLockStatus Lock status bit per PLL - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_checkPllsLockStatus(mykonosDevice_t *device, uint8_t *pllLockStatus) -{ - uint8_t readData = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkPllsLockStatus()\n"); -#endif - - if (pllLockStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM)); - return MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM; - } - - *pllLockStatus = 0; - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); - *pllLockStatus = readData; - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); - *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 1); - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); - *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 2); - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1, &readData, 0x01, 0); - *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 3); - - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CALPLL_SDM_CONTROL, &readData, 0x80, 7); - *pllLockStatus = *pllLockStatus | (uint8_t)(readData << 4); - - return MYKONOS_ERR_OK; -} - -/* - ***************************************************************************** - * Shared Data path functions - ***************************************************************************** - */ - -/** - * \brief Sets the digital Tx PFIR SYNC clock divider. - * - * This function is a helper function. It is called automatically in - * MYKONOS_initialize() and should not need to be called by the BBIC. - * - * This function sets the digital clock divider that is used to synchronize the - * Tx PFIR each time the Tx channel power up. The Sync clock must - * be set equal to or slower than the FIR processing clock. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->txProfile->txFir - * - device->tx->txProfile->txFir->numFirCoefs - * - device->tx->txProfile->txFirInterpolation - * - device->tx->txProfile->iqRate_kHz - * - * \param device Pointer to the Mykonos data structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM: Invalid number of Tx FIR coefficients - * \retval MYKONOS_ERR_TXFIR_INV_NUMROWS Invalid number of PFIR coefficient rows - * \retval MYKONOS_ERR_TXFIR_TAPSEXCEEDED Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps - */ -mykonosErr_t MYKONOS_setTxPfirSyncClk(mykonosDevice_t *device) -{ - const uint8_t numTapMultiple = 16; - const uint8_t maxNumTaps = 96; - uint8_t effectiveRows = 0; - uint8_t numRows = 0; - uint32_t dpClk_kHz = 0; - uint32_t syncClk_kHz = 0; - uint32_t hsDigClkDiv4or5_kHz = 0; - uint8_t syncDiv = 0; - mykonosErr_t retval = MYKONOS_ERR_OK; - - if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->txProfile->txFir != NULL)) - { - /* Calculate number of FIR rows for number of Taps */ - if ((device->tx->txProfile->txFir->numFirCoefs % numTapMultiple == 0) && (device->tx->txProfile->txFir->numFirCoefs > 0) - && (device->tx->txProfile->txFir->numFirCoefs <= maxNumTaps)) - { - numRows = (device->tx->txProfile->txFir->numFirCoefs / numTapMultiple); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM, - getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM)); - return MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM; - } - - effectiveRows = ((numRows + (device->tx->txProfile->txFirInterpolation - 1)) / device->tx->txProfile->txFirInterpolation); - - /* round up to next power of 2 */ - switch (effectiveRows) - { - case 1: - effectiveRows = 1; - break; - case 2: - effectiveRows = 2; - break; - case 3: /* fall through */ - case 4: - effectiveRows = 4; - break; - case 5: /* fall through */ - case 6: /* fall through */ - case 7: /* fall through */ - case 8: - effectiveRows = 8; - break; - default: - { - /* invalid number of FIR taps */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_NUMROWS, - getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_NUMROWS)); - return MYKONOS_ERR_TXFIR_INV_NUMROWS; - } - } - - dpClk_kHz = (device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txInputHbInterpolation * device->tx->txProfile->txFirInterpolation * effectiveRows); - - /* FIR DPCLK can only run at max of 500MHz */ - if (dpClk_kHz > 500000) - { - /* Max number of Tx PFIR taps exceeded for Tx Profile */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_TAPSEXCEEDED, - getMykonosErrorMessage(MYKONOS_ERR_TXFIR_TAPSEXCEEDED)); - return MYKONOS_ERR_TXFIR_TAPSEXCEEDED; - } - - /* SYNC CLOCK is the PFIR output rate / 2 */ - syncClk_kHz = device->tx->txProfile->iqRate_kHz * device->tx->txProfile->txFirInterpolation / 2; - if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK) - { - return retval; - } - - /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */ - for (syncDiv = 0; syncDiv < 5; syncDiv++) - { - if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz) - { - break; - } - } - - /* Write Tx PFIR SYNC Clock divider */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x70, 4); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the digital Rx PFIR SYNC clock divider. - * - * This function is a helper function. It is called automatically in - * MYKONOS_initialize() and should not need to be called by the BBIC. - * - * This function sets the digital clock divider that is used to synchronize the - * Rx/ORx/Sniffer PFIRs each time the channels power up. The Sync clock must - * be set equal to or slower than the slowest Rx/ORx/Sniffer PFIR processing - * clock. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->rx->rxProfile->rxFir - * - device->rx->rxProfile->rxFir->numFirCoefs - * - device->rx->rxProfile->iqRate_kHz - * - device->obsRx->orxProfile->rxFir - * - device->obsRx->orxProfile->rxFir->numFirCoefs - * - device->obsRx->orxProfile->iqRate_kHz - * - device->obsRx->snifferProfile->rxFir - * - device->obsRx->snifferProfile->rxFir->numFirCoefs - * - device->obsRx->snifferProfile->iqRate_kHz - * - * \param device Pointer to the Mykonos data structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_RXFIR_TAPSEXCEEDED ERROR: the number of Rx FIR taps exceeds the number of taps accommodated by the FIR processing clock - * \retval MYKONOS_ERR_ORXFIR_TAPSEXCEEDED ERROR: the number of ORx FIR Taps exceeds the number of taps accommodated by the FIR processing clock - * \retval MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED ERROR: the number of sniffer FIR taps exceeds the number of taps accommodated by the FIR processing clock - */ -mykonosErr_t MYKONOS_setRxPfirSyncClk(mykonosDevice_t *device) -{ - uint32_t rxDpClk_kHz = 0; - uint32_t orxDpClk_kHz = 0; - uint32_t snRxDpClk_kHz = 0; - uint32_t slowestIqRate_kHz = 0; - uint32_t syncClk_kHz = 0; - uint8_t effectiveRxNumRows = 0; - uint8_t effectiveOrxNumRows = 0; - uint8_t effectiveSnrxNumRows = 0; - - uint32_t hsDigClkDiv4or5_kHz = 0; - uint8_t syncDiv = 0; - mykonosErr_t retval = MYKONOS_ERR_OK; - - /** - * Calculate Rx SYNC Clock divider for Rx PFIR. Same Rx SYNC Clock is used - * for Rx, ORx, and Sniffer PFIRs, and must be slow enough to handle the slowest - * PFIR rate. - **/ - - if (((device->profilesValid & RX_PROFILE_VALID) > 0) && (device->rx->rxProfile->rxFir != NULL)) - { - switch (device->rx->rxProfile->rxFir->numFirCoefs) - { - case 24: - effectiveRxNumRows = 1; - break; - case 48: - effectiveRxNumRows = 2; - break; - case 72: - effectiveRxNumRows = 4; - break; - default: - break; - } - - rxDpClk_kHz = device->rx->rxProfile->iqRate_kHz * effectiveRxNumRows; - - if (rxDpClk_kHz > 500000) - { - /* Max number of Rx PFIR taps exceeded for Profile */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_TAPSEXCEEDED, - getMykonosErrorMessage(MYKONOS_ERR_RXFIR_TAPSEXCEEDED)); - return MYKONOS_ERR_RXFIR_TAPSEXCEEDED; - } - - slowestIqRate_kHz = device->rx->rxProfile->iqRate_kHz; - } - - if (((device->profilesValid & ORX_PROFILE_VALID) > 0) && (device->obsRx->orxProfile->rxFir != NULL)) - { - switch (device->obsRx->orxProfile->rxFir->numFirCoefs) - { - case 24: - effectiveOrxNumRows = 1; - break; - case 48: - effectiveOrxNumRows = 2; - break; - case 72: - effectiveOrxNumRows = 4; - break; - default: - break; - } - - orxDpClk_kHz = device->obsRx->orxProfile->iqRate_kHz * effectiveOrxNumRows; - - if (orxDpClk_kHz > 500000) - { - /* Max number of ORx PFIR taps exceeded for Profile */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ORXFIR_TAPSEXCEEDED, - getMykonosErrorMessage(MYKONOS_ERR_ORXFIR_TAPSEXCEEDED)); - return MYKONOS_ERR_ORXFIR_TAPSEXCEEDED; - } - - if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->orxProfile->iqRate_kHz)) - { - slowestIqRate_kHz = device->obsRx->orxProfile->iqRate_kHz; - - } - } - - if (((device->profilesValid & SNIFF_PROFILE_VALID) > 0) && (device->obsRx->snifferProfile->rxFir != NULL)) - { - switch (device->obsRx->snifferProfile->rxFir->numFirCoefs) - { - case 24: - effectiveSnrxNumRows = 1; - break; - case 48: - effectiveSnrxNumRows = 2; - break; - case 72: - effectiveSnrxNumRows = 4; - break; - default: - break; - } - - snRxDpClk_kHz = device->obsRx->snifferProfile->iqRate_kHz * effectiveSnrxNumRows; - - if (snRxDpClk_kHz > 500000) - { - /* Max number of ORx PFIR taps exceeded for Profile */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED, - getMykonosErrorMessage(MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED)); - return MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED; - } - - if ((slowestIqRate_kHz == 0) || (slowestIqRate_kHz > device->obsRx->snifferProfile->iqRate_kHz)) - { - slowestIqRate_kHz = device->obsRx->snifferProfile->iqRate_kHz; - } - } - - /* SYNC CLOCK should be FIR output rate / 2 */ - syncClk_kHz = (slowestIqRate_kHz / 2); - if ((retval = MYKONOS_calculateDigitalClocks(device, NULL, &hsDigClkDiv4or5_kHz)) != MYKONOS_ERR_OK) - { - return retval; - } - - /* Select correct divider setting for SYNCCLK - must be == syncClk_kHz or slower */ - for (syncDiv = 0; syncDiv < 5; syncDiv++) - { - if ((hsDigClkDiv4or5_kHz / (uint32_t)(4 << syncDiv)) <= syncClk_kHz) - { - break; - } - } - - /* Write Rx PFIR SYNC Clock divider */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_5, syncDiv, 0x07, 0); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Configures one or more FIR filters in the device - * - * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx). - * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32, - * 48, 64, 80, or 96 taps. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos data structure - * \param filterToProgram Name of the desired filter to program - * \param firFilter Pointer to the filter to write into the device - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_PROGRAMFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer - * \retval MYKONOS_ERR_PROGRAMFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer - * \retval MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToProgram parameter - * \retval MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter - * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting - * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting - * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting - * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting - */ -mykonosErr_t MYKONOS_programFir(mykonosDevice_t *device, mykonosfirName_t filterToProgram, mykonosFir_t *firFilter) -{ - uint8_t filterSelect = 0; - uint8_t i = 0; - uint8_t numTapsReg = 0; - uint8_t numTapMultiple = 24; /* Rx=24, Tx=16 */ - uint8_t maxNumTaps = 72; /* Rx=72, Tx=96 */ - uint8_t filterGain = 0; - -#if MYK_ENABLE_SPIWRITEARRAY == 1 - uint32_t addrIndex = 0; - uint32_t dataIndex = 0; - uint32_t spiBufferSize = ((MYK_SPIWRITEARRAY_BUFFERSIZE / 6) * 6); /* Make buffer size a multiple of 6 */ - uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; - uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; -#endif - - const uint8_t COEF_WRITE_EN = 0x40; - const uint8_t PROGRAM_CLK_EN = 0x80; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programFir()\n"); -#endif - - if (firFilter == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_NULL_PARM)); - return MYKONOS_ERR_PROGRAMFIR_NULL_PARM; - } - - if (firFilter->coefs == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_COEFS_NULL, - getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_COEFS_NULL)); - return MYKONOS_ERR_PROGRAMFIR_COEFS_NULL; - } - - switch (filterToProgram) - { - case TX1_FIR: - filterSelect = 0x01; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case TX2_FIR: - filterSelect = 0x02; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case TX1TX2_FIR: - filterSelect = 0x03; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case RX1_FIR: - filterSelect = 0x04; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case RX2_FIR: - filterSelect = 0x08; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case RX1RX2_FIR: - filterSelect = 0x0C; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case OBSRX_A_FIR: - filterSelect = 0x10; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case OBSRX_B_FIR: - filterSelect = 0x20; - numTapMultiple = 24; - maxNumTaps = 72; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM)); - return MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM; - } - - /* Calculate register value for number of Taps */ - if ((firFilter->numFirCoefs % numTapMultiple == 0) && (firFilter->numFirCoefs > 0) && (firFilter->numFirCoefs <= maxNumTaps)) - { - numTapsReg = (firFilter->numFirCoefs / numTapMultiple) - 1; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, - getMykonosErrorMessage(MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM)); - return MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM; - } - - /* Select which FIR filter to program coeffs for */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock - -#if (MYK_ENABLE_SPIWRITEARRAY == 0) - - /* write filter coefficients */ - for (i = 0; i < firFilter->numFirCoefs; i++) - { - /* Write Low byte of 16bit coefficient */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (i * 2)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, (firFilter->coefs[i] & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect)); /* write enable (self clearing) */ - - /* Write High Byte of 16bit coefficient */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, ((i * 2) + 1)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, ((firFilter->coefs[i] >> 8) & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect));/* write enable (self clearing) */ - } - -#elif (MYK_ENABLE_SPIWRITEARRAY == 1) - - addrIndex = 0; - dataIndex = 0; - for (i = 0; i < firFilter->numFirCoefs; i++) - { - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR; - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA; - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL; - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_ADDR; - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_DATA; - addrArray[addrIndex++] = MYKONOS_ADDR_PFIR_COEFF_CTL; - - dataArray[dataIndex++] = (uint8_t)(i * 2); - dataArray[dataIndex++] = (firFilter->coefs[i] & 0xFF); - dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect); - dataArray[dataIndex++] = (uint8_t)((i * 2) + 1); - dataArray[dataIndex++] = (((uint16_t)firFilter->coefs[i] >> 8) & 0xFF); - dataArray[dataIndex++] = (PROGRAM_CLK_EN | COEF_WRITE_EN | filterSelect); - - /* Send full buffer size when possible */ - /* spiBufferSize set to multiple of 6 at top of function */ - if (addrIndex >= spiBufferSize) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); - dataIndex = 0; - addrIndex = 0; - } - } - - if (addrIndex > 0) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); - } - -#endif - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect); /* clear Program clock enable */ - /* write filter gain and #taps */ - if (filterToProgram == RX1_FIR || filterToProgram == RX2_FIR || filterToProgram == RX1RX2_FIR) - { - /* Write Rx FIR #taps */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x60, 5); - - /* Set Rx filter gain */ - switch (firFilter->gain_dB) - { - case -12: - filterGain = 0x00; - break; - case -6: - filterGain = 0x01; - break; - case 0: - filterGain = 0x02; - break; - case 6: - filterGain = 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_RXFIR_INV_GAIN_PARM; - } - - /* Write Rx filter gain */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, filterGain, 0x03, 0); - } - else if (filterToProgram == OBSRX_A_FIR) - { - /* Write Obs Rx FIR A #taps */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x06, 1); - - /* Set Rx filter gain */ - switch (firFilter->gain_dB) - { - case -12: - filterGain = 0x00; - break; - case -6: - filterGain = 0x01; - break; - case 0: - filterGain = 0x02; - break; - case 6: - filterGain = 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM; - } - - /* Write Obs Rx filter gain */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x03, 0); - } - else if (filterToProgram == OBSRX_B_FIR) - { - /* Write Obs Rx FIR B #taps */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, numTapsReg, 0x18, 3); - - /* Set Rx filter gain */ - switch (firFilter->gain_dB) - { - case -12: - filterGain = 0x00; - break; - case -6: - filterGain = 0x01; - break; - case 0: - filterGain = 0x02; - break; - case 6: - filterGain = 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM; - } - - /* Write Obs Rx filter gain */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, filterGain, 0x60, 5); - } - else if (filterToProgram == TX1_FIR || filterToProgram == TX2_FIR || filterToProgram == TX1TX2_FIR) - { - /* Write number of Taps */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, numTapsReg, 0xE0, 5); - - switch (firFilter->gain_dB) - { - case 0: - filterGain = 0; - break; - case 6: - filterGain = 1; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_TXFIR_INV_GAIN_PARM; - } - - /* Write Tx Filter gain */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, filterGain, 0x01, 0); - - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the FIR filter programmed into the device - * - * The device stores up to 6 FIR filters (2Rx, 2Obs Rx/Sniffer, and 2Tx). - * Rx filters can have 24, 48, or 72 taps. Tx filters can have 16, 32, - * 48, 64, 80, or 96 taps. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos data structure - * \param filterToRead Name of the desired filter to be read - * \param firFilter Pointer to the filter to be read from the device - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READFIR_NULL_PARM ERROR: firFilter parameter is a NULL pointer - * \retval MYKONOS_ERR_READFIR_COEFS_NULL ERROR: firFilter->coefs is a NULL pointer - * \retval MYKONOS_ERR_READFIR_INV_FIRNAME_PARM ERROR: Invalid FIR filter name in filterToRead parameter - * \retval MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM ERROR: Invalid number of taps for the filter - * \retval MYKONOS_ERR_RXFIR_INV_GAIN_PARM ERROR: Rx FIR filter has invalid gain setting - * \retval MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM ERROR: OBSRX_A (ORX) FIR filter has invalid gain setting - * \retval MYKONOS_ERR_SRXFIR_INV_GAIN_PARM ERROR: OBSRX_B (Sniffer) FIR filter has invalid gain setting - * \retval MYKONOS_ERR_TXFIR_INV_GAIN_PARM ERROR: Tx FIR filter has invalid gain setting - */ -mykonosErr_t MYKONOS_readFir(mykonosDevice_t *device, mykonosfirName_t filterToRead, mykonosFir_t *firFilter) -{ - uint8_t filterSelect = 0; - uint8_t i = 0; - uint8_t numTapsReg = 0; - uint8_t numTapMultiple = 24; - uint8_t maxNumTaps = 72; - uint8_t filterGain = 0; - uint8_t msbRead = 0; - uint8_t lsbRead = 0; - - const uint8_t PROGRAM_CLK_EN = 0x80; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readFir()\n"); -#endif - - if (firFilter == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_READFIR_NULL_PARM)); - return MYKONOS_ERR_READFIR_NULL_PARM; - } - - if (firFilter->coefs == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_COEFS_NULL, getMykonosErrorMessage(MYKONOS_ERR_READFIR_COEFS_NULL)); - return MYKONOS_ERR_READFIR_COEFS_NULL; - } - - switch (filterToRead) - { - case TX1_FIR: - filterSelect = 0x01; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case TX2_FIR: - filterSelect = 0x02; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case TX1TX2_FIR: - filterSelect = 0x03; - numTapMultiple = 16; - maxNumTaps = 96; - break; - case RX1_FIR: - filterSelect = 0x04; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case RX2_FIR: - filterSelect = 0x08; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case RX1RX2_FIR: - filterSelect = 0x0C; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case OBSRX_A_FIR: - filterSelect = 0x10; - numTapMultiple = 24; - maxNumTaps = 72; - break; - case OBSRX_B_FIR: - filterSelect = 0x20; - numTapMultiple = 24; - maxNumTaps = 72; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_FIRNAME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_FIRNAME_PARM)); - return MYKONOS_ERR_READFIR_INV_FIRNAME_PARM; - } - - /* clear Program clock enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, filterSelect); - - /* Read filter gain and #taps */ - if (filterToRead == RX1_FIR || filterToRead == RX2_FIR || filterToRead == RX1RX2_FIR) - { - /* Read Rx FIR #taps */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 5); - - firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); - - /* Read Rx filter gain */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_GAIN, &filterGain, 0x03, 0); - - switch (filterGain) - { - case 0x00: - firFilter->gain_dB = -12; - break; - case 0x01: - firFilter->gain_dB = -6; - break; - case 0x02: - firFilter->gain_dB = 0; - break; - case 0x03: - firFilter->gain_dB = 6; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_RXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_RXFIR_INV_GAIN_PARM; - } - } - else if (filterToRead == OBSRX_A_FIR) - { - /* Read Obs Rx FIR A #taps */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x60, 1); - - firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); - - /* Read Obs Rx FIR A gain */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x03, 0); - - switch (filterGain) - { - case 0x00: - firFilter->gain_dB = -12; - break; - case 0x01: - firFilter->gain_dB = -6; - break; - case 0x02: - firFilter->gain_dB = 0; - break; - case 0x03: - firFilter->gain_dB = 6; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM; - } - } - else if (filterToRead == OBSRX_B_FIR) - { - /* Read Obs Rx FIR B #taps */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_RX_FILTER_CONFIGURATION, &numTapsReg, 0x18, 3); - - firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); - - /* Read Obs Rx FIR B gain */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN, &filterGain, 0x60, 5); - - switch (filterGain) - { - case 0x00: - firFilter->gain_dB = -12; - break; - case 0x01: - firFilter->gain_dB = -6; - break; - case 0x02: - firFilter->gain_dB = 0; - break; - case 0x03: - firFilter->gain_dB = 6; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SRXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_SRXFIR_INV_GAIN_PARM; - } - } - else if (filterToRead == TX1_FIR || filterToRead == TX2_FIR || filterToRead == TX1TX2_FIR) - { - /* Read number of Taps */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &numTapsReg, 0xE0, 5); - - firFilter->numFirCoefs = (uint8_t)((numTapsReg + 1) * numTapMultiple); - - /* Read Tx Filter gain */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX_FILTER_CONFIGURATION, &filterGain, 0x01, 0); - - switch (filterGain) - { - case 0: - firFilter->gain_dB = 0; - break; - case 1: - firFilter->gain_dB = 6; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TXFIR_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_TXFIR_INV_GAIN_PARM)); - return MYKONOS_ERR_TXFIR_INV_GAIN_PARM; - } - } - - /* Select which FIR filter to read the coeffs for */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); //select filter and enable the programming clock - - if (firFilter->numFirCoefs > maxNumTaps) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM)); - return MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM; - } - - /* write filter coefficients */ - for (i = 0; i < firFilter->numFirCoefs; i++) - { - /* Write Low byte of 16bit coefficient */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)(i * 2)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect)); /* write enable (self clearing) */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &lsbRead); - - /* Write High Byte of 16bit coefficient */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_ADDR, (uint8_t)((i * 2) + 1)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_CTL, (PROGRAM_CLK_EN | filterSelect));/* write enable (self clearing) */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PFIR_COEFF_DATA, &msbRead); - - firFilter->coefs[i] = (int16_t)((lsbRead & 0xFF) | ((msbRead << 8) & 0xFF00)); - } - - return MYKONOS_ERR_OK; -} - -/* - ***************************************************************************** - * Rx Data path functions - ***************************************************************************** - */ -/*! - * \brief Programs the gain table settings for either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx receiver types - * - * The gain table for a receiver type is set with the parameters passed by uint8_t gainTablePtr array. - * gainTablePtr is a 4 x n array, where there are four (4) elements per index, and the array - * length (n) is dependent upon receiver type. The (n) value is conveyed by numGainIndexesInTable. - * All gain tables have a maximum index of 255 when used with this function. The minimum gain index is - * application dependent. - * - * Where for Rx1, Rx2, and ObsRx: - * [A, B, C, D]: A = Front End Gain, B = External Control, C = Digital Attenuation/Gain, D = Attenuation/Gain select - * - * Where for SnRx: - * [A, B, C, D]: A = Front End Gain, B = LNA Bypass, C = Digital Attenuation/Gain, D = Attenuation/Gain select - * - * The gain table starting address changes with each receiver type. This function accounts for this change as well as the - * difference between byte [B] for {Rx1, Rx2, ObsRx} and SnRx receiver array values and programs the correct registers. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos data structure - * \param gainTablePtr Pointer to 4 x n array containing gain table program values - * \param numGainIndexesInTable The number of 'n' indices in 4 x n array. A range check is performed to ensure the maximum is not exceeded. - * \param rxChannel mykonosGainTable_t enum type to select either Rx1, Rx2, Rx1 + Rx2, ORx, or SnRx gain table for programming. A - * channel check is performed to ensure a valid selection. - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK if successful, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL if invalid channel is selected, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE - * if numGainIndexesInTable exceeds range for selected receiver gain table - */ -mykonosErr_t MYKONOS_programRxGainTable(mykonosDevice_t *device, uint8_t *gainTablePtr, uint8_t numGainIndexesInTable, mykonosGainTable_t rxChannel) -{ - uint8_t ctlReg = 0; - uint8_t ch3CtlReg = 0; - uint16_t rxFEGainAddr = 0; - uint16_t rxExtCtlLnaAddr = 0; - uint16_t rxDigGainAttenAddr = 0; - uint16_t rx2FEGainAddr = 0; - uint16_t rx2ExtCtlAddr = 0; - uint16_t rx2DigGainAttenAddr = 0; - uint8_t minGainIndex = 0; - uint8_t startIndex = 0; - int16_t i = 0; - uint16_t tableRowIndex = 0; - uint8_t retFlag = 0; - -#if MYK_ENABLE_SPIWRITEARRAY - uint32_t addrIndex = 0; - uint32_t dataIndex = 0; - uint32_t spiBufferSize = (((MYK_SPIWRITEARRAY_BUFFERSIZE / 9) - 1) * 9); - uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; - uint8_t dataArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; -#endif - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_programRxGainTable()\n"); -#endif - - if (gainTablePtr == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM)); - return MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM; - } - - /* checking range of numGainIndexesInTable against maximums and for valid rxChannel selection */ - switch (rxChannel) - { - case RX1_GT: - /* Rx1 max gain index = 255, check is out of range of uint8_t */ - break; - case RX2_GT: - /* Rx1 max gain index = 255, check is out of range of uint8_t */ - break; - case RX1_RX2_GT: - /* Rx1 max gain index = 255, check is out of range of uint8_t */ - break; - case ORX_GT: - if (numGainIndexesInTable > MAX_ORX_GAIN_TABLE_NUMINDEXES) - { - retFlag = 1; - } - break; - case SNRX_GT: - if (numGainIndexesInTable > MAX_SNRX_GAIN_TABLE_NUMINDEXES) - { - retFlag = 1; - } - break; - case LOOPBACK_GT: - if (numGainIndexesInTable > MAX_LOOPBACK_GAIN_TABLE_NUMINDEXES) - { - retFlag = 1; - } - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL)); - return MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL; - } - - if (retFlag) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE)); - return MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE; - } - else - { - /* calculating minimum gain index value */ - minGainIndex = MAX_GAIN_TABLE_INDEX - numGainIndexesInTable + 1; - } - - /* forming control register words based on channel select, assigning starting index, and register addressing, also updating max and min gain table indices in structure */ - switch (rxChannel) - { - case RX1_GT: - ctlReg = ((uint8_t)rxChannel << 3) | 0x05; - startIndex = START_RX_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN; - device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX; - device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex; - break; - case RX2_GT: - ctlReg = ((uint8_t)rxChannel << 3) | 0x05; - startIndex = START_RX_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN; - device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX; - device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex; - break; - case RX1_RX2_GT: - ctlReg = ((uint8_t)rxChannel << 3) | 0x05; - startIndex = START_RX_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN; - rx2FEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL; - rx2ExtCtlAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN; - rx2DigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN; - device->rx->rxGainCtrl->rx1MaxGainIndex = MAX_GAIN_TABLE_INDEX; - device->rx->rxGainCtrl->rx1MinGainIndex = minGainIndex; - device->rx->rxGainCtrl->rx2MaxGainIndex = MAX_GAIN_TABLE_INDEX; - device->rx->rxGainCtrl->rx2MinGainIndex = minGainIndex; - break; - case ORX_GT: - ctlReg = 0x05; - ch3CtlReg = 0x08; - startIndex = START_ORX_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; - device->obsRx->orxGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX; - device->obsRx->orxGainCtrl->minGainIndex = minGainIndex; - break; - case SNRX_GT: - ctlReg = 0x05; - ch3CtlReg = 0x00; - startIndex = START_SNRX_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; - device->obsRx->snifferGainCtrl->maxGainIndex = MAX_GAIN_TABLE_INDEX; - device->obsRx->snifferGainCtrl->minGainIndex = minGainIndex; - break; - /*case LOOPBACK_GT: Loopback is only for ARM calibrations */ - default: - ctlReg = 0x05; - ch3CtlReg = 0x10; - startIndex = START_LOOPBACK_GAIN_INDEX; - rxFEGainAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN; - rxExtCtlLnaAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB; - rxDigGainAttenAddr = MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN; - break; - } - - /* starting the gain table clock and read from gain table address bits */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg); - - /* if ORx or Sniffer are selected also writing channel 3 readback bits for ObsRx or Sniffer selection */ - if (rxChannel > RX1_RX2_GT) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg); - } - - /* programming a table selected by rxChannel enum type */ - -#if MYK_ENABLE_SPIWRITEARRAY == 0 - - for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--) - { - tableRowIndex = (uint16_t)(startIndex - i) << 2; - - /* set current gain table index (address) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_ADDR, i); - - /* Set Rx Front End gain[5:0] */ - CMB_SPIWriteByte(device->spiSettings, rxFEGainAddr, gainTablePtr[tableRowIndex]); - - /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */ - if (rxChannel == SNRX_GT) - { - CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1] << 4); - } - else - { - CMB_SPIWriteByte(device->spiSettings, rxExtCtlLnaAddr, gainTablePtr[tableRowIndex + 1]); - } - - /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */ - CMB_SPIWriteByte(device->spiSettings, rxDigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); - - /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */ - if (rxChannel == RX1_RX2_GT) - { - /* Set Rx Front End gain[5:0] */ - CMB_SPIWriteByte(device->spiSettings, rx2FEGainAddr, gainTablePtr[tableRowIndex]); - - /* Set external control [5:0] */ - CMB_SPIWriteByte(device->spiSettings, rx2ExtCtlAddr, gainTablePtr[tableRowIndex + 1]); - - /* Set digital attenuation/gain[6:0] */ - CMB_SPIWriteByte(device->spiSettings, rx2DigGainAttenAddr, (gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); - } - - /* setting the write enable depending on rxChannel choice */ - if (rxChannel == ORX_GT) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x02); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); - } - else if (rxChannel == SNRX_GT) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); - } - else if (rxChannel == LOOPBACK_GT) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, ch3CtlReg | 0x04); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, ctlReg | 0x02); - } - } - -#elif MYK_ENABLE_SPIWRITEARRAY == 1 -//#elif 0 - - addrIndex = 0; - dataIndex = 0; - for(i = startIndex; i >= ((startIndex + 1) - numGainIndexesInTable); i--) - { - tableRowIndex = (uint16_t)(startIndex - (uint8_t)i) << 2; - - /* set current gain table index (address) */ - addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_ADDR; - dataArray[dataIndex++] = (uint8_t)i; - - /* Set Rx Front End gain[5:0] */ - addrArray[addrIndex++] = rxFEGainAddr; - dataArray[dataIndex++] = gainTablePtr[tableRowIndex]; - - /* Set external control [5:0] OR LNA bypass if rxChannel == SNRX_GT */ - addrArray[addrIndex++] = rxExtCtlLnaAddr; - dataArray[dataIndex++] = (rxChannel == SNRX_GT) ? (uint8_t)(gainTablePtr[tableRowIndex + 1] << 4) : (gainTablePtr[tableRowIndex + 1]); - - /* Set digital attenuation/gain[6:0] and set/clear attenuation bit */ - addrArray[addrIndex++] = rxDigGainAttenAddr; - dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); - - /* repeating gain table settings if Rx1 and Rx2 are selected for Rx2 configuration */ - if (rxChannel == RX1_RX2_GT) - { - /* Set Rx Front End gain[5:0] */ - addrArray[addrIndex++] = rx2FEGainAddr; - dataArray[dataIndex++] = gainTablePtr[tableRowIndex]; - - /* Set external control [5:0] */ - addrArray[addrIndex++] = rx2ExtCtlAddr; - dataArray[dataIndex++] = gainTablePtr[tableRowIndex + 1]; - - /* Set digital attenuation/gain[6:0] */ - addrArray[addrIndex++] = rx2DigGainAttenAddr; - dataArray[dataIndex++] = ((uint8_t)(gainTablePtr[tableRowIndex + 3] << 7) | gainTablePtr[tableRowIndex + 2]); - } - - /* setting the write enable depending on rxChannel choice */ - if (rxChannel == ORX_GT) - { - addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ch3CtlReg | 0x02); - addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ctlReg | 0x02); - } - else if (rxChannel == SNRX_GT) - { - addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ch3CtlReg | 0x01); - addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ctlReg | 0x02); - } - else if (rxChannel == LOOPBACK_GT) - { - addrArray[addrIndex++] = MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ch3CtlReg | 0x04); - addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ctlReg | 0x02); - } - else - { - addrArray[addrIndex++] = MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION; - dataArray[dataIndex++] = (ctlReg | 0x02); - } - - if (addrIndex >= spiBufferSize) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); - dataIndex = 0; - addrIndex = 0; - } - } - - if (addrIndex > 0) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &dataArray[0], addrIndex); - } - -#endif - - /* clearing the channel 3 gain table configuration register if selected and stopping the gain table clock */ - if (rxChannel > RX1_RX2_GT) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION, 0x00); - } - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION, 0x08); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the Rx1 Manual Gain Index - * - * If the value passed in the gainIndex parameter is within range of the gain table minimum and - * maximum indexes, the Rx1 gain index will be updated in the device data structure - * and written to the transceiver. Else, an error will be returned. The maximum index is 255 - * and the minimum index is application specific. - * - * Dependencies - * - device->spiSettings - * - device->rxSettings->rxGainControl->rx1GainIndex - * - device->rxSettings->rxGainControl->rx1MaxGainIndex - * - device->rxSettings->rxGainControl->rx1MinGainIndex - * - * \param device Pointer to the Mykonos data structure - * \param gainIndex Desired Rx1 gain index - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_setRx1ManualGain(mykonosDevice_t *device, uint8_t gainIndex) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1ManualGain()\n"); -#endif - - if ((gainIndex < device->rx->rxGainCtrl->rx1MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM)); - return MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM; - - } - else - { - /* If the desired gain index is in range of the gain table, update the - * value in the device data structure, and write to device. - */ - device->rx->rxGainCtrl->rx1GainIndex = gainIndex; - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_1, gainIndex); - - return MYKONOS_ERR_OK; - } -} - -/** - * \brief Sets the Rx2 Manual Gain index - * - * If the value passed in the gainIndex parameter is within range of the gain table minimum and - * maximum indexes, the Rx2 gain index will be updated in the device data structure - * and written to the transceiver. Else, an error will be returned. The maximum index is 255 - * and the minimum index is application specific. - * - * Dependencies - * - device->spiSettings - * - device->rxTxSettings->rxGainControl->rx2GainIndex - * - device->rxTxSettings->rxGainControl->rx2MaxGainIndex - * - device->rxTxSettings->rxGainControl->rx2MinGainIndex - * - * \param device Pointer to the Mykonos data structure - * \param gainIndex Desired Rx2 gain index - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_setRx2ManualGain(mykonosDevice_t *device, uint8_t gainIndex) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2ManualGain()\n"); -#endif - - if ((gainIndex < device->rx->rxGainCtrl->rx2MinGainIndex) || (gainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM)); - return MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM; - - } - else - { - /* If the desired gain index is in range of the gain table, update the - * value in the device data structure, and write to device. - */ - device->rx->rxGainCtrl->rx2GainIndex = gainIndex; - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_2, gainIndex); - - return MYKONOS_ERR_OK; - } -} - -/** - * \brief Reads the Rx1 Gain Index for Manual or AGC gain control mode - * - * This function reads the Rx1 gain index for manual or AGC modes. If the - * *rx1GainIndex pointer is nonzero, the read back gain index will - * be returned in the parameter. If the *rx1GainIndex pointer - * is NULL, the device data structure will be updated with the new read back value - * - * Dependencies - * - device->spiSettings - * - device->rxTxSettings->rxGainControl->rx1GainIndex - * - * \param device Pointer to the Mykonos data structure - * \param rx1GainIndex uint8_t Pointer to the Rx1 gain index value - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_getRx1Gain(mykonosDevice_t *device, uint8_t *rx1GainIndex) -{ - uint8_t readData = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1Gain()\n"); -#endif - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_1, &readData); - - /* - * If rx1GainIndex address is not NULL, return the Rx1 gain index in the - * rx1GainIndex function parameter - */ - if (rx1GainIndex != NULL) - { - *rx1GainIndex = readData; - } - - /* - * set the current Rx1 gain in the device data structure - */ - if (device->profilesValid & RX_PROFILE_VALID) - { - device->rx->rxGainCtrl->rx1GainIndex = readData; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the Rx2 Gain Index for Manual or AGC gain control mode - * - * This function reads the Rx2 gain index for manual or AGC modes. If the - * *rx1GainIndex pointer is nonzero, the read back gain index will - * be returned in the parameter. If the *rx1GainIndex pointer - * is NULL, the device data structure will be updated with the new read back value - * - * Dependencies - * - device->spiSettings - * - device->rxTxSettings->rxGainControl->rx2GainIndex - * - * \param device Pointer to the Mykonos data structure - * \param rx2GainIndex Desired Rx2 gain index - * - * \return Returns enum MYKONOS_ERR, MYKONOS_ERR_OK=pass, !MYKONOS_ERR_OK=fail - */ -mykonosErr_t MYKONOS_getRx2Gain(mykonosDevice_t *device, uint8_t *rx2GainIndex) -{ - uint8_t readData = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2Gain()\n"); -#endif - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_CHANNEL_2, &readData); - - /* - * If rx1GainIndex address is not NULL, return the Rx1 gain index in the - * rx1GainIndex function parameter - */ - if (rx2GainIndex != NULL) - { - *rx2GainIndex = readData; - } - - /* - * set the current Rx2 gain in the device data structure - */ - if (device->profilesValid & RX_PROFILE_VALID) - { - device->rx->rxGainCtrl->rx2GainIndex = readData; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the device Rx Automatic Gain Control (AGC) registers. - * - * Three data structures (mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t) - * must be instantiated prior to calling this function. Valid ranges for data structure members - * must also be provided. - * - * - * Dependencies: - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->rx->rxAgcCtrl->agcRx1MaxGainIndex - * - device->rx->rxAgcCtrl->agcRx1MinGainIndex - * - device->rx->rxAgcCtrl->agcRx2MaxGainIndex - * - device->rx->rxAgcCtrl->agcRx2MinGainIndex - * - device->rx->rxAgcCtrl->agcObsRxMaxGainIndex - * - device->rx->rxAgcCtrl->agcObsRxMinGainIndex - * - device->rx->rxAgcCtrl->agcObsRxSelect - * - device->rx->rxAgcCtrl->agcPeakThresholdMode - * - device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease - * - device->rx->rxAgcCtrl->agcGainUpdateCounter - * - device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay - * - device->rx->rxAgcCtrl->agcPeakWaitTime - * - device->rx->rxAgcCtrl->agcResetOnRxEnable - * - device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter - * - device->rx->rxAgcCtrl->peakAgc->apdHighThresh - * - device->rx->rxAgcCtrl->peakAgc->apdLowThresh - * - device->rx->rxAgcCtrl->peakAgc->hb2HighThresh - * - device->rx->rxAgcCtrl->peakAgc->hb2LowThresh - * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh - * - device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt - * - device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt - * - device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt - * - device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt - * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt - * - device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack - * - device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery - * - device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack - * - device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery - * - device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery - * - device->rx->rxAgcCtrl->peakAgc->apdFastAttack - * - device->rx->rxAgcCtrl->peakAgc->hb2FastAttack - * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable - * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt - * - device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt - * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh - * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh - * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh - * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh - * - device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack - * - device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack - * - device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery - * - device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery - * - device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration - * - device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig - * - * \param device is structure pointer to the Mykonos data structure containing settings - * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer - * to ensure it has been initialized. If not an error is thrown. - * - * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail - * \retval MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY - * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION - * \retval MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG - * \retval MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC - * \retval MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE - * \retval MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE - * \retval MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE - * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT - * \retval MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT - */ -mykonosErr_t MYKONOS_setupRxAgc(mykonosDevice_t *device) -{ - uint8_t decPowerConfig = 0; - uint8_t lower1ThreshGainStepRegValue = 0; - uint8_t powerThresholdsRegValue = 0; - uint8_t hb2OvldCfgRegValue = 0; - uint8_t agcGainUpdateCtr[3] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgc()\n"); -#endif - - /* Check mykonosAgcCfg_t device->rx->rxAgcCtrl pointer for initialization */ - if (device->rx->rxAgcCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT; - } - - /* Check mykonosPeakDetAgcCfg_t device->rx->rxAgcCtrl->peakAgc pointer for initialization */ - if (device->rx->rxAgcCtrl->peakAgc == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT; - } - - /* Check mykonosPowerMeasAgcCfg_t device->rx->rxAgcCtrl->powerAgc pointer for initialization */ - if (device->rx->rxAgcCtrl->powerAgc == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT; - } - - /* Range check agcRx1MaxGainIndex versus gain table limits */ - if ((device->rx->rxAgcCtrl->agcRx1MaxGainIndex > device->rx->rxGainCtrl->rx1MaxGainIndex) - || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex)) - - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MaxGainIndex); - } - - /* Range check agcRx1MinGainIndex versus gain table limits */ - if ((device->rx->rxAgcCtrl->agcRx1MinGainIndex < device->rx->rxGainCtrl->rx1MinGainIndex) - || (device->rx->rxAgcCtrl->agcRx1MaxGainIndex < device->rx->rxAgcCtrl->agcRx1MinGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx1MinGainIndex); - } - - /* Range check agcRx2MaxGainIndex versus gain table limits */ - if ((device->rx->rxAgcCtrl->agcRx2MaxGainIndex > device->rx->rxGainCtrl->rx2MaxGainIndex) - || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MaxGainIndex); - } - - /* Range check agcRx2MinGainIndex versus gain table limits */ - if ((device->rx->rxAgcCtrl->agcRx2MinGainIndex < device->rx->rxGainCtrl->rx2MinGainIndex) - || (device->rx->rxAgcCtrl->agcRx2MaxGainIndex < device->rx->rxAgcCtrl->agcRx2MinGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, device->rx->rxAgcCtrl->agcRx2MinGainIndex); - } - - /* Range check for agcGainUpdateCounter (22-bit) */ - if ((device->rx->rxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) || (device->rx->rxAgcCtrl->agcGainUpdateCounter < 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM)); - return MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM; - } - else - { - /* Split agcGainUpdateCounter into three values */ - agcGainUpdateCtr[0] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter); - agcGainUpdateCtr[1] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 8); - agcGainUpdateCtr[2] = (uint8_t)(device->rx->rxAgcCtrl->agcGainUpdateCounter >> 16); - - /* Write two bytes directly due. Third word has its upper two bits masked off. */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_1, agcGainUpdateCtr[0]); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_2, agcGainUpdateCtr[1]); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, agcGainUpdateCtr[2], 0x3F, 0); - } - - /* Range check on agcPeakWaitTime (5-bit) */ - if (device->rx->rxAgcCtrl->agcPeakWaitTime > 0x1F || device->rx->rxAgcCtrl->agcPeakWaitTime < 0x02) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM)); - return MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM; - } - else - { - /* Write agcPeakWaitTime */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, device->rx->rxAgcCtrl->agcPeakWaitTime, 0x1F, 0); - } - - /* Set MYKONOS_ADDR_AGC_CFG_2 bits [6:5] = b11 to enable AGC counters for MGC mode - needed for ARM cals to work correctly */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 3, 0x60, 5); - - /* Range check for agcSlowLoopSettlingDelay (7-bit) */ - if (device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY)); - return MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY; - } - else - { - /* Write agcSlowLoopSettlingDelay */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0); - } - - /* Range check for pmdMeasDuration */ - if ((uint32_t)(1 << (3 + device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->rx->rxAgcCtrl->agcGainUpdateCounter)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION)); - return MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION; - } - else - { - /* Write pmdMeasDuration */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_2, device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0); - } - - /* Range check for pmdMeasConfig */ - if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig > 0x3) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG)); - return MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG; - } - else - { - if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 0) - { - decPowerConfig = 0x0; /* Dec Pwr measurement disable */ - } - else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 1) - { - decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */ - } - else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 2) - { - decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */ - } - else if (device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig == 3) - { - decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */ - } - /* Write pmdMeasConfig */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_DEC_POWER_CONFIG_1, decPowerConfig); - } - - /* Range check agcLowThsPreventGainIncrease (1-bit) */ - if (device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC)); - return MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC; - } - else - { - /* Write agcLowThsPreventGainIncrease */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7); - } - - /* Range check agcPeakThresholdMode (1-bit), */ - if (device->rx->rxAgcCtrl->agcPeakThresholdMode > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE)); - return MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE; - } - else - { - /* Save to lower1ThreshGainStepRegValue register variable */ - lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->agcPeakThresholdMode << 5); - } - - /* Range check agcResetOnRxEnable (1-bit) */ - if (device->rx->rxAgcCtrl->agcResetOnRxEnable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC)); - return MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE; - } - else - { - /* Write agcResetOnRxEnable */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3, (uint8_t)(device->rx->rxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0); - } - - /* Range check agcEnableSyncPulseForGainCounter (1-bit) */ - if (device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER)); - return MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER; - } - else - { - /* Write agcEnableSyncPulseForGainCounter */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, (uint8_t)(device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0); - } - - /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */ - - /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */ - if ((device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh) - || device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH)); - return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH; - } - else - { - /* Write pmdLowerHighThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0); - } - - /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */ - if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH)); - return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH; - } - else - { - /* Write pmdUpperLowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_LOCK_LEVEL, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh); - } - - /* Range check pmdLowerLowThresh (4-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH)); - return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH; - } - else - { - /* Write pmdUpperLowThresh to temp variable */ - powerThresholdsRegValue |= device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh; - } - - /* Range check pmdUpperHighThresh (4-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH)); - return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH; - } - else - { - /* Write pmdUpperHighThresh to temp var, then to register */ - powerThresholdsRegValue |= (uint8_t)(device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh << 4); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_POWER_THRSH, powerThresholdsRegValue); - } - - /* Range check pmdUpperHighGainStepAttack (5-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP; - } - else - { - /* Write pmdUpperHighGainStepAttack */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER1_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0); - } - - /* Range check pmdLowerLowGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - lower1ThreshGainStepRegValue |= (device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery); - } - - /* Range check pmdUpperLowGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_UPPER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack); - } - - /* Range check pmdLowerHighGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER0_THRSH_GAIN_STEP, device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery); - } - - /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */ - - /* Range check apdFastAttack and hb2FastAttack (1-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->apdFastAttack > 0x1 || device->rx->rxAgcCtrl->peakAgc->hb2FastAttack > 0x1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE)); - return MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->apdFastAttack << 7); - lower1ThreshGainStepRegValue |= (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2FastAttack << 6); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue); - } - - /* Range check apdHighThresh */ - if ((device->rx->rxAgcCtrl->peakAgc->apdHighThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh <= device->rx->rxAgcCtrl->peakAgc->apdLowThresh)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM; - } - else - { - /* Write apdHighThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ULB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0); - } - - /* Range check apdLowThresh */ - if ((device->rx->rxAgcCtrl->peakAgc->apdLowThresh > 0x3F) || (device->rx->rxAgcCtrl->peakAgc->apdHighThresh < device->rx->rxAgcCtrl->peakAgc->apdLowThresh)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM; - } - else - { - /* write apdLowThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_LLB_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0); - } - - /* Range check hb2HighThresh */ - if (device->rx->rxAgcCtrl->peakAgc->hb2HighThresh < device->rx->rxAgcCtrl->peakAgc->hb2LowThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM; - } - else - { - /* write hb2HighThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThresh); - } - - /* Range check hb2LowThresh */ - if (device->rx->rxAgcCtrl->peakAgc->hb2LowThresh > device->rx->rxAgcCtrl->peakAgc->hb2HighThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM; - } - else - { - /* write hb2LowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThresh); - } - - /* Range check hb2VeryLowThresh */ - if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh > device->rx->rxAgcCtrl->peakAgc->hb2LowThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM; - } - else - { - /* write hb2VeryLowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_VERYLOW_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh); - } - - /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ULB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdHighThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LLB_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->apdLowThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_HIGH_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2HighThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2LowThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_VERYLOW_OVRG_CNT_THRSH, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt); - - /* Range check on apdHighGainStepAttack (5-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM; - } - else - { - /* Write apdHighGainStepAttack */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_1, device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack); - } - - /* Range check on apdLowGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM; - } - else - { - /* Write apdLowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_4, device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery); - } - - /* Range check on hb2HighGainStepAttack (5-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM; - } - else - { - /* Write hb2HighGainStepAttack */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_2, device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack); - } - - /* Range check on hb2LowGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM; - } - else - { - /* Write hb2LowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_5, device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery); - } - - /* Range check on hb2VeryLowGainStepRecovery (5-bit) */ - if (device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM; - } - else - { - /* Write hb2VeryLowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_6, device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery); - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE)); - return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE; - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT)); - return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT; - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT)); - return MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT; - } - else - { - /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */ - hb2OvldCfgRegValue = (device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt) |(uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4) - | (uint8_t)(device->rx->rxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue); - } - - /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OVRLD_ADC_OVRLD_CFG, 0x18); - /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX_BLOCK_DET_DECAY, 0x0); - - /* performing a soft reset */ - return MYKONOS_resetRxAgc(device); -} - -/** - * \brief This function resets the AGC state machine - * - * Calling this function resets all state machines within the gain control and maximum gain. - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_resetRxAgc(mykonosDevice_t *device) -{ - const uint8_t AGC_RESET = 0x80; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetRxAgc()\n"); -#endif - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 1, AGC_RESET, 7); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_CFG_2, 0, AGC_RESET, 7); - - return MYKONOS_ERR_OK; - -} - -/** - * \brief This function sets the min/max gain indexes for AGC in the main RX channel - * - * Allows to change min/max gain index on runtime. - * If RX1_RX2 selected, then the maxGainIndex/minGainIndex value will be applied to both channels. - * If only Rx1 selected, then only Rx1 min/max gain indices will be updated, along with their device data structure values. - * If only Rx2 selected, then only Rx2 min/max gain indices will be updated, along with their device data structure values. - * - * Dependencies: - * - device->spiSettings - * - device->rx->rxAgcCtrl - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param rxChannelSelect RX channel for setting the max and min gain index settings - * \param maxGainIndex Max gain index setting - * \param minGainIndex Min gain index setting - * - * \retval MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table. - * \retval MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table. - * \retval MYKONOS_ERR_AGC_MIN_MAX_CHANNEL Wrong RX channel selected - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosRxChannels_t rxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex) -{ - const uint8_t MIN_GAIN_INDEX = 1 + MAX_GAIN_TABLE_INDEX - (sizeof(RxGainTable) / sizeof(RxGainTable[0])); - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxAgcMinMaxGainIndex()\n"); -#endif - - /* Check for maxGainIndex */ - if (maxGainIndex > MAX_GAIN_TABLE_INDEX) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX)); - return MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX; - } - - /* Check for minGainIndex */ - if (minGainIndex < MIN_GAIN_INDEX) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX)); - return MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX; - } - - if ((uint32_t)rxChannelSelect & (uint32_t)RX1) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX, maxGainIndex); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX, minGainIndex); - device->rx->rxAgcCtrl->agcRx1MaxGainIndex = maxGainIndex; - device->rx->rxAgcCtrl->agcRx1MinGainIndex = minGainIndex; - } - - if ((uint32_t)rxChannelSelect & (uint32_t)RX2) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX, maxGainIndex); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX, minGainIndex); - device->rx->rxAgcCtrl->agcRx2MaxGainIndex = maxGainIndex; - device->rx->rxAgcCtrl->agcRx2MinGainIndex = minGainIndex; - } - - /* Check for invalid Rx channel */ - if (!((uint32_t)rxChannelSelect & (uint32_t)RX1_RX2)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL)); - return MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function sets the min/max gain indexes for AGC in the observation channel - * - * Allows to change min/max gain index on runtime. - * - * Dependencies: - * - device->spiSettings - * - device->rx->rxAgcCtrl - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param obsRxChannelSelect Observation channel for setting the max and min gain index settings - * \param maxGainIndex Max gain index setting - * \param minGainIndex Min gain index setting - * - * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL Wrong read back channel. - * \retval MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX Max gain index bigger than max gain index loaded table. - * \retval MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX Min gain index lower than min gain index loaded table. - * \retval MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL Wrong observation channel selected - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex) -{ - uint8_t rdObsActive = 0x00; - uint8_t obsActive = 0x00; - uint8_t obsCheck = 0x00; - uint8_t minGainIndexCheck = 0x00; - uint8_t maxGainIndexCheck = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxAgcMinMaxGainIndex()\n"); -#endif - - /* Read active channel */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, &rdObsActive, 0x03, 0); - - /* Check active channel and set min/max checks */ - switch (rdObsActive) - { - case 0x00: - case 0x01: - /*sniffer*/ - maxGainIndexCheck = MAX_GAIN_TABLE_INDEX; - minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(SnRxGainTable) / sizeof(SnRxGainTable[0])); - obsActive = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C; - break; - case 0x02: - case 0x03: - /*observation 1*/ - maxGainIndexCheck = MAX_GAIN_TABLE_INDEX; - minGainIndexCheck = MAX_GAIN_TABLE_INDEX - (sizeof(ORxGainTable) / sizeof(ORxGainTable[0])); - obsActive = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL)); - return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL; - } - - /* Check for maxGainIndex */ - if ((maxGainIndex > maxGainIndexCheck) || (maxGainIndex < minGainIndexCheck)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX)); - return MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX; - } - - /* Check for minGainIndex */ - if ((minGainIndex < minGainIndexCheck) || (minGainIndex > maxGainIndexCheck)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX)); - return MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX; - } - - device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex = maxGainIndex; - device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex = minGainIndex; - - switch (obsRxChannelSelect) - { - case OBS_SNIFFER: - case OBS_SNIFFER_A: - case OBS_SNIFFER_B: - case OBS_SNIFFER_C: - obsCheck = (uint32_t)OBS_SNIFFER | (uint32_t)OBS_SNIFFER_A | (uint32_t)OBS_SNIFFER_B | (uint32_t)OBS_SNIFFER_C; - maxGainIndex = maxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES; - minGainIndex = minGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES; - break; - - case OBS_RX1_TXLO: - case OBS_RX2_TXLO: - case OBS_RX1_SNIFFERLO: - case OBS_RX2_SNIFFERLO: - obsCheck = (uint32_t)OBS_RX1_TXLO | (uint32_t)OBS_RX1_SNIFFERLO | (uint32_t)OBS_RX2_TXLO | (uint32_t)OBS_RX2_SNIFFERLO; - maxGainIndex = maxGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES; - minGainIndex = minGainIndex - MAX_ORX_GAIN_TABLE_NUMINDEXES; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL)); - return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL; - } - - if (obsCheck == obsActive) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX, maxGainIndex); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX, minGainIndex); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL)); - return MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function sets the Temperature gain compensation for Rx1 channel - * - * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain - * in the data path. - * The resolution of the temperature compensation gain is 250mdB. - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param rx1TempCompGain_mdB gain compensation for Rx1, the range is from -3000mdB to +3000mdB in steps of 250mdB - * - * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) - * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setRx1TempGainComp(mykonosDevice_t *device, int16_t rx1TempCompGain_mdB) -{ - int8_t tempGainComp = 0x00; - - const int16_t LOW_LIMIT_GAIN_COMP = -3000; - const int16_t HIGH_LIMIT_GAIN_COMP = 3000; - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx1TempGainComp()\n"); -#endif - - /* Check for Gain compensation range */ - if ((rx1TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx1TempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE)); - return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE; - } - - /* Check for Gain compensation steps */ - if (rx1TempCompGain_mdB % GAIN_COMP_STEP) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP, - getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP)); - return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP; - } - - /* Prepare register write */ - tempGainComp = (rx1TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, (uint8_t)tempGainComp); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function gets the Temperature gain compensation for Rx1 - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param rx1TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx1 channel. - * - * \retval MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL rx1TempCompGain_mdB pointer is null. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRx1TempGainComp(mykonosDevice_t *device, int16_t *rx1TempCompGain_mdB) -{ - uint8_t tempGainComp = 0x00; - int8_t tempGainCompDB = 0x00; - - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1TempGainComp()\n"); -#endif - - /* Check for null passed parameter */ - if (rx1TempCompGain_mdB == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL, - getMykonosErrorMessage(MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL)); - return MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL; - } - - /* Read Temperature Gain Compensation */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX1_TEMP_GAIN_COMP, &tempGainComp); - - /* Convert to dB and prepare the signed return */ - tempGainCompDB = tempGainComp & 0x1F; - if (tempGainCompDB & 0x10) - { - tempGainCompDB = ((((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1)); - } - - /* Assign value to the passed pointer */ - *rx1TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function sets the Temperature gain compensation for Rx2 channel - * - * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain - * in the data path. - * The resolution of the temperature compensation gain is 250mdB. - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param rx2TempCompGain_mdB gain compensation for Rx1, - * the range is from -3000mdB to +3000mdB in steps of 250mdB - * - * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) - * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setRx2TempGainComp(mykonosDevice_t *device, int16_t rx2TempCompGain_mdB) -{ - int8_t tempGainComp = 0x00; - - const int16_t LOW_LIMIT_GAIN_COMP = -3000; - const int16_t HIGH_LIMIT_GAIN_COMP = 3000; - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRx2TempGainComp()\n"); -#endif - - /* Check for Gain compensation range */ - if ((rx2TempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (rx2TempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE)); - return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE; - } - - /* Check for Gain compensation range */ - if (rx2TempCompGain_mdB % GAIN_COMP_STEP) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP, - getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP)); - return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP; - } - - /* Prepare register write */ - tempGainComp = (rx2TempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, (uint8_t)tempGainComp); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function gets the Temperature gain compensation for Rx2 - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param rx2TempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for Rx2 channel. - * - * \retval MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL rx2TempCompGain_mdB pointer is null. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRx2TempGainComp(mykonosDevice_t *device, int16_t *rx2TempCompGain_mdB) -{ - uint8_t tempGainComp = 0x00; - int8_t tempGainCompDB = 0x00; - - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2TempGainComp()\n"); -#endif - - /* Check for null passed parameter */ - if (rx2TempCompGain_mdB == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL, - getMykonosErrorMessage(MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL)); - return MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL; - } - - /* Read programmed Temperature Gain Compensation */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX2_TEMP_GAIN_COMP, &tempGainComp); - - /* Convert to dB and prepare the signed return */ - tempGainCompDB = tempGainComp & 0x1F; - if (tempGainCompDB & 0x10) - { - tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1); - } - - /* Assign value to the passed pointer */ - *rx2TempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function sets the Temperature gain compensation for the observation channel - * - * The temperature gain compensation control allow for a +3000mdB to -3000mdB digital gain - * in the data path. - * The resolution of the temperature compensation gain is 250mdB. - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param obsRxTempCompGain_mdB gain compensation for observation channel, - * the range is from -3000mdB to +3000mdB in steps of 250mdB - * - * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE The temp gain compensation is outside range (-3000mdB to 3000mdB) - * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP Not valid temp gain compensation, step size is 250mdB - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setObsRxTempGainComp(mykonosDevice_t *device, int16_t obsRxTempCompGain_mdB) -{ - int8_t tempGainComp = 0x00; - - const int16_t LOW_LIMIT_GAIN_COMP = -3000; - const int16_t HIGH_LIMIT_GAIN_COMP = 3000; - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxTempGainComp()\n"); -#endif - - /* Check for Gain compensation range */ - if ((obsRxTempCompGain_mdB > HIGH_LIMIT_GAIN_COMP) || (obsRxTempCompGain_mdB < LOW_LIMIT_GAIN_COMP)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE)); - return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE; - } - - /* Check for Gain compensation range */ - if (obsRxTempCompGain_mdB % GAIN_COMP_STEP) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP, - getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP)); - return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP; - } - - /* Prepare register write */ - tempGainComp = (obsRxTempCompGain_mdB / GAIN_COMP_STEP) & 0x1F; - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, (uint8_t)tempGainComp); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function gets the Temperature gain compensation for the observation channel - * - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param obsRxTempCompGain_mdB Which will be populated with the Temperature Gain Compensation in mdB value for the observation channel. - * - * \retval MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL obsRxTempCompGain_mdB pointer is null. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getObsRxTempGainComp(mykonosDevice_t *device, int16_t *obsRxTempCompGain_mdB) -{ - uint8_t tempGainComp = 0x00; - int8_t tempGainCompDB = 0x00; - - const int16_t GAIN_COMP_STEP = 250; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxTempGainComp()\n"); -#endif - - /* Check for null passed parameter */ - if (obsRxTempCompGain_mdB == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL, - getMykonosErrorMessage(MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL)); - return MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_TEMP_GAIN_COMP, &tempGainComp); - - /* Convert to dB and prepare the signed return */ - tempGainCompDB = tempGainComp & 0x1F; - if (tempGainCompDB & 0x10) - { - tempGainCompDB = (((~((uint8_t)tempGainCompDB)) & 0x0F) + 1) * (-1); - } - - /* Assign value to the passed pointer */ - *obsRxTempCompGain_mdB = tempGainCompDB * GAIN_COMP_STEP; - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables or disables the Rx slow loop gain counter to use the sync pulse - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param enable is a uint8_t data type where '0' = disable Rx gain counter from using sync pulse, '1' = enable Rx gain. All other values will throw an error. - * counter to use the sync pulse. This value is written back to the device data structure for storage. - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable) -{ - const uint8_t syncPulseBitMask = 0x80; - uint8_t enableBit = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainCtrSyncPulse()\n"); -#endif - - /* read, modify, write Rx gain counter sync pulse enable bit */ - enableBit = (enable > 0) ? 1 : 0; - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_LOOP_CFG, enableBit, syncPulseBitMask, 7); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Configures the Rx gain control mode - * - * Dependencies: - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->rx->rxGainCtrl->gainMode - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param mode is a mykonosGainMode_t enumerated gain control mode type where: - * Manual Gain = MGC, Automatic Gain Control = AGC, and hybrid mode = HYBRID - * - * When the mode enumerated type is passed, the Rx1 and Rx2 gain mode is set to this value and the - * Rx gainMode structure member is updated with the new value - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_INV_RX_GAIN_MODE_PARM Invalid AGC mode pass in function mode paramter - */ -mykonosErr_t MYKONOS_setRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode) -{ - uint8_t rxGainCfgReg = 0; - - const uint8_t RX_GAIN_TYPE_MASK = 0x1F; - const uint8_t RX_GAIN_HYBRID_MASK = 0x10; - const uint8_t RX_GAIN_TYPE_SHIFT = 0x02; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxGainControlMode()\n"); -#endif - - /* read AGC type for Rx1 and Rx2 for modify, write */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, &rxGainCfgReg); - rxGainCfgReg &= ~RX_GAIN_TYPE_MASK; - - /* performing AGC type check */ - switch (mode) - { - case MGC: - rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK; - break; - case AGC: - rxGainCfgReg &= ~RX_GAIN_HYBRID_MASK; - break; - case HYBRID: - rxGainCfgReg |= RX_GAIN_HYBRID_MASK; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RX_GAIN_MODE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_RX_GAIN_MODE_PARM)); - return MYKONOS_ERR_INV_RX_GAIN_MODE_PARM; - } - - /* modify, write AGC type for Rx1 and Rx2 */ - rxGainCfgReg |= (uint8_t)mode; - rxGainCfgReg |= (uint8_t)((uint8_t)mode << RX_GAIN_TYPE_SHIFT); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_CFG_1, rxGainCfgReg); - - /* writing mode setting to data structure */ - if ((device->profilesValid & RX_PROFILE_VALID) > 0) - { - device->rx->rxGainCtrl->gainMode = mode; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs a power measurement in the Rx1 digital data path. - * - * Due to interdependencies between the AGC and power measurement the power measurement duration and - * where the measurement is taken is variable. - * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig - * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate, - * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. - * If the receiver is disabled during the power measurement, this function returns a 0 value for rx1DecPower_mdBFS - * - * The resolution of this function is 0.25dB. - * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. - * - * Dependencies - * - device->spiSettings - * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig - * - device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration - * - * \param device Pointer to the Mykonos data structure - * \param rx1DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRx1DecPower(mykonosDevice_t *device, uint16_t *rx1DecPower_mdBFS) -{ - uint8_t rx1DecPower_dBFS = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx1DecPower()\n"); -#endif - - /* read Rx1 Dec Power Measurement */ - if (rx1DecPower_mdBFS != NULL) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_CH1_DECIMATED_PWR, &rx1DecPower_dBFS); - *rx1DecPower_mdBFS = (uint16_t)(rx1DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM)); - return MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs a power measurement in the Rx2 digital data path. - * - * Due to interdependencies between the AGC and power measurement the power measurement duration and - * where the measurement is taken is variable. - * The location of the power measurement is given by device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasConfig - * The number of samples the power measurement uses is given by 8*2^(device->rx->rxAgcCtrl->rxPwrAgc->pmdMeasDuration) at the IQ rate, - * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. - * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS - * - * The resolution of this function is 0.25dB. - * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. - * - * Dependencies - * - device->spiSettings - * - * \param device Pointer to the Mykonos data structure - * \param rx2DecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRx2DecPower(mykonosDevice_t *device, uint16_t *rx2DecPower_mdBFS) -{ - uint8_t rx2DecPower_dBFS = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRx2DecPower()\n"); -#endif - - /* read Rx2 Dec Power Measurement */ - if (rx2DecPower_mdBFS != NULL) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_CH2_DECIMATED_PWR, &rx2DecPower_dBFS); - *rx2DecPower_mdBFS = (uint16_t)(rx2DecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM)); - return MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM; - } - - return MYKONOS_ERR_OK; -} - -/* - ***************************************************************************** - * Observation Rx Data path functions - ***************************************************************************** - */ - -/** - * \brief Sets the default Obs Rx channel to enter when device moves from - * radioOff to radioOn - * - * By default, the observation receiver remains powered down when the device - * moves into the radioOn state. If the BBIC prefers a particular ObsRx - * channel to be enabled, this function can be called in radioOff to set - * the default channel to power up when the device moves to radioOn. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->obsRx->defaultObsRxChannel - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param defaultObsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT Observation profile not valid, device->obsRx structure is NULL - * \retval MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT Invalid defaultObsRxCh function parameter - */ -mykonosErr_t MYKONOS_setDefaultObsRxPath(mykonosDevice_t *device, mykonosObsRxChannels_t defaultObsRxCh) -{ - uint8_t orxEntryMode[1] = {0}; - uint16_t byteOffset = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDefaultObsRxPath()\n"); -#endif - - if (device->obsRx == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT, - getMykonosErrorMessage(MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT)); - return MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT; - } - - if (((defaultObsRxCh > OBS_RX2_SNIFFERLO) && (defaultObsRxCh != OBS_SNIFFER_A) && (defaultObsRxCh != OBS_SNIFFER_B) && (defaultObsRxCh != OBS_SNIFFER_C))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM)); - return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM; - } - - device->obsRx->defaultObsRxChannel = defaultObsRxCh; - orxEntryMode[0] = ((uint8_t)device->obsRx->defaultObsRxChannel & 0xFF); - - byteOffset = 6; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_RADIO_CONTROL, byteOffset, &orxEntryMode[0], 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Powers up or down the Observation Rx signal chain in the radioOn state - * - * When the ARM radio control is in ARM command mode, this - * function allows the user to selectively power up or down the desired ObsRx - * data path. If this function is called when the ARM is expecting GPIO pin - * control of the ObsRx path source, an error will be returned. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxCh is mykonosObsRxChannels_t enum type which selects the desired observation receive path to power up - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM Invalid obsRxCh function parameter - * \retval MYKONOS_ERR_PU_OBSRXPATH_ARMERROR ARM returned an error while trying to set the ObsRx Path source - */ -mykonosErr_t MYKONOS_setObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh) -{ - uint8_t cmdStatByte = 0; - uint32_t timeoutMs = 0; - uint8_t payload[2] = {0, 0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxPathSource()\n"); -#endif - - if (((obsRxCh > OBS_RX2_SNIFFERLO) && (obsRxCh != OBS_SNIFFER_A) && (obsRxCh != OBS_SNIFFER_B) && (obsRxCh != OBS_SNIFFER_C))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM)); - return MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM; - } - - payload[0] = MYKONOS_ARM_OBJECTID_ORX_MODE; - payload[1] = (uint8_t)(obsRxCh); - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &payload[0], sizeof(payload)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; /* wait max of 1sec for command to complete */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR)); - return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR; - } - - return retVal; - } - - /* Verify ARM command did not return an error */ - if (cmdStatByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_PU_OBSRXPATH_ARMERROR)); - return MYKONOS_ERR_PU_OBSRXPATH_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads back the currently enabled Observation Rx channel in the - * radioOn state - * - * In pin mode, the pin could change asynchronous to reading back the - * current enable ObsRx path. Calling this function while in radioOff will - * return OBS_RXOFF since all radio channels are powered down. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxCh Parameter to return enum of the current observation receive - * path powered up - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR ARM returned an error while trying to get the ObsRx Path source - */ -mykonosErr_t MYKONOS_getObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t *obsRxCh) -{ - uint8_t extData[1] = {MYKONOS_ARM_OBJECTID_ORX_MODE}; - uint8_t cmdStatusByte = 0; - uint8_t armData[1] = {0}; - uint32_t timeoutMs = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxPathSource()\n"); -#endif - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR)); - return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR; - } - - return retVal; - } - - /* read 64-bit frequency from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 1, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR)); - return MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR; - } - - *obsRxCh = (mykonosObsRxChannels_t)(armData[0]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the Rx gain of the ObsRx channel - * - * The ObsRx channel can have different RF inputs (ORx1/ORx2/SnRx A,B,C) - * This function sets the ObsRx gain index independently for ORx1/ORx2, or SnRx. - * SnRx A, B, and C share the same gain index. Please note that ORx1/ORx2 share a gain - * table, as does SnRx A, B, and C. The maximum index is 255 - * and the minimum index is application specific. - * - * Dependencies - * - device->spiSettings - * - device->obsRx->orxGainCtrl->maxGainIndex - * - device->obsRx->orxGainCtrl->minGainIndex - * - device->obsRx->orxGainCtrl->orx1GainIndex - * - device->obsRx->orxGainCtrl->orx2GainIndex - * - device->obsRx->snifferGainCtrl->maxGainIndex - * - device->obsRx->snifferGainCtrl->minGainIndex - * - device->obsRx->snifferGainCtrl->gainIndex - * - * \param device Pointer to the Mykonos device data structure - * \param obsRxCh is an enum type mykonosObsRxChannels_t to identify the desired RF input for gain change - * \param gainIndex Desired manual gain table index to set - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN Invalid gain requested for ORx1: outside gain table min/max index - * \retval MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN Invalid gain requested for ORx2: outside gain table min/max index - * \retval MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN Invalid gain requested for Sniffer: outside gain table min/max index - * \retval MYKONOS_ERR_SETORXGAIN_INV_CHANNEL Function parameter obsRxCh has an invalid enum value - */ -mykonosErr_t MYKONOS_setObsRxManualGain(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh, uint8_t gainIndex) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxManualGain()\n"); -#endif - - if ((obsRxCh == OBS_RX1_TXLO) || (obsRxCh == OBS_RX1_SNIFFERLO)) - { - if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX1_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX)); - device->obsRx->orxGainCtrl->orx1GainIndex = gainIndex; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN, - getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN)); - return MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN; - } - } - else if ((obsRxCh == OBS_RX2_TXLO) || (obsRxCh == OBS_RX2_SNIFFERLO)) - { - if (gainIndex <= device->obsRx->orxGainCtrl->maxGainIndex && gainIndex >= device->obsRx->orxGainCtrl->minGainIndex) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX2_MANUAL_GAIN_INDEX, (gainIndex - MIN_ORX_GAIN_TABLE_INDEX)); - device->obsRx->orxGainCtrl->orx2GainIndex = gainIndex; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN, - getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN)); - return MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN; - } - - } - else if (obsRxCh == OBS_SNIFFER_A || obsRxCh == OBS_SNIFFER_B || obsRxCh == OBS_SNIFFER_C || obsRxCh == OBS_SNIFFER) - { - if (gainIndex <= device->obsRx->snifferGainCtrl->maxGainIndex && gainIndex >= device->obsRx->snifferGainCtrl->minGainIndex) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SNRX_MANUAL_GAIN_INDEX, (gainIndex - MIN_SNRX_GAIN_TABLE_INDEX)); - device->obsRx->snifferGainCtrl->gainIndex = gainIndex; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN, - getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN)); - return MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN; - } - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETORXGAIN_INV_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SETORXGAIN_INV_CHANNEL)); - return MYKONOS_ERR_SETORXGAIN_INV_CHANNEL; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Gets the gain index of the currently enabled ObsRx channel - * - * The ObsRx data path can have multiple RF sources. This function will - * read back the gain index of the currently enabled RF source. If the ObsRx - * data path is disabled, an error is returned. If the functions uint8_t *gainIndex - * parameter is a valid pointer, the gain index is returned at the pointers - * address. Else, if the uint8_t *gainIndex pointer is NULL, the gainIndex read back - * is stored in the device data structure. - * - * NOTE: if the observation source is chosen by ORX_MODE pins, it is possible that - * the readback value will be incorrect if the obsRx channel changes while this function - * reads the gain. - * - * Dependencies - * - device->spiSettings - * - device->profilesValid - * - device->obsRx->orxGainCtrl->orx1GainIndex - * - device->obsRx->orxGainCtrl->orx2GainIndex - * - device->obsRx->snifferGainCtrl->gainIndex - * - * \param device Pointer to the Mykonos device data structure - * \param gainIndex Return value of the current gain index for the currently enabled ObsRx channel. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETORX1GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure - * \retval MYKONOS_ERR_GETORX2GAIN_INV_POINTER The ObsRx profile is not valid in the device data structure - * \retval MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER The sniffer profile is not valid in the device data structure - * \retval MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED The observation receiver is currently disabled, can not read back gain index. - */ -mykonosErr_t MYKONOS_getObsRxGain(mykonosDevice_t *device, uint8_t *gainIndex) -{ - /* Potential issue, if ARM is using loopback path when this function is called, it will likely readback loopback gain */ - uint8_t readObsRxPathEnabled = 0; - uint8_t readObsRxGain = 0; - - const uint8_t ORX1_EN = 0x01; - const uint8_t ORX2_EN = 0x02; - const uint8_t SNRX_EN = 0x04; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxGain()\n"); -#endif - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_1, &readObsRxPathEnabled); - - /* If obsRx channel enabled, then read gain index */ - if (readObsRxPathEnabled > 0) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_GAIN, &readObsRxGain); - - switch (readObsRxPathEnabled) - { - case 0x01: - readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX; - break; - case 0x02: - readObsRxGain += MIN_ORX_GAIN_TABLE_INDEX; - break; - case 0x04: - readObsRxGain += MIN_SNRX_GAIN_TABLE_INDEX; - break; - default: - break; - } - - if (gainIndex != NULL) - { - *gainIndex = readObsRxGain; - } - - /* Store the gain index in the device's gain control data structure. */ - - if (readObsRxPathEnabled == ORX1_EN) - { - /* verify valid data structure pointers */ - if (device->profilesValid & ORX_PROFILE_VALID) - { - device->obsRx->orxGainCtrl->orx1GainIndex = readObsRxGain; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX1GAIN_INV_POINTER, - getMykonosErrorMessage(MYKONOS_ERR_GETORX1GAIN_INV_POINTER)); - return MYKONOS_ERR_GETORX1GAIN_INV_POINTER; - } - - } - else if (readObsRxPathEnabled == ORX2_EN) - { - /* verify valid pointers */ - if (device->profilesValid & ORX_PROFILE_VALID) - { - device->obsRx->orxGainCtrl->orx2GainIndex = readObsRxGain; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORX2GAIN_INV_POINTER, - getMykonosErrorMessage(MYKONOS_ERR_GETORX2GAIN_INV_POINTER)); - return MYKONOS_ERR_GETORX2GAIN_INV_POINTER; - } - - } - else if (readObsRxPathEnabled == SNRX_EN) - { - /* verify valid pointers */ - if (device->profilesValid & SNIFF_PROFILE_VALID) - { - device->obsRx->snifferGainCtrl->gainIndex = readObsRxGain; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER, - getMykonosErrorMessage(MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER)); - return MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER; - } - } - else - { - /* ignore gain index for Tx loopback input into obsRx channel */ - } - } - else - { - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED, - getMykonosErrorMessage(MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED)); - return MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the device ObsRx Automatic Gain Control (AGC) registers. - * - * Three data structures (of types mykonosAgcCfg_t, mykonosPeakDetAgcCfg_t, mykonosPowerMeasAgcCfg_t) - * must be instantiated prior to calling this function. Valid ranges for data structure members - * must also be provided. - * - * - * Dependencies: - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->obsRx->orxAgcCtrl->agcRx1MaxGainIndex - * - device->obsRx->orxAgcCtrl->agcRx1MinGainIndex - * - device->obsRx->orxAgcCtrl->agcRx2MaxGainIndex - * - device->obsRx->orxAgcCtrl->agcRx2MinGainIndex - * - device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex - * - device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex - * - device->obsRx->orxAgcCtrl->agcObsRxSelect - * - device->obsRx->orxAgcCtrl->agcPeakThresholdMode - * - device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease - * - device->obsRx->orxAgcCtrl->agcGainUpdateCounter - * - device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay - * - device->obsRx->orxAgcCtrl->agcPeakWaitTime - * - device->obsRx->orxAgcCtrl->agcResetOnRxEnable - * - device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter - * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh - * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh - * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh - * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh - * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh - * - device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt - * - device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt - * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt - * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt - * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt - * - device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack - * - device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery - * - device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack - * - device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery - * - device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery - * - device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack - * - device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack - * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable - * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt - * - device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt - * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh - * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh - * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh - * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh - * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack - * - device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack - * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery - * - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery - * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration - * - device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig - * - * \param device is structure pointer to the Mykonos data structure containing settings - * The pointer to the Mykonos AGC data structure containing settings is checked for a null pointer - * to ensure it has been initialized. If not an error is thrown. - * - * \retval Returns MYKONOS_ERR=pass, !MYKONOS_ERR=fail - * \retval MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT - * \retval MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX - * \retval MYKONOS_ERR_INV_AGC_OBSRX_SELECT - * \retval MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG - * \retval MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE - * \retval MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE - * \retval MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP - * \retval MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE - * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT - * \retval MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT - */ -mykonosErr_t MYKONOS_setupObsRxAgc(mykonosDevice_t *device) -{ - /* Current configuration does not support AGC on ORx channel */ - uint8_t decPowerConfig = 0; - uint8_t lower1ThreshGainStepRegValue = 0; - uint8_t powerThresholdsRegValue = 0; - uint8_t hb2OvldCfgRegValue = 0; - uint8_t agcGainUpdateCtr[3] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupObsRxAgc()\n"); -#endif - - /* Check mykonosAgcCfg_t device->obsRx->orxAgcCtrl pointer for initialization */ - if (device->obsRx->orxAgcCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT; - } - - /* Check mykonosPeakDetAgcCfg_t device->orx->orxAgcCtrl->peakAgc pointer for initialization */ - if (device->obsRx->orxAgcCtrl->peakAgc == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT; - } - - /* Check mykonosPowerMeasAgcCfg_t device->obsRx->orxAgcCtrl->powerAgc pointer for initialization */ - if (device->obsRx->orxAgcCtrl->powerAgc == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT)); - return MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT; - } - - /* Range check agcObsRxMaxGainIndex versus gain table limits and agcObsRxMinGainIndex */ - if ((device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex > device->obsRx->snifferGainCtrl->maxGainIndex) || - (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX, - (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES)); - } - - /* Range check agcObsRxMinGainIndex versus gain table limits and agcObsRxMaxGainIndex */ - if ((device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex < device->obsRx->snifferGainCtrl->minGainIndex) || - (device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex < device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX)); - return MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX, - (device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex - MAX_SNRX_GAIN_TABLE_NUMINDEXES)); - } - - /* Range check agcObsRxSelect. Sniffer only support. Sniffer is selected if value is 0 or 1. 2 or 3 select ORx1/ORx2 respectively */ - if (device->obsRx->orxAgcCtrl->agcObsRxSelect > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SELECT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SELECT)); - return MYKONOS_ERR_INV_AGC_OBSRX_SELECT; - } - else - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE, device->obsRx->orxAgcCtrl->agcObsRxSelect); - } - - /* Range check for agcGainUpdateCounter (22-bit) */ - if ((device->obsRx->orxAgcCtrl->agcGainUpdateCounter > 0x3FFFFF) || - (device->obsRx->orxAgcCtrl->agcGainUpdateCounter < 1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM; - } - else - { - /* Split agcGainUpdateCounter into three values */ - agcGainUpdateCtr[0] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter); - agcGainUpdateCtr[1] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 8); - agcGainUpdateCtr[2] = (uint8_t)(device->obsRx->orxAgcCtrl->agcGainUpdateCounter >> 16); - - /* Write two bytes directly due. Third word has its upper two bits masked off. */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_1, agcGainUpdateCtr[0]); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_2, agcGainUpdateCtr[1]); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, agcGainUpdateCtr[2], 0x3F, 0); - } - - /* Range check on agcPeakWaitTime (5-bit) */ - if ((device->obsRx->orxAgcCtrl->agcPeakWaitTime > 0x1F) || - (device->obsRx->orxAgcCtrl->agcPeakWaitTime < 0x02)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM; - } - else - { - /* Write agcPeakWaitTime */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2, device->obsRx->orxAgcCtrl->agcPeakWaitTime, 0x1F, 0); - } - - /* Range check for agcSlowLoopSettlingDelay (7-bit) */ - if (device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY)); - return MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY; - } - else - { - /* Write agcSlowLoopSettlingDelay */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay, 0x7F, 0); - } - - /* Range check for pmdMeasDuration */ - if ((uint32_t)(1 << (3 + device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration)) >= (device->obsRx->orxAgcCtrl->agcGainUpdateCounter)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION; - } - else - { - /* Write pmdMeasDuration */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_2, device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration, 0x0F, 0); - } - - /* Range check for pmdMeasConfig */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig > 0x3) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG; - } - else - { - if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 0) - { - decPowerConfig = 0x0; /* Dec Pwr measurement disable */ - } - else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 1) - { - decPowerConfig = 0x3; /* Dec Pwr measurement enable, HB2 for decPwr measurement */ - } - else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 2) - { - decPowerConfig = 0x5; /* Dec Pwr measurement enable, RFIR for decPwr measurement */ - } - else if (device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig == 3) - { - decPowerConfig = 0x11; /* Dec Pwr measurement enable, BBDC2 for decPwr measurement */ - } - /* Write pmdMeasConfig */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_SNIFFER_DEC_POWER_CONFIG_1, decPowerConfig); - } - - /* Range check agcLowThsPreventGainIncrease (1-bit) */ - if (device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC)); - return MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC; - } - else - { - /* Write agcLowThsPreventGainIncrease */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease, 0x80, 7); - } - - /* Range check agcPeakThresholdMode (1-bit), */ - if (device->obsRx->orxAgcCtrl->agcPeakThresholdMode > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE)); - return MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE; - } - else - { - /* Save to lower1ThreshGainStepRegValue register variable */ - lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->agcPeakThresholdMode << 5); - } - - /* Range check agcResetOnRxEnable (1-bit) */ - if (device->obsRx->orxAgcCtrl->agcResetOnRxEnable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE)); - return MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE; - } - else - { - /* Write agcResetOnRxEnable */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3, (uint8_t)(device->obsRx->orxAgcCtrl->agcResetOnRxEnable << 7), 0x80, 0); - } - - /* Range check agcEnableSyncPulseForGainCounter (1-bit) */ - if (device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER)); - return MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER; - } - else - { - /* Write agcEnableSyncPulseForGainCounter */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, (uint8_t)(device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter << 7), 0x80, 0); - } - - /* WRITE REGISTERS FOR THE AGC POWER MEASUREMENT DETECTOR (PMD) STRUCTURE */ - - /* Range check pmdLowerHighThresh (7-bit) vs 0x7F and pmdUpperLowThresh */ - if ((device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh <= device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh) || - device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH; - } - else - { - /* Write pmdLowerHighThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh, 0x7F, 0); - } - - /* Range check pmdUpperLowThresh (7-bit): Comparison to pmdLowerHigh done earlier */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh > 0x7F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH; - } - else - { - /* Write pmdUpperLowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LOCK_LEVEL, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh); - } - - /* Range check pmdLowerLowThresh (4-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH; - } - else - { - /* Write pmdUpperLowThresh to temp variable */ - powerThresholdsRegValue |= device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh; - } - - /* Range check pmdUpperHighThresh (4-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH; - } - else - { - /* Write pmdUpperHighThresh to temp var, then to register */ - powerThresholdsRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh << 4); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_POWER_THRSH, powerThresholdsRegValue); - } - - /* Range check pmdUpperHighGainStepAttack (5-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP; - } - else - { - /* Write pmdUpperHighGainStepAttack */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER1_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack, 0x1F, 0); - } - - /* Range check pmdLowerLowGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery); - } - - /* Range check pmdUpperLowGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP; - } - else - { - /* Write pmdUpperLowGainStepRecovery to register */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack); - } - - /* Range check pmdLowerHighGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP)); - return MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER0_THRSH_GAIN_STEP, device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery); - } - - /* WRITE REGISTERS FOR THE AGC PEAK DETECTOR (APD/HB2) STRUCTURE */ - - /* Range check apdFastAttack and hb2FastAttack (1-bit) */ - if ((device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack > 0x1) || - (device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack > 0x1)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE)); - return MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE; - } - else - { - /* Write pmdLowerLowGainStepRecovery to temp var, then to register */ - lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack << 7); - lower1ThreshGainStepRegValue |= (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2FastAttack << 6); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER1_THRSH_GAIN_STEP, lower1ThreshGainStepRegValue); - } - - /* Range check apdHighThresh */ - if ((device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh > 0x3F) || - (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh <= device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM; - } - else - { - /* Write apdHighThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_ULB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh, 0X3F, 0); - } - - /* Range check apdLowThresh */ - if ((device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh > 0x3F) || - (device->obsRx->orxAgcCtrl->peakAgc->apdHighThresh < device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM; - } - else - { - /* write apdLowThresh */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_LLB_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThresh, 0x3F, 0); - } - - /* Range check hb2HighThresh */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh < device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM; - } - else - { - /* write hb2HighThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_UPPER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh); - } - - /* Range check hb2LowThresh */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM; - } - else - { - /* write hb2LowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_LOWER_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh); - } - - /* Range check hb2VeryLowThresh */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh > device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM; - } - else - { - /* write hb2VeryLowThresh */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_VERYLOW_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh); - } - - /* Write threshold counter values for apdHigh/apdLow/hb2High/hb2Low/hb2VeryLow */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ULB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdHighThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LLB_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->apdLowThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_HIGH_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2HighThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_LOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2LowThreshExceededCnt); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_VERYLOW_OVRG_CNT_THRSH, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThreshExceededCnt); - - /* Range check on apdHighGainStepAttack (5-bit) */ - if (device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM; - } - else - { - /* Write apdHighGainStepAttack */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_1, device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack); - } - - /* Range check on apdLowGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM; - } - else - { - /* Write apdLowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_4, device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery); - } - - /* Range check on hb2HighGainStepAttack (5-bit) */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM; - } - else - { - /* Write hb2HighGainStepAttack */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_2, device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack); - } - - /* Range check on hb2LowGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM; - } - else - { - /* Write hb2LowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_5, device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery); - } - - /* Range check on hb2VeryLowGainStepRecovery (5-bit) */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM; - } - else - { - /* Write hb2VeryLowGainStepRecovery */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_6, device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery); - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable > 0x1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE; - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt > 0x7) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT; - } - - /* Range Check on hb2OverloadDetectEnable */ - if (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt > 0xF) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT, - getMykonosErrorMessage(MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT)); - return MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT; - } - else - { - /* Write the hb2OvldCfgRegValue, the combination of hb2OverloadThreshCnt, hb2OverloadDurationCnt, and hb2OverloadDetectEnable */ - hb2OvldCfgRegValue = (device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThreshCnt) | - (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt << 4) | - (uint8_t)(device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDetectEnable << 7); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_CFG, hb2OvldCfgRegValue); - } - - /* Hard-coded value for the ADC overload configuration. Sets the HB2 offset to -6dB.*/ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ORX_SNRX_OVRLD_ADC_OVRLD_CFG, 0x18); - /* Hard-coded value for APD decay setting. Setting allows for the quickest settling time of peak detector */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_BLOCK_DET_DECAY, 0x0); - - /* performing a soft reset */ - return MYKONOS_resetRxAgc(device); -} - -/** - * \brief Enables or disables the ObsRx slow loop gain counter to use the sync pulse - * - * Dependencies: - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing the device SPI settings - * \param enable is a uint8_t data type where '0' = disable ObsRx gain counter from using sync pulse, '1' = enable ObsRx gain. All other values will throw an error. - * counter to use the sync pulse. This value is written back to the device data structure for storage. - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable) -{ - const uint8_t syncPulseBitMask = 0x80; - uint8_t enableBit = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxGainCtrSyncPulse()\n"); -#endif - - enableBit = (enable > 0) ? 1 : 0; - - /* read, modify, write ObsRx gain counter sync pulse enable bit */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG, enableBit, syncPulseBitMask, 7); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Configures the ObsRx gain control mode - * - * Dependencies: - * - device->spiSettings - * - device->obsRx->orxGainCtrl->gainMode - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param mode is a mykonosGainMode_t enumerated gain control mode type - * - * When the mode enumerated type is passed, the ObsRx gain mode is set to this value and the - * ObsRX agcType mykonosAgcCfg_t structure member is updated with the new value - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM Invalid Observation Rx Gain control mode selected (use mykonosGainMode_t ENUM values) - */ -mykonosErr_t MYKONOS_setObsRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode) -{ - const uint8_t ORX_GAIN_TYPE_MASK = 0x3; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxGainControlMode()\n"); -#endif - - /* performing gain type check */ - switch (mode) - { - case MGC: - break; - case AGC: - break; - case HYBRID: - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM)); - return MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_CFG_1, mode, ORX_GAIN_TYPE_MASK, 0); - - /* writing mode setting to data structure */ - if ((device->profilesValid & ORX_PROFILE_VALID) > 0) - { - device->obsRx->orxGainCtrl->gainMode = mode; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs a power measurement in the ObsRx digital data path. - * - * Due to interdependencies between the AGC and power measurement the power measurement duration and - * where the measurement is taken is variable. - * The location of the power measurement is given by device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig - * The number of samples the power measurement uses is given by 8*2^(device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig) at the IQ rate, - * if measured at RFIR output. This number of samples must be less than the agcGainUpdateCounter. - * If the receiver is disabled during the power measurement, this function returns a 0 value for rx2DecPower_mdBFS - * - * The resolution of this function is 0.25dB. - * The dynamic range of this function is 40dB. Signals lower than 40dBFS may not be measured accurately. - * - * Dependencies - * - device->spiSettings - * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig - * - device->obsRx->obsRxAgcCtrl->obsRxPwrAgc->pmdMeasConfig - * - * \param device Pointer to the Mykonos data structure - * \param obsRxDecPower_mdBFS Pointer to store the Rx1 decimated power return. Value returned in mdBFS - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getObsRxDecPower(mykonosDevice_t *device, uint16_t *obsRxDecPower_mdBFS) -{ - uint8_t obsRxDecPower_dBFS = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getObsRxDecPower()\n"); -#endif - - /* read ObsRx Dec Power Measurement */ - if (obsRxDecPower_mdBFS != NULL) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_SNIFFER_DECIMATED_PWR, &obsRxDecPower_dBFS); - *obsRxDecPower_mdBFS = (uint16_t)(obsRxDecPower_dBFS * 250); /* 250 = 1000 * 0.25dB */ - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM)); - return MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM; - } - - return MYKONOS_ERR_OK; -} - -/* - ***************************************************************************** - * Tx Data path functions - ***************************************************************************** - */ - -/** - * \brief Sets the Tx1 RF output Attenuation - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->tx->txAttenStepSize - * - * \param device Pointer to the Mykonos device's data structure - * \param tx1Attenuation_mdB The desired TxAttenuation in milli-dB (Range: 0 to 41950 mdB) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SETTX1ATTEN_INV_PARM tx1Attenuation_mdB parameter is out of range (0 - 41950) - * \retval MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value - */ -mykonosErr_t MYKONOS_setTx1Attenuation(mykonosDevice_t *device, uint16_t tx1Attenuation_mdB) -{ - uint16_t data = 0; - uint16_t attenStepSizeDiv = 50; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx1Attenuation()\n"); -#endif - - /* check input parameter is in valid range */ - if (tx1Attenuation_mdB > 41950) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_PARM)); - return MYKONOS_ERR_SETTX1ATTEN_INV_PARM; - } - - switch (device->tx->txAttenStepSize) - { - case TXATTEN_0P05_DB: - attenStepSizeDiv = 50; - break; - case TXATTEN_0P1_DB: - attenStepSizeDiv = 100; - break; - case TXATTEN_0P2_DB: - attenStepSizeDiv = 200; - break; - case TXATTEN_0P4_DB: - attenStepSizeDiv = 400; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM)); - return MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM; - - } - - data = (tx1Attenuation_mdB / attenStepSizeDiv); - - /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1, ((data >> 8) & 0x03)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0, (data & 0xFF)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the Tx2 RF output Attenuation (Step size is 0.05dB.) - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->tx->txAttenStepSize - * - * \param device Pointer to the Mykonos device's data structure - * \param tx2Attenuation_mdB The desired TxAttenuation in milli-dB - * (Range: 0 to 41950 mdB) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SETTX2ATTEN_INV_PARM tx2Attenuation_mdB parameter is out of range (0 - 41950) - * \retval MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM device->tx->txAttenStepSize is not a valid enum value - */ -mykonosErr_t MYKONOS_setTx2Attenuation(mykonosDevice_t *device, uint16_t tx2Attenuation_mdB) -{ - uint16_t attenStepSizeDiv = 50; - uint16_t data = 0; - //const uint8_t SPI_TXATTEN_MODE = 0x01; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTx2Attenuation()\n"); -#endif - - /* check input parameter is in valid range */ - if (tx2Attenuation_mdB > 41950) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_PARM)); - return MYKONOS_ERR_SETTX2ATTEN_INV_PARM; - } - - switch (device->tx->txAttenStepSize) - { - case TXATTEN_0P05_DB: - attenStepSizeDiv = 50; - break; - case TXATTEN_0P1_DB: - attenStepSizeDiv = 100; - break; - case TXATTEN_0P2_DB: - attenStepSizeDiv = 200; - break; - case TXATTEN_0P4_DB: - attenStepSizeDiv = 400; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM)); - return MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM; - } - - data = (tx2Attenuation_mdB / attenStepSizeDiv); - - /* Write MSB bits followed by LSB bits, TxAtten updates when [7:0] written */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1, ((data >> 8) & 0x03)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0, (data & 0xFF)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads back the Tx1 RF output Attenuation - * - * This function reads back the TxAttenuation setting currently applied to the transmit chain. - * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO - * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path - * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be - * read back. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device's data structure - * \param tx1Attenuation_mdB The readback value of the Tx1 Attenuation in milli-dB (Range: 0 to 41950 mdB) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETTX1ATTEN_NULL_PARM tx1Attenuation_mdB return parameter has NULL pointer - */ -mykonosErr_t MYKONOS_getTx1Attenuation(mykonosDevice_t *device, uint16_t *tx1Attenuation_mdB) -{ - uint8_t txAttenLsb = 0; - uint8_t txAttenMsb = 0; - uint16_t attenStepSizeDiv = 50; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx1Attenuation()\n"); -#endif - - /* check return parameter pointer is not NULL pointer */ - if (tx1Attenuation_mdB == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1ATTEN_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GETTX1ATTEN_NULL_PARM)); - return MYKONOS_ERR_GETTX1ATTEN_NULL_PARM; - } - - /* Write TxAtten read back reg to update readback values, then read Tx1Atten */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, 0x00); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0); - - /* Readback word always reads back with 0.05dB resolution */ - *tx1Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads back the Tx2 RF output Attenuation - * - * This function reads back the TxAttenuation setting currently applied to the transmit chain. - * The function will work with SPI mode or pin controlled TxAtten mode using the increment/decrement GPIO - * pins. For the readback value to be valid the Tx data path must be powered up. If the Tx data path - * is powered down or radioOff state, the last TxAtten setting while the Tx was powered up will be - * read back. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device's data structure - * \param tx2Attenuation_mdB The readback value of the Tx2 Attenuation in milli-dB (Range: 0 to 41950 mdB) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETTX2ATTEN_NULL_PARM tx2Attenuation_mdB return parameter pointer is NULL - */ -mykonosErr_t MYKONOS_getTx2Attenuation(mykonosDevice_t *device, uint16_t *tx2Attenuation_mdB) -{ - uint8_t txAttenLsb = 0; - uint8_t txAttenMsb = 0; - uint16_t attenStepSizeDiv = 50; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTx2Attenuation()\n"); -#endif - - /* check return parameter pointer is not NULL pointer */ - if (tx2Attenuation_mdB == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2ATTEN_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GETTX2ATTEN_NULL_PARM)); - return MYKONOS_ERR_GETTX2ATTEN_NULL_PARM; - } - - /* Write TxAtten read back reg to update readback values, then read Tx1Atten */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, 0x00); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_0_READBACK, &txAttenLsb, 0xFF, 0); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK, &txAttenMsb, 0x03, 0); - - /* Readback word always reads back with 0.05dB resolution */ - *tx2Attenuation_mdB = (uint16_t)(((uint16_t)(txAttenLsb) | ((uint16_t)(txAttenMsb) << 8)) * attenStepSizeDiv); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Checks the Tx Filter over-range bit assignments for digital clipping in the Tx data path - * - * Dependencies - * - device->spiSettings - * - * txFilterStatus bit-field assignments are: - * txFilterStatus[0] = TFIR Ch1 Overflow - * txFilterStatus[1] = HB1 Ch1 Overflow - * txFilterStatus[2] = HB2 Ch1 Overflow - * txFilterStatus[3] = QEC Ch1 Overflow - * txFilterStatus[4] = TFIR Ch2 Overflow - * txFilterStatus[5] = HB1 Ch2 Overflow - * txFilterStatus[6] = HB2 Ch2 Overflow - * txFilterStatus[7] = QEC Ch2 Overflow - * - * \param device Pointer to the Mykonos device's data structure - * \param txFilterStatus is an 8-bit Tx filter over-range status bit-field - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM Function txFilterStatus parameter pointer is NULL - */ -mykonosErr_t MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t *device, uint8_t *txFilterStatus) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxFilterOverRangeStatus()\n"); -#endif - - if (txFilterStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM)); - return MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_FILTER_OVERFLOW, txFilterStatus); - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables/Disables the Tx NCO test tone - * - * This function enables/disables a digital numerically controlled oscillator - * in the Mykonos Digital to create a test CW tone on Tx1 and Tx2 RF outputs. - * - * The TxAttenuation is forced in this function to max analog output power, but - * the digital attenuation is backed off 6dB to make sure the digital filter - * does not clip and cause spurs in the tx spectrum. - * - * Dependencies - * - device->spiSettings - * - device->profilesValid - * - device->tx->txProfile->iqRate_kHz - * - * \param device Pointer to the Mykonos device's data structure - * \param enable 0 = Disable Tx NCO, 1 = Enable Tx NCO on both transmitters - * \param tx1ToneFreq_kHz Signed frequency in kHz of the desired Tx1 tone - * \param tx2ToneFreq_kHz Signed frequency in kHz of the desired Tx2 tone - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID Can not enable Tx NCO when Tx Profile is not enabled/valid - * \retval MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID Tx1 NCO Tone frequency out of range (-IQrate/2 to IQrate/2) - * \retval MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID Tx2 NCO Tone frequency out of range (-IQrate/2 to IQrate/2) - */ -mykonosErr_t MYKONOS_enableTxNco(mykonosDevice_t *device, uint8_t enable, int32_t tx1ToneFreq_kHz, int32_t tx2ToneFreq_kHz) -{ - int16_t tx1NcoTuneWord = 0; - int16_t tx2NcoTuneWord = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTxNco()\n"); -#endif - - if (enable > 0) - { - if ((device->profilesValid & TX_PROFILE_VALID) == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID, - getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID)); - return MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID; - } - - if ((tx1ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx1ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID, - getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID)); - return MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID; - } - - if ((tx2ToneFreq_kHz > ((int32_t)(device->tx->txProfile->iqRate_kHz) / 2)) || (tx2ToneFreq_kHz < ((int32_t)(device->tx->txProfile->iqRate_kHz) * -1 / 2))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID, - getMykonosErrorMessage(MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID)); - return MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID; - } - - /* Force Tx output power to max analog output power, but 6dB digital */ - /* backoff to prevent the NCO from clipping the Tx PFIR filter */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_0, 0x78); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_1, 0x00, 0x3F, 0); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX1_GAIN_2, 0x0); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_0, 0x78); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_1, 0x00, 0x3F, 0); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX2_GAIN_2, 0x0); - - /* Enable manual Tx output power mode */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x0A, 0x0F, 0); - - /* Set Tx NCO tuning words */ - tx1NcoTuneWord = (int16_t)(((int64_t)(tx1ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1); - tx2NcoTuneWord = (int16_t)(((int64_t)(tx2ToneFreq_kHz) << 16) / device->tx->txProfile->iqRate_kHz * -1); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_MSB, (uint8_t)((uint16_t)tx1NcoTuneWord >> 8)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_LSB, (tx1NcoTuneWord & 0xFF)); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_MSB, (uint8_t)((uint16_t)tx2NcoTuneWord >> 8)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_LSB, (tx2NcoTuneWord & 0xFF)); - - /* Enable Tx NCO - set [7] = 1 */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 1, 0x80, 7); - } - else - { - /* Disable Tx NCO - set [7] = 0 */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DIGITAL_TEST_BYTE_0, 0, 0x80, 7); - - /* Enable normal Tx Atten table mode */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, 0x05, 0x0F, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Writes Mykonos device registers with settings for the PA Protection block. - * - * This function writes register settings for the Mykonos PA Protection Block. - * This function does not enable the PA Protection functionality. - * Note that independent control of PA protection for both Tx channels is not possible. - * The PA Protection block allows for error flags to go high if the accumulated TX power in the data path - * exceeds a programmable threshold level based on samples taken in a programmable duration. - * - * \post After calling this function the user will need to call MYKONOS_enablePaProtection(...) - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device's data structure - * \param powerThreshold PA Protection Threshold sets the power level that, if detected in the TX data path, raises the PA error flags. The range is 0 to 4096. - * To calculate the required setting for the power threshold: - * powerThreshold = MAX_DAC_CODE * (10^((txPowerThresh_dBFS/10))) - * For example: If the required dBFS for the threshold is -10 dBFS, then the powerThreshold passed should be 409. - * - * \param attenStepSize Attenuation Step Size sets the size of the attenuation step when Tx Atten Control is Enabled. The range is 0 to 128 with a resolution is 0.2dB/LSB. - * \param avgDuration Averaging Duration for the TX data path power measurement. The range is 0 to 14 specified in number of cycles of the TX IQ Rate. - * \param stickyFlagEnable "1" Enables the PA Error Flags to stay high after being triggered, even if the power decreases below threshold. "0" disables this functionality. - * \param txAttenControlEnable "1" Enables autonomous attenuation changes in response to PA error flags. "0" disables this functionality. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION avgDuration parameter invalid (valid 0-15) - * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP attenStepSize function parameter invalid (valid 0-127) - */ -mykonosErr_t MYKONOS_setupPaProtection(mykonosDevice_t *device, uint16_t powerThreshold, uint8_t attenStepSize, uint8_t avgDuration, uint8_t stickyFlagEnable, uint8_t txAttenControlEnable) -{ - uint8_t paProtectConfig = 0; - uint8_t paProtectAttenCntl = 0; - - const uint8_t PROTECT_AVG_DUR_MASK = 0x1E; - const uint8_t STICKY_FLAG_EN_MASK = 0x40; - const uint8_t ATT_STEP_MASK = 0xFE; - const uint8_t PROTECT_ATT_EN_MASK = 0x01; - const uint8_t AVG_DUR_MASK = 0x0F; - const uint8_t ATT_STEP_SIZE = 0x7F; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupPaProtection()\n"); -#endif - - /* Overwrite PA Protection Config register data with averaging duration and sticky flag. Also performing range check on stickyFlagEnable and avgDuration */ - if (avgDuration > AVG_DUR_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION, - getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION)); - return MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION; - } - - if (attenStepSize > ATT_STEP_SIZE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP, - getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP)); - return MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP; - } - - paProtectConfig = (PROTECT_AVG_DUR_MASK & (avgDuration << 1)); - - if (stickyFlagEnable > 0) - { - paProtectConfig |= (STICKY_FLAG_EN_MASK); - } - - paProtectAttenCntl = ATT_STEP_MASK & (attenStepSize << 1); - - if (txAttenControlEnable > 0) - { - paProtectAttenCntl |= (PROTECT_ATT_EN_MASK); - } - - /* Clear and write all PA Protection setup registers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, 0x00); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL, paProtectAttenCntl); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectConfig); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB, (powerThreshold & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB, ((powerThreshold >> 8) & 0x0F)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables the Mykonos PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...). - * - * This function enables the PA Protection block according to the parameters passed in MYKONOS_setupPaProtection(...) - * The paProtectEnable signal enables the PA Protection block, allowing usage of the PA protection functions. - * - * \pre Before calling this function the user needs to setup the PA protection by calling MYKONOS_setupPaProtection(...) - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device's data structure - * \param paProtectEnable "1" Enables the PA Protection block. "0" Disables the PA Protection block - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enablePaProtection(mykonosDevice_t *device, uint8_t paProtectEnable) -{ - uint8_t paProtectEnableReg = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enablePaProtection()\n"); -#endif - - paProtectEnableReg = (paProtectEnable > 0) ? 1 : 0; - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, paProtectEnableReg, 0x01, 0); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Obtains an estimate of a TX channel's accumulated power over the sample duration provided in MYKONOS_setupPaProtection(...) - * - * This function uses the 'avgDuration' parameter provided in MYKONOS_setupPaProtection to set the number of samples to accumulate - * to obtain an estimate for a TX channel specified by the 'channel' parameter. - * A 12-bit field estimating the channel power is returned in the '*channelPower' pointer. - * To obtain the dBFS value of the reading: - * dBFS value = 10*log10(channelPower/MAX_DAC_CODE) - * where MAX_DAC_CODE = 2^12 = 4096 - * For example: If channelPower is reading 409 then the channel power in dBFS is -10dBFS. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Point to the Mykonos device's data structure - * \param channel Select the channel of interest. Only use TX1 (1) or TX2 (2) of mykonosTxChannels_t - * \param *channelPower A pointer that stores the selected channels power. Read back is provided as a 12 bit value. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GET_DAC_PWR_INV_POINTER Function channelPower parameter is a NULL pointer - * \retval MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL Invalid Tx Channel passed in function channel parameter (TX1 or TX2) - */ -mykonosErr_t MYKONOS_getDacPower(mykonosDevice_t *device, mykonosTxChannels_t channel, uint16_t *channelPower) -{ - uint8_t channelPowerLsb = 0; - uint8_t channelPowerMsb = 0; - - const uint8_t CHAN_POWER_MSB_MASK = 0xF; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDacPower()\n"); -#endif - - if (channelPower == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DAC_PWR_INV_POINTER, - getMykonosErrorMessage(MYKONOS_ERR_GET_DAC_PWR_INV_POINTER)); - return MYKONOS_ERR_GET_DAC_PWR_INV_POINTER; - } - - /* Set bit D5 to read the appropriate channel power */ - switch (channel) - { - case TX1: - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 0, 0x20, 5); - break; - case TX2: - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, 1, 0x20, 5); - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL)); - return MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL; - } - - /* SPI Write to register PA Protection power readback registers (write strobe) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00); - - /* SPI Read of the PA Protection power readback registers */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, &channelPowerLsb); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, &channelPowerMsb); - - *channelPower = (channelPowerLsb | (((uint16_t)(channelPowerMsb & CHAN_POWER_MSB_MASK)) << 8)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns PA Protection Error Flag Status - * - * This function provides a readback of the PA protection Error Flag Status through the '*errorFlagStatus' pointer - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Point to the Mykonos device's data structure - * \param errorFlagStatus Pointer to store the error flag status. - * errorFlagStatus | error - * -----------------|------------ - * 0 | indicates no PA Error Flags are high - * 1 | indicates TX1 Error Flag - * 2 | indicates TX2 Error Flag - * 3 | indicates TX1 and TX2 Error Flags are high - * - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER Function errorFlagStatus parameter has NULL pointer - */ -mykonosErr_t MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t *device, uint8_t *errorFlagStatus) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPaProtectErrorFlagStatus()\n"); -#endif - - if (errorFlagStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER, - getMykonosErrorMessage(MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER)); - return MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER; - } - - /* SPI Write to register PA Protection power readback registers (write strobe) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB, 0x00); - - /* SPI Read of the PA Protection power readback registers */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB, errorFlagStatus, 0x60, 5); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Manually clears the PA Protection Error Flags. - * - * This function manually clears the PA Error Flags. The user must setup the PA Protection block to enable - * sticky error flags. Sticky error flags require the user to clear the bit manually even if the accumulated power is - * below the power threshold for the PA protection block. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device's data structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_clearPaErrorFlag(mykonosDevice_t *device) -{ - uint8_t paProtectConfig = 0; - - const uint8_t PA_ERROR_CLEAR_MASK = 0x80; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearPaErrorFlag()\n"); -#endif - - /* SPI Read of the PA Protection power readback registers */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, &paProtectConfig); - - /* SPI Write to self clear the PA Error Flags */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION, (paProtectConfig | PA_ERROR_CLEAR_MASK)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Helper function for return of character string based on 32-bit mykonosErr_t enum value - * - * To save codespace, these error strings are ifdef'd out unless the user - * adds a define MYKONOS_VERBOSE to their workspace. This function can be - * useful for debug. Each function also returns unique error codes to - * make it easier to determine where the code broke. - * - * \param errorCode is enumerated error code value - * - * \return Returns character string based on enumerated value - */ -const char* getMykonosErrorMessage(mykonosErr_t errorCode) -{ -#ifndef MYKONOS_VERBOSE - return ""; - -#else - - switch (errorCode) - { - case MYKONOS_ERR_OK: - return ""; - case MYKONOS_ERR_INV_PARM: - return "Mykonos: Invalid parameter\n"; - case MYKONOS_ERR_FAILED: - return "Mykonos: General Failure\n"; - case MYKONOS_ERR_WAITFOREVENT_INV_PARM: - return "waitForEvent had invalid parameter.\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT: - return "waitForEvent timed out.\n"; - case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_WAIT: - return "Requested new ENSM state is invalid from the WAIT state.\n"; - case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_ALERT: - return "Requested new ENSM state is invalid from the ALERT state.\n"; - case MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_TXRX: - return "Requested new ENSM state is invalid from the TXRX state.\n"; - case MYKONOS_ERR_SETENSM_INVALIDSTATE: - return "Current ENSM state is an invalid state or calibration state.\n"; - case MYKONOS_ERR_PU_RXPATH_INV_PARAM: - return "Invalid Rx channel was requested to be powered up.\n"; - case MYKONOS_ERR_PU_TXPATH_INV_PARAM: - return "Invalid Tx channel was requested to be powered up.\n"; - case MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM: - return "Invalid ObsRx channel was requested to be powered up.\n"; - case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT: - return "Invalid default ObsRx channel was requested to be powered up.\n"; - case MYKONOS_ERR_INIT_INV_ORXCHAN: - return "Invalid ObsRx channel requested during initialize().\n"; - case MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE: - return "Invalid combination for rxsyncb and orxsyncb, if shared syncb they should have the CMOS/LVDS mode\n"; - case MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION: - return "Invalid TxFIR interpolation value.(Valid: 1,2,4)\n"; - case MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION: - return "Invalid TXHB2 interpolation value.(Valid: 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION: - return "Invalid TXHB1 interpolation value.(Valid: 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION: - return "Invalid RxFIR decimation value.(Valid: 1,2,4)\n"; - case MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION: - return "Invalid Rx DEC5 decimation value.(Valid: 4 or 5)\n"; - case MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION: - return "Invalid RxHB1 decimation value.(Valid: 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_SNIFFER_RHB1: - return "Invalid Sniffer HB1 decimation value (Valid 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC: - return "Invalid Sniffer RFIR decimation value (Valid 1,2,4)\n"; - case MYKONOS_ERR_INIT_INV_ORX_RHB1: - return "Invalid ORx HB1 decimation value (Valid 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC: - return "Invalid ORx RFIR decimation value. (Valid 1,2,4)\n"; - case MYKONOS_ERR_INIT_INV_ADCDIV: - return "Invalid Rx ADC divider. (Valid 1 or 2)\n"; - case MYKONOS_ERR_INIT_INV_DACDIV: - return "Invalid Tx DAC divider. Use enum DACDIV_2, DACDIV_2p5 or DACDIV_4.\n"; - case MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV: - return "Invalid ObsRx ADC div. (Valid 1 or 2)\n"; - case MYKONOS_ERR_CLKPLL_INV_HSDIV: - return "Invalid CLKPLL HSDIV. (Valid 4 or 5)\n"; - case MYKONOS_ERR_CLKPLL_INV_VCODIV: - return "Invalid CLKPLL VCODIV. Use enum VCODIV_1, VCODIV_1p5, VCODIV_2, VCODIV_3\n"; - case MYKONOS_ERR_CLKPLL_INV_RXTXPROFILES: - return "No Rx or Tx profile is specified.\n"; - case MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX: - return "CLKPLL VCO frequency out of range.\n"; - case MYKONOS_ERR_SETCLKPLL_INV_FRACWORD: - return "CLKPLL fractional word is non zero.\n"; - case MYKONOS_ERR_SETRFPLL_INV_PLLNAME: - return "Invalid pllName requested in setRfPllFreuquency()\n"; - case MYKONOS_ERR_SETRFPLL_INV_LO_PARM: - return "RF PLL frequency out of range\n"; - case MYKONOS_ERR_GETRFPLL_INV_PLLNAME: - return "Invalid pllName requested in getRfPllFrequency()\n"; - case MYKONOS_ERR_GETRFPLL_ARMERROR: - return "ARM Command Error in MYKONOS_getRfPllFrequency()\n"; - case MYKONOS_ERR_GETRFPLL_NULLPARAM: - return "NULL pointer in function parameter for MYKONOS_setRfPllFrequency()\n"; - case MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM: - return "Could not scale device clock into range 40MHz to 80Mhz.\n"; - case MYKONOS_ERR_SETRFPLL_INV_VCOINDEX: - return "RFPLL VCO frequency out of range.\n"; - case MYKONOS_ERR_SETRFPLL_INV_REFCLK: - return "Unsupported PLL reference clock or refclk out of range.\n"; - case MYKONOS_ERR_SETORXGAIN_INV_CHANNEL: - return "Invalid ObsRx channel in setObsRxManualGain().\n"; - case MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN: - return "Invalid gain requested in setObsRxManualGain() for ORX1\n"; - case MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN: - return "Invalid gain requested in setObsRxManualGain() for ORX2\n"; - case MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN: - return "Invalid gain requested in setObsRxManualGain() for Sniffer\n"; - case MYKONOS_ERR_GETORX1GAIN_INV_POINTER: - return "Cannot return ORx1 gain to gain control data structure (invalid pointer).\n"; - case MYKONOS_ERR_GETORX2GAIN_INV_POINTER: - return "Cannot return ORx2 gain to gain control data structure (invalid pointer).\n"; - case MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER: - return "Cannot return Sniffer gain to gain control data structure (invalid pointer).\n"; - case MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED: - return "Cannot read ObsRx gain index. ObsRx Channel is disabled.\n"; - case MYKONOS_ERR_SETTX1ATTEN_INV_PARM: - return "Tx1 attenuation is out of range (0 - 41950 mdB).\n"; - case MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM: - return "Invalid Tx1Atten stepsize. Use enum mykonosTxAttenStepSize_t\n"; - case MYKONOS_ERR_SETTX2ATTEN_INV_PARM: - return "Tx2 attenuation is out of range (0 - 41950 mdB).\n"; - case MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM: - return "Invalid Tx2Atten stepsize. Use enum mykonosTxAttenStepSize_t\n"; - case MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM: - return "Invalid number of FIR taps\n"; - case MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM: - return "Invalid number of FIR taps read for the selected Filter\n"; - case MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM: - return "Invalid FIR filter name requested. use enum mykonosfirName_t\n"; - case MYKONOS_ERR_RXFIR_INV_GAIN_PARM: - return "Rx FIR filter has invalid gain setting\n"; - case MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM: - return "ObsRx FIR filter A (ORx) has invalid gain setting\n"; - case MYKONOS_ERR_SRXFIR_INV_GAIN_PARM: - return "ObsRx FIR filter B (Sniffer) has invalid gain setting\n"; - case MYKONOS_ERR_TXFIR_INV_GAIN_PARM: - return "Tx FIR filter has invalid gain setting\n"; - case MYKONOS_ERR_READFIR_NULL_PARM: - return "MYKONOS_readFir() has a null *firFilter parameter\n"; - case MYKONOS_ERR_READFIR_COEFS_NULL: - return "MYKONOS_readFir() has a null coef array in *firFilter structure\n"; - case MYKONOS_ERR_READFIR_INV_FIRNAME_PARM: - return "Invalid FIR filter name requested. use enum mykonosfirName_t\n"; - case MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM: - return "Rx1 manual gain index out of range of gain table\n"; - case MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM: - return "Rx2 manual gain index out of range of gain table\n"; - case MYKONOS_ERR_INITSER_INV_VCODIV_PARM: - return "Found invalid VCO divider value during setupSerializers()\n"; - case MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM: - return "CLKPLL VCO frequency exceeded max(8Ghz) in VCO divider /1 case ()\n"; - case MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM: - return "CLKPLL VCO frequency exceeded max(9.216Ghz) in VCO divider /1.5 case ()\n"; - case MYKONOS_ERR_INITDES_INV_VCODIV_PARM: - return "Found invalid VCO divider value during setupDeserializers()\n"; - case MYKONOS_ERR_SER_INV_M_PARM: - return "Invalid JESD Framer M parameter during setupSerializers()\n"; - case MYKONOS_ERR_SER_INV_L_PARM: - return "Invalid JESD Framer L parameter during setupSerializers()\n"; - case MYKONOS_ERR_SER_INV_LANERATE_PARM: - return "Invalid Lanerate frequency in setupSerializer()\n"; - case MYKONOS_ERR_SER_INV_LANEEN_PARM: - return "Invalid number of JESD204 lanes enabled.\n"; - case MYKONOS_ERR_SER_INV_AMP_PARM: - return "Invalid JESD204 serializer amplitude\n"; - case MYKONOS_ERR_SER_INV_PREEMP_PARM: - return "Invalid JESD204 serializer preemphasis setting\n"; - case MYKONOS_ERR_SER_INV_LANEPN_PARM: - return "Invald JESD204 serializer PN invert setting\n"; - case MYKONOS_ERR_SER_LANE_CONFLICT_PARM: - return "Rx framer and ObsRx framer are attempting to use the same physical lanes\n"; - case MYKONOS_ERR_SER_INV_TXSER_DIV_PARM: - return "Invalid serializer lane clock divider\n"; - case MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM: - return "Rx lane and ObsRx lane rate must match\n"; - case MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM: - return "Framer M can only =1 if Real IF data option is enabled\n"; - case MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT: - return "Serializer HSCLK and lane clock are not integer multiples\n"; - case MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT: - return "Deserializer HSCLK and lane clock are not integer multiples\n"; - case MYKONOS_ERR_DESER_INV_M_PARM: - return "Invalid deserializer M value. (Valid 2 or 4)\n"; - case MYKONOS_ERR_DESER_INV_L_PARM: - return "Invalid deserializer L value. (Valid 1,2,4)\n"; - case MYKONOS_ERR_DESER_INV_HSCLK_PARM: - return "Invalid HSCLK in setupDeserializer()\n"; - case MYKONOS_ERR_DESER_INV_LANERATE_PARM: - return "Invalid deserializer lane rate\n"; - case MYKONOS_ERR_DESER_INV_LANEEN_PARM: - return "Invalid number of deserializer lanes enabled\n"; - case MYKONOS_ERR_DESER_INV_EQ_PARM: - return "Invalid deserializer EQ setting"; - case MYKONOS_ERR_DESER_INV_LANEPN_PARM: - return "Invalid deserializer invert Lane PN setting\n"; - case MYKONOS_ERR_FRAMER_INV_M_PARM: - return "Invalid Rx framer M setting\n"; - case MYKONOS_ERR_FRAMER_INV_BANKID_PARM: - return "Invalid Rx framer Bank ID\n"; - case MYKONOS_ERR_FRAMER_INV_LANEID_PARM: - return "Invalid Rx framer Lane ID\n"; - case MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM: - return "Invalid Rx framer LMFC offset\n"; - case MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM: - return "Invalid Rx framer Real IF setting\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM: - return "Invalid ObsRx Framer M value\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM: - return "Invalid ObsRx Framer Bank ID\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM: - return "Invalid ObsRx framer Lane ID\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM: - return "Invalid ObsRx framer LMFC offset\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM: - return "Invalid ObsRx framer Real IF setting, M must =1\n"; - case MYKONOS_ERR_DEFRAMER_INV_M_PARM: - return "Invalid Deframer M setting\n"; - case MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM: - return "Invalid Deframer Bank ID\n"; - case MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM: - return "Invalid Deframer Lane ID\n"; - case MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM: - return "Invalid Deframer LMFC offset"; - case MYKONOS_ERR_DEFRAMER_INV_K_PARAM: - return "Invalid Deframer K setting\n"; - case MYKONOS_ERR_DEFRAMER_INV_FK_PARAM: - return "Invalid Deframer F*K value\n"; - case MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM: - return "Invalid polyOrder parameter in enableRxFramerPrbs()\n"; - case MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM: - return "Invalid polyOrder parameter in enableObsRxFramerPrbs()\n"; - case MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM: - return "Invalid enable parameter value in enableDeframerPrbsChecker()\n"; - case MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM: - return "Invalid polyOrder parameter in enableDeframerPrbsChecker()\n"; - case MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM: - return "Invalid lane counter select in readDeframerPrbsCounters()\n"; - case MYKONOS_ERR_INITARM_INV_DATARATE_PARM: - return 0; - case MYKONOS_ERR_INITARM_INV_VCODIV: - return "Invalid ARM VCO divider\n"; - case MYKONOS_ERR_INITARM_INV_REGCLK: - return "Invalid ARM SPI register clock rate\n"; - case MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM: - return "Invalid ARM clock rate\n"; - case MYKONOS_ERR_LOADHEX_INV_CHARCOUNT: - return "LoadHex() char count = 0\n"; - case MYKONOS_ERR_LOADHEX_INVALID_FIRSTCHAR: - return "LoadHex() First char is not :\n"; - case MYKONOS_ERR_LOADHEX_INVALID_CHKSUM: - return "LoadHex() line checksum is invalid\n"; - case MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT: - return "Invalid byte count passed to function MYKONOS_loadArmFromBinary()"; - case MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT: - return "Invalid byte count passed to function MYKONOS_loadArmConcurrent()"; - case MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM: - return "Verify ARM checksum failed\n"; - case MYKONOS_ERR_READARMMEM_INV_ADDR_PARM: - return "ReadArmMem() was given an invalid memory address\n"; - case MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM: - return "WriteArmMem() was given an invalid memory address\n"; - case MYKONOS_ERR_ARM_INV_ADDR_PARM: - return "Invalid memory address in MYKONOS_loadArmConcurrent()"; - case MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM: - return "Invalid ARM opcode given to sendArmCommand()\n"; - case MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM: - return "Invalid number of extended data in sendArmCommand()\n"; - case MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM: - return "Invalid opcode given to waitArmCmdStatus()\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER: - return "Pointer to Mykonos device data structure is NULL\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_SPI: - return "Invalid spiSettings pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_RX: - return "Invalid device->rx pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB: - return "Invalid pointer within device->rx data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR: - return "Invalid RXFIR pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_TX: - return "Invalid device->tx pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB: - return "Invalid pointer within device->tx data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR: - return "Invalid TXFIR pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX: - return "Invalid device->obsRx pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXSUB: - return "Invalid pointer within device->obsRx data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR: - return "Invalid Sniffer FIR pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR: - return "Invalid ORX FIR pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL: - return "Invalid Orx gain control pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL: - return "Invalid Sniffer gain control pointer in device data structure\n"; - case MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER: - return "Invalid obsRx framer pointer in device data structure\n"; - case MYKONOS_ERR_INITSER_INV_PROFILE: - return "Invalid RX profile within device data structure detected in MYKONOS_setupSerializers()\n"; - case MYKONOS_ERR_INITDES_INV_TXPROFILE: - return "Invalid TX profile within device data structure detected in MYKONOS_setupDeserializers()\n"; - case MYKONOS_ERR_JESD204B_ILAS_MISMATCH: - return "Mismatch detected in MYKONOS_jesd204bIlasCheck()\n"; - case MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL: - return "Invalid channel specified in MYKONOS_programRxGainTable()\n"; - case MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE: - return "Invalid numGainIndicesinTable greater than possible number of gain indices for channel. \n"; - case MYKONOS_ERR_WRITE_CFG_MEMORY_FAILED: - return "Failed write to ARM memory in MYKONOS_writeArmProfile()\n"; - case MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM: - return "Invalid PCLKDIV parameter detected in MYKONOS_setupSerializers()\n"; - case MYKONOS_ERR_RXFRAMER_INV_FK_PARAM: - return "Invalid FK parameter detected in MYKONOS_setupJesd204bFramer()\n"; - case MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM: - return "Invalid FK paramter detected in MYKONOS_setupJesd204bObsRxFramer()\n"; - case MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM: - return "Invalid PCLKDIV paramter detected in MYKONOS_setupSerializers()\n"; - case MYKONOS_ERR_PU_OBSRXPATH_INV_LOSOURCE_PARAM: - return "Invalid LO Source for OBSRX data path \n"; - case MYKONOS_ERR_ARM_RADIOON_FAILED: - return "ARM command to move to radioOn state failed. \n"; - case MYKONOS_ERR_ARM_RADIOOFF_FAILED: - return "ARM command to move to radioOff state failed. \n"; - case MYKONOS_ERR_INV_RX_GAIN_MODE_PARM: - return "Invalid gain control mode detected in MYKONOS_setRxGainControlMode()\n"; - case MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM: - return "Invalid gain control mode detected in MYKONOS_setObsRxGainControlMode()\n"; - case MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT: - return "Invalid RX AGC structure detected at &device->rx->rxAgcCtrl in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM: - return "device->rx->rxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM: - return "device->rx->rxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM: - return "device->rx->rxAgcCtrl->apdHighThresh out of range in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM: - return "device->rx->rxAgcCtrl->apdLowThresh out of range in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_BLOCK_DET_DECAY_PARM: - return "device->rx->rxAgcCtrl->apdDecay out of range in MYKONOS_setupRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT: - return "Data structure for peakAgc not initialized when used in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT: - return "Data structure for powerAgc not initialized when used in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX: - return "device->rx->rxAgcCtrl->agcRx1MaxGainIndex out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX: - return "device->rx->rxAgcCtrl->agcRx1MinGainIndex out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX: - return "device->rx->rxAgcCtrl->agcRx2MaxGainIndex out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX: - return "device->rx->rxAgcCtrl->agcRx2MinGainIndex out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY: - return "device->rx->rxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION: - return "device->rx->rxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG: - return "device->rx->rxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC: - return "device->rx->rxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE: - return "device->rx->rxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE: - return "device->rx->rxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER: - return "device->rx->rxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH: - return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH: - return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH: - return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH: - return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP: - return "device->rx->rxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP: - return "device->rx->rxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP: - return "device->rx->rxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP: - return "device->rx->rxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE: - return "device->rx->rxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM: - return "device->rx->rxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM: - return "device->rx->rxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM: - return "device->rx->rxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE: - return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT: - return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadThreshCnt out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT: - return "device->rx->rxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT: - return "Invalid OBSRX AGC structure detected at &device->obsRx->orxAgcCtrl in MYKONOS_setupObsRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT: - return "Data structure for obsRx->orxAgcCtrl->peakAgc not initialized when used in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT: - return "Data structure for obsRx->orxAgcCtrl->powerAgc not initialized when used in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX: - return "device->obsRx->orxAgcCtrl->agcObsRxMaxGainIndex out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX: - return "device->obsRx->orxAgcCtrl->agcObsRxMinGainIndex out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_SELECT: - return "device->obsRx->orxAgcCtrl->agcObsRxSelect out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM: - return "device->obsRx->orxAgcCtrl->agcGainUpdateTime_us out of range in MYKONOS_setupObsRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM: - return "device->obsRx->orxAgcCtrl->agcPeakWaitTime out of range in MYKONOS_setupObsRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY: - return "device->obsRx->orxAgcCtrl->agcSlowLoopSettlingDelay out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasDuration out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdMeasConfig out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC: - return "device->obsRx->orxAgcCtrl->agcLowThsPreventGainIncrease out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE: - return "device->obsRx->orxAgcCtrl->agcPeakThresholdMode out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE: - return "device->obsRx->orxAgcCtrl->agcResetOnRxEnable out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER: - return "device->obsRx->orxAgcCtrl->agcEnableSyncPulseForGainCounter out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdUpperLowGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE: - return "device->obsRx->orxAgcCtrl->peakAgc->apdFastAttack or hb2FastAttack out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM: - return "device->obsRx->orxAgcCtrl->apdHighThresh out of range in MYKONOS_setupObsRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM: - return "device->obsRx->orxAgcCtrl->apdLowThresh out of range in MYKONOS_setupObsRxAgc()\n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowThresh out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->apdHighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->apdLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2HighGainStepAttack out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2LowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2VeryLowGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadEnable out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadDurationCnt out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT: - return "device->obsRx->orxAgcCtrl->peakAgc->hb2OverloadThresholdCnt out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP: - return "device->obsRx->orxAgcCtrl->powerAgc->pmdLowerHighGainStepRecovery out of range in MYKONOS_setupObsRxAgc() \n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK: - return "CAL PLL Lock event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP: - return "Clock PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK: - return "Clock PLL Lock event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP: - return "RX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK: - return "RX PLL Lock event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP: - return "TX PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK: - return "TX PLL Lock event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP: - return "Sniffer PLL Charge Pump Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK: - return "Sniffer PLL Lock event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE: - return "RX Baseband Filter Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE: - return "TX Baseband Filter Cal timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE: - return "RF DC Offset Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE: - return "ADC Tuner Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE: - return "Rx1 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE: - return "Rx2 ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE: - return "ObsRx ADC Profile Loading event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE: - return "Resistor Cal event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY: - return "ARM Busy event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE: - return "Initialize ARM event timed out in MYKONOS_waitForEvent()\n"; - case MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY: - return "ARM Mailbox Busy. Command not executed in MYKONOS_sendArmCommand()\n"; - case MYKONOS_ERR_PU_OBSRXPATH_ARMERROR: - return "ARM Command Error in MYKONOS_setObsRxPathSource()\n"; - case MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR: - return "Device not in radioOff/IDLE state. Error in MYKONOS_enableTrackingCals()\n"; - case MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR: - return "ARM command Error in MYKONOS_setRadioControlPinMode()\n"; - case MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR: - return "ARM Command Error in MYKONOS_enableTrackingCals()\n"; - case MYKONOS_ERR_SETRFPLL_ARMERROR: - return "ARM Command Error in MYKONOS_setRfPllFrequency()\n"; - case MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM: - return "device->tx->txProfile->txInputHbInterpolation out of range in MYKONOS_initialize(): valid = 1,2 or 4\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV: - return "device->clocks->clkPllVcoDiv value not supported in MYKONOS_loadAdcProfiles\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED: - return "Custom RX ADC Profile required\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED: - return "Custom ORX ADC Profile required\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED: - return "Custom SNRX ADC Profile required\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED: - return "Custom Loopback ADC profile required\n"; - case MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED: - return "WriteArmMemory call failed while writing the Loopback ADC profile into ARM memory\n"; - case MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED: - return "WriteArmMemory call failed while writing the Sniffer ADC profile into ARM memory\n"; - case MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED: - return "WriteArmMemory call failed while writing the ObsRx ADC profile into ARM memory\n"; - case MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED: - return "WriteArmMemory call failed while writing the RX ADC profile into ARM memory\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO: - return "SnRx profile has invalid ADC divider of 0, causing a divide by zero\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO: - return "ORx profile has invalid ADC divider of 0, causing a divide by zero\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO: - return "Rx profile has invalid ADC divider of 0, causing a divide by zero\n"; - case MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE: - return "If Tx Profile is valid, a matching ORx profile must be provided to set ADC divider and digital filtering for loopback calibrations\n"; - case MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION: - return "Invalid setting for avgDuration in MYKONOS_setupPaProtection(...)\n"; - case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP: - return "Invalid setting for attenStepSize in MYKONOS_setupPaProtection(...)\n"; - case MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_ENABLE: - return "Invalid setting for txAttenControlEnable in MYKONOS_setupPaProtection(...)\n"; - case MYKONOS_ERR_SETUP_PA_PROT_INV_POWER_THRESH: - return "Invalid setting for powerThreshold in MYKONOS_setupPaProtection(...)\n"; - case MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL: - return "Invalid TX channel selected for MYKONOS_getDacPower(...)\n"; - case MYKONOS_ERR_GET_DAC_PWR_INV_POINTER: - return "Cannot return DAC Power information (invalid pointer)\n"; - case MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER: - return "Cannot return PA Protection Flag Status information (invalid pointer)\n"; - case MYKONOS_ERR_GET_OBSRX_OVERLOADS_NULL_PARM: - return "MYKONOS_getObsRxPathOverloads() has null *obsRxOverloads parameter\n"; - case MYKONOS_ERR_GET_RX1_OVERLOADS_NULL_PARM: - return "MYKONOS_getRxPathOverloads() has null *rx1Overloads parameter\n"; - case MYKONOS_ERR_GET_RX2_OVERLOADS_NULL_PARM: - return "MYKONOS_getRxPathOverloads() has null *rx2Overloads parameter\n"; - case MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM: - return "MYKONOS_getRadioState() has null *radioStatus parameter\n"; - case MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM: - return "MYKONOS_abortInitCals() has null *calsCompleted parameter\n"; - case MYKONOS_ERR_WAIT_INITCALS_ARMERROR: - return "MYKONOS_waitInitCals() returned an ARM error\n"; - case MYKONOS_ERR_WAIT_INITCALS_NULL_PARAM: - return "MYKONOS_waitInitCals() has one or more null parameters\n"; - case MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM: - return "MYKONOS_checkPllsLockStatus() has a null *pllLockStatus parameter\n"; - case MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM: - return "MYKONOS_getTxFilterOverRangeStatus() has a null *txFilterStatus parameter\n"; - case MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM: - return "MYKONOS_programRxGainTable() has a null *gainTablePtr parameter\n"; - case MYKONOS_ERR_PROGRAMFIR_NULL_PARM: - return "MYKONOS_programFir() has a null *firFilter parameter\n"; - case MYKONOS_ERR_PROGRAMFIR_COEFS_NULL: - return "MYKONOS_programFir() has a null coef array in *firFilter structure\n"; - case MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM: - return "MYKONOS_readDeframerStatus() has a null *deframerStatus parameter\n"; - case MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM: - return "MYKONOS_readDeframerPrbscounters() has a null *prbsErrorCount parameter\n"; - case MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM: - return "MYKONOS_readOrxFramerStatus() has a null *obsFramerStatus parameter\n"; - case MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM: - return "MYKONOS_readRxFramerStatus() has a null *framerStatus parameter\n"; - case MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM: - return "MYKONOS_waitArmCmdStatus() has a null *cmdStatByte parameter\n"; - case MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM: - return "MYKONOS_readArmCmdStatus() has one or more null pointer parameters\n"; - case MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM: - return "MYKONOS_readArmCmdStatusByte() has an invalid opcode parameter\n"; - case MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM: - return "MYKONOS_readArmCmdStatusByte() has a null *cmdStatByte parameter\n"; - case MYKONOS_ERR_ARMCMD_NULL_PARM: - return "MYKONOS_sendArmCommand() has a null *extendedData parameter\n"; - case MYKONOS_ERR_WRITEARMMEM_NULL_PARM: - return "MYKONOS_writeArmMem() has a null *data parameter\n"; - case MYKONOS_ERR_LOADBIN_NULL_PARAM: - return "MYKONOS_loadArmFromBinary() has a null *binary parameter\n"; - case MYKONOS_ERR_LOADARMCON_NULL_PARAM: - return "MYKONOS_loadArmConcurrent() has a null *binary parameter\n"; - case MYKONOS_ERR_GETTX1ATTEN_NULL_PARM: - return "MYKONOS_getTx1Attenuation() has NULL tx1Attenuation_mdB parameter\n"; - case MYKONOS_ERR_GETTX2ATTEN_NULL_PARM: - return "MYKONOS_getTx2Attenuation() has NULL tx2Attenuation_mdB parameter\n"; - case MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM: - return "Invalid serializer Lanes Enable parameter in Rx framer structure\n"; - case MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM: - return "Invalid serializer Lanes Enable parameter in ObsRx framer structure\n"; - case MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID: - return "Can not enable Tx NCO when Tx Profile is invalid\n"; - case MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID: - return "Invalid Tx1 NCO frequency\n"; - case MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID: - return "Invalid Tx2 NCO frequency\n"; - case MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM: - return "Function parameter has NULL pointer in MYKONOS_jesd204bIlasCheck()\n"; - case MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV: - return "CLKPLL refclk divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; - case MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV: - return "CLKPLL HSDIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; - case MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV: - return "CLKPLL VCODIV divider was read back as an invalid setting in MYKONOS_getRfPllFrequency()\n"; - case MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM: - return "MYKONOS_getRx1DecPower() has a null *rx1DecPower_mdBFS parameter\n"; - case MYKONOS_ERR_GET_RX1_DEC_POWER_NUM_SAMPLES: - return "MYKONOS_getRx1DecPower() numSamples greater than agcGainUpdateCounter\n"; - case MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM: - return "MYKONOS_getRx2DecPower() has a null *rx2DecPower_mdBFS parameter\n"; - case MYKONOS_ERR_GET_RX2_DEC_POWER_NUM_SAMPLES: - return "MYKONOS_getRx2DecPower() numSamples greater than agcGainUpdateCounter\n"; - case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM: - return "MYKONOS_getObsRxDecPower() has a null *obsRxDecPower_mdBFS parameter\n"; - case MYKONOS_ERR_GET_OBSRX_DEC_POWER_NUM_SAMPLES: - return "MYKONOS_getObsRxDecPower() numSamples greater than agcGainUpdateCounter\n"; - case MYKONOS_ERR_GETARMVER_NULL_PARM: - return "MYKONOS_getArmVersion() has a NULL pointer in one of the function parameters\n"; - case MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR: - return "ARM is not in the RadioOff state before MYKONOS_enableDpdTracking(), call MYKONOS_radioOff()\n"; - case MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE: - return "MYKONOS_restoreDpdModel() supplied DPD Model Data Buffer is incorrect size\n"; - case MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG: - return "The ARM reported a error while in MYKONOS_restoreDpdModel().\n"; - case MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL: - return "MYKONOS_restoreDpdModel() invalid txChannel specified\n"; - case MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE: - return "MYKONOS_saveDpdModel() supplied DPD Model Data Buffer is incorrect size\n"; - case MYKONOS_ERR_SAVDPDMOD_ARMSTATE: - return "ARM is not in the RadioOff state before MYKONOS_saveDpdModel(), call MYKONOS_radioOff()\n"; - case MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL: - return "MYKONOS_saveDpdModel() invalid txChannel specified\n"; - case MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR: - return "ARM is not in the RadioOff state before MYKONOS_enableClgcTracking(), call MYKONOS_radioOff()\n"; - case MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV: - return "Tx or ORx profile is not valid, both are necessary for DPD features in MYKONOS_configDpd()\n"; - case MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT: - return "device->tx->dpdConfig structure has NULL pointer in MYKONOS_configDpd()\n"; - case MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG: - return "The ARM reported a error while writing to an ARM config structure in MYKONOS_writeArmCfgStruct()\n"; - case MYKONOS_ERR_CFGDPD_INV_DPDDAMPING: - return "ERROR: device->tx->dpdConfig->damping parameter is out of range (0-15)\n"; - case MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES: - return "ERROR: device->tx->dpdConfig->samples parameter is out of range (64 - 32768)\n"; - case MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS: - return "ERROR: device->tx->dpdConfig->numWeights parameter is out of range (0-3)\n"; - case MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH: - return "ERROR: device->tx->dpdConfig->outlierThreshold parameter is out of range\n"; - case MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT: - return "ERROR: device->tx->dpdConfig->modelPriorWeight parameter is out of range (Valid 0-32)\n"; - case MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN: - return "ERROR: device->tx->clgcConfig->tx1DesiredGain or tx2DesiredGain parameter is out of range\n"; - case MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT: - return "ERROR: device->tx->clgcConfig->tx1AttenLimit or tx2AttenLimit parameter is out of range\n"; - case MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO: - return "ERROR: device->tx->clgcConfig->tx1ControlRatio or tx2ControlRatio parameter is out of range\n"; - case MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY: - return "ERROR: device->tx->dpdConfig->additionalDelayOffset parameter is out of range\n"; - case MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL: - return "ERROR: device->tx->dpdConfig->pathDelayPnSeqLevel parameter is out of range\n"; - case MYKONOS_ERR_CFGDPD_INV_MODELVERSION: - return "ERROR: device->tx->dpdConfig->modelVersion parameter is out of range\n"; - case MYKONOS_ERR_READARMCFG_ARMERRFLAG: - return "ERROR: MYKONOS_readArmConfig failed due to an ARM error\n"; - case MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM: - return "MYKONOS_getPendingTrackingCals() has NULL function parameter\n"; - case MYKONOS_ERR_ARMCMDSTATUS_ARMERROR: - return "MYKONOS_waitArmCmdStatus() exited due to ARM error for the desired ARM opcode\n"; - case MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT: - return "MYKONOS_waitArmCmdStatus() timed out waiting for the ARM to complete the requested command\n"; - case MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR: - return "ARM returned an error while trying to get the ObsRx Path source in MYKONOS_getObsRxPathSource()\n"; - case MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT: - return "MYKONOS_getDpdConfig() could not complete due to a NULL pointer to device->tx->dpdConfig structure\n"; - case MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV: - return "The Tx and ORx profiles must be valid for DPD related functions\n"; - case MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG: - return "MYKONOS_getDpdStatus() reported an ARM error with the ARM Get command\n"; - case MYKONOS_ERR_GETDPDSTATUS_NULLPARAM: - return "MYKONOS_getDpdStatus() has NULL pointer in the function parameter\n"; - case MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT: - return "Observation profile not valid, device->obsRx structure is NULL in MYKONOS_setDefaultObsRxPath()\n"; - case MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM: - return "MYKONOS_getClgcStatus() has NULL clgcStatus parameter\n"; - case MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG: - return "ARM reported an error with the ARM GET command during MYKONOS_getClgcStatus()\n"; - case MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM: - return "MYKONOS_getDeframerFifoDepth() function parameter fifoDepth is a NULL pointer\n"; - case MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM: - return "MYKONOS_getDeframerFifoDepth() function parameter readEnLmfcCount is a NULL pointer\n"; - case MYKONOS_ERR_GETDPDSTATUS_INV_CH: - return "MYKONOS_getDpdStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n"; - case MYKONOS_ERR_GETCLGCSTATUS_INV_CH: - return "MYKONOS_getClgcStatus() txChannel parameter is not valid (TX1 and TX2 are the only valid options)\n"; - case MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE: - return "Invalid Tx profile: When using Tx Input halfband, IQ rate must not exceed 160MSPS\n"; - case MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE: - return "Invalid Tx profile: When using Tx Input halfband 0, IQ rate must not exceed 80MSPS\n"; - case MYKONOS_ERR_RXFIR_TAPSEXCEEDED: - return "Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; - case MYKONOS_ERR_ORXFIR_TAPSEXCEEDED: - return "ORx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; - case MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED: - return "Sniffer Rx PFIR can not be clocked fast enough to handle the number of FIR coefficents provided\n"; - case MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM: - return "Invalid number of Tx FIR coefficients\n"; - case MYKONOS_ERR_TXFIR_INV_NUMROWS: - return "Invalid number of PFIR coefficient rows\n"; - case MYKONOS_ERR_TXFIR_TAPSEXCEEDED: - return "Too many Tx PFIR taps for the IQ sample rate. FIR processing clock can not run fast enough to handle the number of taps\n"; - case MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM: - return "MYKONOS_getInitCalStatus() has a null pointer in parameter list\n"; - case MYKONOS_ERR_GETINITCALSTATUS_ARMERROR: - return "MYKONOS_getInitCalStatus() returned an ARM error while getting the init cal status information"; - case MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV: - return "Tx and ObsRx profiles must be valid to use the CLGC feature in MYKONOS_configClgc()\n"; - case MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT: - return "CLGC config structure is NULL in device->tx->clgcConfig in MYKONOS_configClgc()\n"; - case MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV: - return "Could not read back CLGC status because Tx and ORx profiles are not valid\n"; - case MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT: - return "Could not read back CLGC status because return structure device->tx->clgcConfig pointer is NULL\n"; - case MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM: - return "device structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n"; - case MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT: - return "device->clocks structure pointer is NULL in MYKONOS_calculateDigitalClocks()\n"; - case MYKONOS_ERR_NULL_DEVICE_PARAM: - return "The device pointer in the calling function's parameter list is a NULL pointer\n"; - case MYKONOS_ERR_CALCDEVCLK_NULLPARAM: - return "MYKONOS_calculateScaledDeviceClk_kHz() has a NULL pointer in one of the function parameters\n"; - case MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY: - return "CLGC Additional Delay parameter is out of range in MYKONOS_configClgc\n"; - case MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL: - return "CLGC PN Sequence level parameter is out of range in MYKONOS_configClgc\n"; - case MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV: - return "The Tx and ORx profiles must be valid to use the VSWR feature in MYKONOS_configVswr()\n"; - case MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR: - return "ARM must be in radioOff state to configure the VSWR config parameters in MYKONOS_configVswr()\n"; - case MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN: - return "VSWR 3.3v GPIO pin selection is out of range (0-11) in MYKONOS_configVswr()\n"; - case MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL: - return "VSWR init PN sequence level is out of range in MYKONOS_configVswr()\n"; - case MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY: - return "VSWR additionalDelay member is out of range in MYKONOS_configVswr()\n"; - case MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT: - return "device->tx->vswrConfig pointer is null in MYKONOS_confgiVswr()\n"; - case MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT: - return "device->tx->vswrConfig pointer is null in MYKONOS_getVswrConfig()\n"; - case MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV: - return "Tx and ORx profiles must be valid in MYKONOS_getVswrConfig()\n"; - case MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG: - return "ARM returned an error while attempting to read the VSWR status structure\n"; - case MYKONOS_ERR_GETVSWRSTATUS_INV_CH: - return "Invalid Tx channel parameter passed to MYKONOS_getVswrStatus()\n"; - case MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM: - return "vswrStatus function parameter is null in MYKONOS_getVswrStatus\n"; - case MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX: - return "Max gain index bigger than max gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX: - return "Min gain index lower than min gain index loaded table in MYKONOS_setRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL: - return "Wrong RX channel selected in MYKONOS_setRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL: - return "Wrong read back channel in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX: - return "Max gain index bigger than max gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX: - return "Min gain index lower than min gain index loaded table in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL: - return "Wrong observation channel selected in MYKONOS_setObsRxAgcMinMaxGainIndex().\n"; - case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE: - return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx1TempGainComp().\n"; - case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP: - return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx1TempGainComp().\n"; - case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE: - return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setRx2TempGainComp().\n"; - case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP: - return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setRx2TempGainComp().\n"; - case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE: - return "The temp gain compensation is outside range (-3000mdB to 3000mdB) in MYKONOS_setObsRxTempGainComp().\n"; - case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP: - return "Not valid temp gain compensation, step size is 250mdB in MYKONOS_setObsRxTempGainComp().\n"; - case MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL: - return "rx1TempCompGain_mdB pointer is null MYKONOS_getRx1TempGainComp().\n"; - case MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL: - return "rx2TempCompGain_mdB pointer is null MYKONOS_getRx2TempGainComp().\n"; - case MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL: - return "obsRxTempCompGain_mdB pointer is null MYKONOS_getObsRxTempGainComp().\n"; - case MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM: - return "Function parameter mykonosOrxQecStatus_t is a NULL pointer in MYKONOS_getOrxQecStatus().\n"; - case MYKONOS_ERR_GETORXQECSTATUS_INV_CH: - return "Channel selection not valid in MYKONOS_getOrxQecStatus().\n"; - case MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG: - return "ARM command error in MYKONOS_getOrxQecStatus().\n"; - case MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM: - return "Function parameter mykonosRxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n"; - case MYKONOS_ERR_GETRXQECSTATUS_INV_CH: - return "Channel selection not valid in MYKONOS_getRxQecStatus().\n"; - case MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG: - return "ARM command error in MYKONOS_getRxQecStatus().\n"; - case MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM: - return "Function parameter mykonosTxQecStatus_t is a NULL pointer in MYKONOS_getRxQecStatus().\n"; - case MYKONOS_ERR_GETTXQECSTATUS_INV_CH: - return "Channel selection not valid in MYKONOS_getTxQecStatus().\n"; - case MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG: - return "ARM command error in MYKONOS_getTxQecStatus().\n"; - case MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM: - return "Function parameter mykonosTxLolStatus_t is a NULL pointer in MYKONOS_getTLolStatus().\n"; - case MYKONOS_ERR_GETTXLOLSTATUS_INV_CH: - return "Channel selection not valid in MYKONOS_getTLolStatus().\n"; - case MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG: - return "ARM command error in MYKONOS_getTLolStatus().\n"; - case MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV: - return "Not valid calibration passed to MYKONOS_rescheduleTrackingCal().\n"; - case MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG: - return "ARM error in MYKONOS_rescheduleTrackingCal().\n"; - case MYKONOS_ERR_ARMSTATE_EXCEPTION: - return "ARM system problem has been detected.\n"; - case MYKONOS_ERR_ARMSTATE_CAL_ERROR: - return "ARM has detected an error in the tracking calibrations.\n"; - case MYKONOS_ERR_ARMSTATE_PROFILE_ERROR: - return "ARM has detected an illegal profile.\n"; - case MYKONOS_ERR_WAITARMCSTATE_TIMEOUT: - return "Timeout occurred in MYKONOS_checkArmState().\n"; - case MYKONOS_ERR_GET_API_VERSION_NULL_PARAM: - return "Null parameter passed to the function MYKONOS_getApiVersion().\n"; - case MYKONOS_ERR_GETPRODUCTID_NULL_PARAM: - return "Null parameter passed to the function MYKONOS_getProductId().\n"; - case MYKONOS_ERR_TXPROFILE_IQRATE: - return "Tx Profile IQ rate out of range.\n"; - case MYKONOS_ERR_TXPROFILE_RFBW: - return "Tx Profile RF bandwidth out of range.\n"; - case MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION: - return "Tx Filter interpolation not valid.\n"; - case MYKONOS_ERR_TXPROFILE_FIR_COEFS: - return "Tx FIR filter not valid.\n"; - case MYKONOS_ERR_RXPROFILE_RXCHANNEL: - return " Rx channel is not valid.\n"; - case MYKONOS_ERR_RXPROFILE_IQRATE: - return "Receiver profile out of range IQ rate.\n"; - case MYKONOS_ERR_RXPROFILE_RFBW: - return "Receiver profile out of range RF bandwidth.\n"; - case MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION: - return "Receiver profile not valid filter decimation setting.\n"; - case MYKONOS_ERR_RXPROFILE_FIR_COEFS: - return "Receiver profile FIR filter not valid.\n"; - case MYKONOS_ERR_RXPROFILE_ADCDIV: - return "Receiver profile not valid ADC divider.\n"; - case MYKONOS_ERR_PROFILES_HSDIGCLK: - return "Profile combinations loaded are not valid.\n"; - case MYKONOS_ERR_RESET_TXLOL_INV_PARAM: - return "Selected channel is not valid.\n"; - case MYKONOS_ERR_RESET_TXLOL_ARMERROR: - return "ARM command error in MYKONOS_resetExtTxLolChannel().\n"; - case MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV: - return "Not valid calibration mask passed for trackCals.\n"; - case MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG: - return "ARM error flag set.\n"; - case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG: - return "ARM error flag set.\n"; - case MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR: - return "ARM command error.\n"; - case MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM: - return "Null parameter passed for trackCals.\n"; - case MYKONOS_ERR_SETSTATE_TRACK_CAL_INV: - return "Not valid calibration passed.\n"; - case MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG: - return "ARM command error.\n"; - case MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM: - return "Null parameter passed to trackCalState.\n"; - case MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG: - return "ARM command error flag set.\n"; - case MYKONOS_ERR_GETSTATE_TRACK_ARMERROR: - return "ARM command error.\n"; - case MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL: - return "Tx channel is not valid (Valid ENUM values: TX1 or TX2 only).\n"; - case MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG: - return "ARM command flag error set.\n"; - case MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN: - return "CLGC gain parameter is out of range, valid range is from -10000 to 10000.\n"; - case MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL: - return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2).\n"; - case MYKONOS_ERR_SETDPDACT_INV_STATE: - return "Invalid Actuator state, valid states are 0-disable and 1-enable.\n"; - case MYKONOS_ERR_SETDPDACT_ARMERRFLAG: - return "ARM command flag error set.\n"; - case MYKONOS_ERR_SETRFPLL_LF_PLLNAME: - return "Invalid pllName requested in MYKONOS_setRfPllLoopFilter()\n"; - case MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY: - return "Invalid stability value requested in MYKONOS_setRfPllLoopFilter()\n"; - case MYKONOS_ERR_SETRFPLL_LF_ARMERROR: - return "ARM Command Error in MYKONOS_setRfPllLoopFilter()\n"; - case MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH: - return "Invalid Tx/Rx value bandwith requested in MYKONOS_setRfPllLoopFilter()\n"; - case MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH: - return "Invalid Sniffer value bandwith in MYKONOS_setRfPllLoopFilter()\n"; - case MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME: - return "Invalid pllName requested in MYKONOS_getRfPllLoopFilter()\n"; - case MYKONOS_ERR_GETRFPLL_LF_ARMERROR: - return "ARM Command Error in MYKONOS_getRfPllLoopFilter()\n"; - case MYKONOS_ERR_GETRFPLL_LF_NULLPARAM: - return "NULL pointer in function parameter for MYKONOS_getRfPllLoopFilter()\n"; - case MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT: - return "Invalid value passed as parameter for measureCount to function MYKONOS_setRfDcOffsetCnt().\n"; - case MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT: - return "The measureCount value passed to function MYKONOS_setRfDcOffsetCnt() is less than the minimum limit allowed.\n"; - case MYKONOS_ERR_DC_OFFSET_INV_CHAN: - return "Invalid channel passed as parameter, for valid channel refer mykonosDcOffsetChannels_t enum.\n"; - case MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT: - return "Null parameter passed for measureCount MYKONOS_getRfDcOffsetCnt().\n"; - case MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT: - return "Invalid MShift value passed as parameter to function MYKONOS_setDigDcOffsetMShift().\n"; - case MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT: - return "MShift passed to the function MYKONOS_getDigDcOffsetMShift() is NULL.\n"; - case MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK: - return "Invalid enable mask passed to the function MYKONOS_setDigDcOffsetEn().\n"; - case MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK: - return "Enable mask passed to the function MYKONOS_getDigDcOffsetEn() is NULL.\n"; - case MYKONOS_ERR_RESETDPD_WRONG_PARAM: - return "reset parameter passed to function MYKONOS_resetDpd() is not valid, possible values are: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR \n"; - case MYKONOS_ERR_RESETDPD_ARMERRFLAG: - return "ARM command flag error set in function MYKONOS_resetDpd().\n"; - case MYKONOS_ERR_CFGCLGC_INV_THRESHOLD: - return "tx1RelThreshold or tx2RelThreshold parameter is out of range in function MYKONOS_configClgc().\n"; - case MYKONOS_ERR_RESETDPD_INV_TXCHANNEL: - return "Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2 in function MYKONOS_resetDpd().\n"; - case MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM: - return "pathDelay structure is null in function MYKONOS_setPathDelay().\n"; - case MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE: - return "path delay not valid range in MYKONOS_setPathDelay(), valid ranges are from 0 to 4095 at 1/16 sample resolution of ORx sample rate.\n"; - case MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM: - return "pathDelay structure is null in function MYKONOS_getPathDelay().\n"; - case MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION: - return "invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t.\n"; - case MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG: - return "Arm error while reading path delay for the selected calibration status.\n"; - case MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM: - return "dpdErrCnt is null in function MYKONOS_getDpdErrorCounters().\n"; - case MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH: - return "invalid selection for getting the error counters tx channel in MYKONOS_getDpdErrorCounters().\n"; - case MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG: - return "Arm error while reading the error counters for the DPD status MYKONOS_getDpdErrorCounters().\n"; - case MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT: - return "Passed structure is null in MYKONOS_setDpdBypassConfig().\n"; - case MYKONOS_ERR_SETDPDACT_INV_ACTMODE: - return "Invalid mode passed detected in MYKONOS_setDpdBypassConfig(), actConfig->bypassActuatorMode for valid modes mykonosDpdResetMode_t.\n"; - case MYKONOS_ERR_SETDPDACT_INV_LEVEL: - return "Passed actConfig->bypassActuatorLevel outside the range in MYKONOS_setDpdBypassConfig().\n"; - case MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT: - return "Passed structure is null in MYKONOS_getDpdBypassConfig().\n"; - case MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT: - return "Passed structure is null in MYKONOS_setDpdActuatorCheck().\n"; - case MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE: - return "Invalid mode detected in MYKONOS_setDpdActuatorCheck(), actCheck->actuatorGainCheckMode for valid modes mykonosDpdResetMode_t.\n"; - case MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL: - return "Passed actCheck->actuatorGainCheckLevel outside the range in MYKONOS_setDpdActuatorCheck().\n"; - case MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT: - return "Passed structure is null in MYKONOS_getDpdActuatorCheck().\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT: - return "Passed structure is null in MYKONOS_setClgcAttenTuningConfig().\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE: - return "Invalid mode detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), for valid modes ::mykonosClgcAttenTuningMode_t.\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET: - return "Invalid AttenTuningPreset detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 839 (0 to 41.95dB).\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE: - return "Invalid AttenTuningRange detected for attRangeCfg member in MYKONOS_getClgcAttenTuningConfig(), valid range is from 0 to 420 (0 to 21dB).\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS: - return "Invalid Tx1 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n"; - case MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS: - return "Invalid Tx2 AttenTuningRange and AttenTuningPreset combination in MYKONOS_getClgcAttenTuningConfig().\n"; - case MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT: - return "Passed structure is null in MYKONOS_getClgcAttenTuningConfig().\n"; - - default: - return "Unknown error was encountered.\n"; - } - -#endif -} - -/** - * \brief Calculates the scaled device clock frequency at the input of the - * CLKPLL or RFPLL - * - * Use this helper function any time the scaled device clock frequency is needed. - * - * Dependencies - * - device->clocks->deviceClock_kHz - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param scaledRefClk_kHz Output: The returned scaled reference clock for the device's PLLs - * \param deviceClkDiv Output: The device clock divider setting that gets set in the devices SPI register. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_NULL_DEVICE_PARAM Function parameter device pointer is NULL - * \retval MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM The scaled PLL refclk frequency is out of range (40MHz to 80MHz) - * \retval MYKONOS_ERR_CALCDEVCLK_NULLPARAM Function parameter scaledRefClk_kHz or deviceClkDiv has a NULL pointer - */ -static mykonosErr_t MYKONOS_calculateScaledDeviceClk_kHz(mykonosDevice_t *device, uint32_t *scaledRefClk_kHz, uint8_t *deviceClkDiv) -{ - uint32_t deviceClock_kHz = 0; - - if ((device == NULL) || (device->clocks == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_NULL_DEVICE_PARAM, getMykonosErrorMessage(MYKONOS_ERR_NULL_DEVICE_PARAM)); - return MYKONOS_ERR_NULL_DEVICE_PARAM; - } - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_calculateScaledDeviceClk_kHz()\n"); -#endif - - deviceClock_kHz = device->clocks->deviceClock_kHz; - - if ((scaledRefClk_kHz == NULL) || (deviceClkDiv == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDEVCLK_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_CALCDEVCLK_NULLPARAM)); - return MYKONOS_ERR_CALCDEVCLK_NULLPARAM; - } - - /* scaled Ref Clock at input to CLKPLL must be in range 40-80MHz. */ - if (deviceClock_kHz > 20000 && deviceClock_kHz <= 40000) - { - *scaledRefClk_kHz = deviceClock_kHz << 1; - *deviceClkDiv = 3; - } /* x2 */ - else if (deviceClock_kHz > 40000 && deviceClock_kHz <= 80000) - { - *scaledRefClk_kHz = deviceClock_kHz; - *deviceClkDiv = 0; - } /* x1 */ - else if (deviceClock_kHz > 80000 && deviceClock_kHz <= 160000) - { - *scaledRefClk_kHz = deviceClock_kHz >> 1; - *deviceClkDiv = 1; - } /* div2 */ - else if (deviceClock_kHz > 160000 && deviceClock_kHz <= 320000) - { - *scaledRefClk_kHz = deviceClock_kHz >> 2; - *deviceClkDiv = 2; - } /* div4 */ - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM)); - return MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM; - } - return MYKONOS_ERR_OK; -} - -/** - * \brief Resets the JESD204B Deframer - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_resetDeframer(mykonosDevice_t *device) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDeframer()\n"); -#endif - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x03); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_RESET, 0x00); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the JESD204B Serializers - * - * This function uses the Rx framer and ObsRx framer structures to setup the 4 - * serializer lanes that are shared between the two framers. If the Rx profile is valid - * the serializer amplitude and preEmphasis are used from the Rx framer. If only the ObsRx - * profile is valid, the obsRx framer settings are used. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->rx->framer->M - * - device->rx->framer->serializerAmplitude - * - device->rx->framer->preEmphasis - * - device->rx->framer->serializerLanesEnabled - * - device->rx->framer->invertLanePolarity - * - device->obsRx->framer->serializerLanesEnabled - * - device->obsRx->framer->invertLanePolarity - * - device->obsRx->framer->M - * - device->obsRx->framer->serializerLanesEnabled - * - device->obsRx->framer->serializerAmplitude - * - device->obsRx->framer->preEmphasis - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_INITSER_INV_VCODIV_PARM Mykonos CLKPLL has invalid VCO divider, verify CLKPLL config - * \retval MYKONOS_ERR_SER_LANE_CONFLICT_PARM When both Rx and ObsRx framers are enabled, framers can not share the same physical lane. - * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM Rx Framer M can only = 1 when Real IF mode is enabled - * \retval MYKONOS_ERR_SER_INV_M_PARM Invalid Rx Framer M (valid 1,2,4) - * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM Invalid Rx framer serializerLanesEnabled (valid 0-15) - * \retval MYKONOS_ERR_SER_INV_AMP_PARM Invalid Rx serializer amplitude (valid 0-31) - * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM Invalid Rx serializer pre-emphesis (valid 0-7) - * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM Invalid Rx serializer PN invert setting (valid 0-15) - * \retval MYKONOS_ERR_SER_INV_L_PARM Invalid Rx serializer lanes enabled (must use 1, 2 or 4 lanes) - * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM Invalid Rx serializer lane rate (valid 614.4Mbps - 6144Mbps) - * - * \retval MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM - * \retval MYKONOS_ERR_SER_INV_LANEEN_PARM - * \retval MYKONOS_ERR_SER_INV_AMP_PARM - * \retval MYKONOS_ERR_SER_INV_PREEMP_PARM - * \retval MYKONOS_ERR_SER_INV_LANEPN_PARM - * \retval MYKONOS_ERR_SER_INV_L_PARM - * \retval MYKONOS_ERR_SER_INV_LANERATE_PARM - * - * \retval MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM Necessary lane rates for Rx and ObsRx framer can not be obtained with possible divider settings - * \retval MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT HSCLK is not an integer multiple of the lane clock rate - * \retval MYKONOS_ERR_SER_INV_TXSER_DIV_PARM No valid Tx serializer divider to obtain desired lane rates - * \retval MYKONOS_ERR_INITSER_INV_PROFILE Rx/ObsRx and sniffer profiles are not valid - can not config serializers - * \retval MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM Invalid Rx framer PCLK divider - * \retval MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM Invalid ORx/Sniffer framer PCLK divider - * - */ -mykonosErr_t MYKONOS_setupSerializers(mykonosDevice_t *device) -{ - uint8_t serializerHalfRateReg = 0; - uint8_t txser_div = 0; - uint8_t txser_div_reg = 0; - uint32_t clkPllVcoFrequency_kHz = 0; - uint32_t hsclkRate_kHz = 0; - uint32_t rxLaneRate_kHz = 0; - uint32_t obsRxLaneRate_kHz = 0; - uint32_t fasterLaneRate_kHz = 0; - uint32_t slowerLaneRate_kHz = 0; - uint8_t modHsLaneRate = 0; - uint8_t rxL = 0; - uint8_t obsRxL = 0; - uint8_t i = 0; - uint8_t amplitudeEmphasis = 0; - uint8_t lanePowerDown = 0x00; - mykonosVcoDiv_t vcoDiv = VCODIV_1; - uint8_t rxLanePn = 0; - uint8_t obsRxLanePn = 0; - - uint32_t hsDigClkdiv4_5_kHz = 0; - uint32_t rxPclkDiv = 0; - uint32_t obsRxPclkDiv = 0; - uint32_t tempPclkDiv = 0; - uint32_t rxFramerPclk_kHz = 0; - uint32_t obsRxFramerPclk_kHz = 0; - uint8_t rxSyncbSelect = 0; - uint8_t obsRxSyncbSelect = 0; - - static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1P5 = 6144000; /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */ - static const uint32_t MAX_HSCLK_KHZ_IF_VCODIV1 = 8000000; /* max VCO div1 output is 8000Mhz. This limits VCO to 8000MHz */ - static const uint32_t MIN_SERIALIZER_RATE_KHZ = 614400; /* max serializer lane rate = 0.6144 Gbps */ - static const uint32_t MAX_SERIALIZER_RATE_KHZ = 6144000; /* max serializer lane rate = 6.144 Gbps */ -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupSerializers()\n"); -#endif - - vcoDiv = device->clocks->clkPllVcoDiv; - clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz; - - switch (vcoDiv) - { - case VCODIV_1: - hsclkRate_kHz = clkPllVcoFrequency_kHz; - - /* max VCO /1 output is 8000Mhz. This limits VCO to 8000MHz */ - if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM)); - return MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM; - } - - break; - - case VCODIV_1p5: - hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10; - - /* max VCO /1.5 output is 6144Mhz. This limits VCO to 9216MHz */ - if (hsclkRate_kHz > MAX_HSCLK_KHZ_IF_VCODIV1P5) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM)); - return MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM; - } - - break; - - case VCODIV_2: - hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1; - break; - - case VCODIV_3: - hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10; - break; - - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_VCODIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_VCODIV_PARM)); - return MYKONOS_ERR_INITSER_INV_VCODIV_PARM; - } - } - - if ((device->profilesValid & RX_PROFILE_VALID) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) - { - if (device->rx->framer->serializerLanesEnabled & device->obsRx->framer->serializerLanesEnabled) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_CONFLICT_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_CONFLICT_PARM)); - return MYKONOS_ERR_SER_LANE_CONFLICT_PARM; - } - } - - lanePowerDown = 0x9F; - if (device->profilesValid & RX_PROFILE_VALID) - { - if (device->rx->framer->M == 1 && !(device->rx->realIfData)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM)); - return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM; - } - - if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_M_PARM)); - return MYKONOS_ERR_SER_INV_M_PARM; - } - - for (i = 0; i < 4; i++) - { - rxL += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01); - } - - if (device->rx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM)); - return MYKONOS_ERR_SER_INV_LANEEN_PARM; - } - - if (device->rx->framer->serializerAmplitude > 31) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM)); - return MYKONOS_ERR_SER_INV_AMP_PARM; - } - - if (device->rx->framer->preEmphasis > 7) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM)); - return MYKONOS_ERR_SER_INV_PREEMP_PARM; - } - - if (device->rx->framer->invertLanePolarity > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM)); - return MYKONOS_ERR_SER_INV_LANEPN_PARM; - } - if ((rxL != 1) && (rxL != 2) && (rxL != 4)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM)); - return MYKONOS_ERR_SER_INV_L_PARM; - } - - rxLaneRate_kHz = device->rx->rxProfile->iqRate_kHz * 20 * device->rx->framer->M / rxL; - lanePowerDown &= (~(device->rx->framer->serializerLanesEnabled)); - - if ((rxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (rxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); - return MYKONOS_ERR_SER_INV_LANERATE_PARM; - } - } - - if ((device->obsRx->framer != NULL) && (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID))) - { - if ((device->obsRx->framer->M == 1) && !(device->obsRx->realIfData)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM)); - return MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM; - } - - for (i = 0; i < 4; i++) - { - obsRxL += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01); - } - - if (device->obsRx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEEN_PARM)); - return MYKONOS_ERR_SER_INV_LANEEN_PARM; - } - - if (device->obsRx->framer->serializerAmplitude > 31) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_AMP_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_AMP_PARM)); - return MYKONOS_ERR_SER_INV_AMP_PARM; - } - - if (device->obsRx->framer->preEmphasis > 7) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_PREEMP_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_PREEMP_PARM)); - return MYKONOS_ERR_SER_INV_PREEMP_PARM; - } - - if (device->obsRx->framer->invertLanePolarity > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANEPN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANEPN_PARM)); - return MYKONOS_ERR_SER_INV_LANEPN_PARM; - } - - if ((obsRxL != 0) && (obsRxL != 1) && (obsRxL != 2) && (obsRxL != 4)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_SER_INV_L_PARM)); - return MYKONOS_ERR_SER_INV_L_PARM; - } - - /* check for valid pointer */ - if (obsRxL == 0) - { - /* Allow ORx receiver to work but disable Obs Rx framer link - valid on a DPD-enabled transceiver */ - obsRxLaneRate_kHz = 0; - } - else if (device->profilesValid & ORX_PROFILE_VALID) - { - obsRxLaneRate_kHz = device->obsRx->orxProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL; - } - else if (device->profilesValid & SNIFF_PROFILE_VALID) - { - obsRxLaneRate_kHz = device->obsRx->snifferProfile->iqRate_kHz * 20 * device->obsRx->framer->M / obsRxL; - } - - lanePowerDown &= (~(device->obsRx->framer->serializerLanesEnabled)); - - if ((obsRxLaneRate_kHz != 0) && ((obsRxLaneRate_kHz < MIN_SERIALIZER_RATE_KHZ) || (obsRxLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); - return MYKONOS_ERR_SER_INV_LANERATE_PARM; - } - } - - /* checking for RX and OBSRX effective lane rates match */ - /* Need to account for oversampling, verify that the 2 lane rate are integer related */ - - if ((rxLaneRate_kHz > 0) && (obsRxLaneRate_kHz > 0)) - { - fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz); - slowerLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (obsRxLaneRate_kHz) : (rxLaneRate_kHz); - - /* Verify that lane rates are integer multiples of each other */ - if ((fasterLaneRate_kHz % slowerLaneRate_kHz) != 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM)); - return MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM; - } - } - else - { - fasterLaneRate_kHz = (rxLaneRate_kHz >= obsRxLaneRate_kHz) ? (rxLaneRate_kHz) : (obsRxLaneRate_kHz); - } - - /* performing integer multiple check on HS clock and lane rate clock */ - if (fasterLaneRate_kHz == 0) - { - /* All serializer lanes are disabled */ - txser_div = 1; - txser_div_reg = 0; - serializerHalfRateReg = 0; - } - else - { - if ((fasterLaneRate_kHz > hsclkRate_kHz) || - (fasterLaneRate_kHz > MAX_SERIALIZER_RATE_KHZ)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_LANERATE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_LANERATE_PARM)); - return MYKONOS_ERR_SER_INV_LANERATE_PARM; - } - - modHsLaneRate = (uint8_t)(hsclkRate_kHz % fasterLaneRate_kHz); - if (modHsLaneRate != 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT, - getMykonosErrorMessage(MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT)); - return MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT; - } - - txser_div = (uint8_t)(hsclkRate_kHz / fasterLaneRate_kHz); /* Total serializer Divider (1,2,4,8) */ - switch (txser_div) - { - case 1: - txser_div_reg = 0; /* Divide hsclk by 1 */ - serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ - break; - case 2: - txser_div_reg = 1; /* Divide hsclk by 2 */ - serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ - break; - case 4: - txser_div_reg = 2; /* Divide hsclk by 4 */ - serializerHalfRateReg = 0; /* 0 = divide serializer clock by 1 */ - break; - case 8: - txser_div_reg = 2; /* Divide hsclk by 4 */ - serializerHalfRateReg = 1; /* 1 = divide serializer clock by 2 */ - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SER_INV_TXSER_DIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_SER_INV_TXSER_DIV_PARM)); - return MYKONOS_ERR_SER_INV_TXSER_DIV_PARM; - } - } - - if (device->profilesValid & RX_PROFILE_VALID) - { - amplitudeEmphasis = ((device->rx->framer->serializerAmplitude & 0x1f) << 3) | (device->rx->framer->preEmphasis & 0x07); - } - else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) - { - amplitudeEmphasis = ((device->obsRx->framer->serializerAmplitude & 0x1f) << 3) | (device->obsRx->framer->preEmphasis & 0x07); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITSER_INV_PROFILE, getMykonosErrorMessage(MYKONOS_ERR_INITSER_INV_PROFILE)); - return MYKONOS_ERR_INITSER_INV_PROFILE; - } - - if (device->profilesValid & RX_PROFILE_VALID) - { - rxSyncbSelect = (device->rx->framer->obsRxSyncbSelect > 0) ? 1 : 0; - rxLanePn = (uint8_t)(rxSyncbSelect << 7) | (device->rx->framer->invertLanePolarity & 0xF); - } - - if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) - { - obsRxSyncbSelect = (device->obsRx->framer->obsRxSyncbSelect > 0) ? 1 : 0; - obsRxLanePn = (uint8_t)(obsRxSyncbSelect << 7) | (device->obsRx->framer->invertLanePolarity & 0xF); - } - - /* Serializer lane clock frequency */ - /* serLaneClock_kHz = fasterLaneRate_kHz / txser_div / 20; */ - if (device->profilesValid & RX_PROFILE_VALID) - { - /* calculate manual PCLK frequency for Rx framer = Rx IQrate * F, where F = (2*M/L) or PCLK = lanerate /10 */ - if (device->rx->framer->overSample) - { - rxFramerPclk_kHz = fasterLaneRate_kHz / 10; - } - else - { - rxFramerPclk_kHz = rxLaneRate_kHz / 10; - } - - hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->rx->rxProfile->rxDec5Decimation; - - /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */ - if (hsDigClkdiv4_5_kHz == rxFramerPclk_kHz) - { - rxPclkDiv = 2; - } - else if (hsDigClkdiv4_5_kHz > rxFramerPclk_kHz) - { - if (rxFramerPclk_kHz == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; - } - - tempPclkDiv = hsDigClkdiv4_5_kHz / rxFramerPclk_kHz; - switch (tempPclkDiv) - { - case 2: - rxPclkDiv = 3; - break; - case 4: - rxPclkDiv = 4; - break; - case 8: - rxPclkDiv = 5; - break; - case 16: - rxPclkDiv = 6; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; - } - } - } - else if (hsDigClkdiv4_5_kHz < rxFramerPclk_kHz) - { - tempPclkDiv = rxFramerPclk_kHz / hsDigClkdiv4_5_kHz; - switch (tempPclkDiv) - { - case 2: - rxPclkDiv = 1; - break; - case 4: - rxPclkDiv = 0; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM; - } - } - } - } - - if (obsRxL == 0) - { - /* Make sure PCLK is set as low as possible because it interacts with Rx Framer logic, */ - /* even though ObsRx Framer disabled */ - obsRxPclkDiv = 6; - } - else if (device->profilesValid & (ORX_PROFILE_VALID | SNIFF_PROFILE_VALID)) - { - /* calculate manual PCLK frequency for obsRx framer = obsRx IQrate * F, where F = (2*M/L) */ - if (device->profilesValid & ORX_PROFILE_VALID) - { - if (device->obsRx->framer->overSample) - { - obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10; - } - else - { - obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10; - } - - hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->orxProfile->rxDec5Decimation; - } - else if (device->profilesValid & SNIFF_PROFILE_VALID) - { - if (device->obsRx->framer->overSample) - { - obsRxFramerPclk_kHz = fasterLaneRate_kHz / 10; - } - else - { - obsRxFramerPclk_kHz = obsRxLaneRate_kHz / 10; - } - - hsDigClkdiv4_5_kHz = hsclkRate_kHz / device->clocks->clkPllHsDiv / device->obsRx->snifferProfile->rxDec5Decimation; - } - - /* PCLKDiv: 0=4x, 1=2x, 2=1x, 3=/2, 4=/4, 5=/8, 6=/16 */ - if (hsDigClkdiv4_5_kHz == obsRxFramerPclk_kHz) - { - obsRxPclkDiv = 2; - } - else if ((hsDigClkdiv4_5_kHz > obsRxFramerPclk_kHz) && (obsRxFramerPclk_kHz != 0)) - { - tempPclkDiv = hsDigClkdiv4_5_kHz / obsRxFramerPclk_kHz; - switch (tempPclkDiv) - { - case 2: - obsRxPclkDiv = 3; - break; - case 4: - obsRxPclkDiv = 4; - break; - case 8: - obsRxPclkDiv = 5; - break; - case 16: - obsRxPclkDiv = 6; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; - } - } - } - else if (hsDigClkdiv4_5_kHz < obsRxFramerPclk_kHz) - { - if (hsDigClkdiv4_5_kHz == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; - } - - tempPclkDiv = obsRxFramerPclk_kHz / hsDigClkdiv4_5_kHz; - switch (tempPclkDiv) - { - case 2: - obsRxPclkDiv = 1; - break; - case 4: - obsRxPclkDiv = 0; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM)); - return MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM; - } - } - } - } - - /* set lane rate divide setting */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, txser_div_reg, 0x03, 0); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_2, amplitudeEmphasis); - - /* Serializer: Release Reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_SPECIAL, 0x03); - - /* Serializer: txser clk enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_HS_DIV_TXSER_CLK_EN, 0x01); - - /* Serializer: Enable 2 to 1 serializer */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_3, 0x20 | serializerHalfRateReg); - - /* power up desired serializer lanes */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, lanePowerDown); - - /* apply desired lane PN inversions to the TX and OBSRX framers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_DATA_CTL, rxLanePn); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_DATA_CTL, obsRxLanePn); - - /* set Rx framer manual PCLK frequency based on lane rate of the serializers */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, (uint8_t)rxPclkDiv, 0x70, 4); - - /* enable bit repeat mode in Rx framer - since manual PCLK, oversample will still work */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x80, 7); - - /* enable manual PCLK mode in Rx framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 1, 0x04, 2); - - /* set obsRx framer manual PCLK frequency based on lane rate of the serializers */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, (uint8_t)obsRxPclkDiv, 0x70, 4); - - /* enable bit repeat mode in ObsRx framer - since manual PCLK, oversample will still work */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x80, 7); - - /* enable manual PCLK mode in ObsRx framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 1, 0x04, 2); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the JESD204B Deserializers - * - * This function enables the necessary deserializer lanes, sets the deserializer clocks - * PN inversion settings, and EQ settings based on the info found in the device data structure. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->tx->txProfile->clkPllVcoDiv - * - device->tx->txProfile->vcoFreq_kHz - * - device->tx->txProfile->txIqRate_kHz - * - device->tx->deframer->M - * - device->tx->deframer->deserializerLanesEnabled - * - device->tx->deframer->invertLanePolarity - * - device->tx->deframer->EQSetting - * - * \param device Pointer to the device settings structure - - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_INITDES_INV_TXPROFILE Tx Profile is not valid in data structure - can not setup deserializer - * \retval MYKONOS_ERR_INITDES_INV_VCODIV_PARM Mykonos CLKPLL VCO divider is invalid - * \retval MYKONOS_ERR_DESER_INV_M_PARM Invalid M (valid 2 or 4) - * \retval MYKONOS_ERR_DESER_INV_L_PARM Invalid L (valid 1,2,4) - * \retval MYKONOS_ERR_DESER_INV_HSCLK_PARM Invalid HSCLK, must be 6.144G or less after CLKPLL VCO divider - verify CLKPLL config - * \retval MYKONOS_ERR_DESER_INV_LANERATE_PARM Invalid lanerate, must be between 614.4 Mbps to 6144 Mbps - * \retval MYKONOS_ERR_DESER_INV_LANEEN_PARM Invalid deserializerLanesEnabled (valid 0-15 in 1,2,4 lane combinations) - * \retval MYKONOS_ERR_DESER_INV_EQ_PARM Invalid EQ parameter (valid 0-4) - * \retval MYKONOS_ERR_DESER_INV_LANEPN_PARM Invalid PN invert setting, (valid 0-15, invert bit per lane) - * \retval MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT Invalid clock settings, HSCLK is not an integer multiple of lane rate - * - */ -mykonosErr_t MYKONOS_setupDeserializers(mykonosDevice_t *device) -{ - uint8_t lanePowerDown = 0xF; - uint8_t des_div = 0; - uint8_t des_div_bitfield = 0; - uint8_t rxcdr_div = 0; - uint8_t rxcdr_div_bitfield = 0; - uint32_t hsclkRate_kHz = 0; - uint8_t i = 0; - uint8_t L = 0; - uint32_t laneRate_kHz = 0; - uint8_t invertLanePolarity = 0; - uint8_t modHsLaneRate = 0; - - const uint32_t MAX_HSCLKRATE_KHZ = 12288000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupDeserializers()\n"); -#endif - - if ((device->profilesValid & TX_PROFILE_VALID) == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_TXPROFILE, - getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_TXPROFILE)); - return MYKONOS_ERR_INITDES_INV_TXPROFILE; - } - - if (device->tx->deframer->M != 2 && device->tx->deframer->M != 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_M_PARM)); - return MYKONOS_ERR_DESER_INV_M_PARM; - } - - for (i = 0; i < 4; i++) - { - L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01); - } - - if ((L == 0) || (L == 3) || (L > 4)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_L_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_L_PARM)); - return MYKONOS_ERR_DESER_INV_L_PARM; - } - - //laneRate_kHz calculation and checks - laneRate_kHz = device->tx->txProfile->iqRate_kHz * 20 * device->tx->deframer->M / L; - - if ((laneRate_kHz < 614400) || (laneRate_kHz > 6144000)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANERATE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANERATE_PARM)); - return MYKONOS_ERR_DESER_INV_LANERATE_PARM; - } - - if (device->tx->deframer->deserializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM)); - return MYKONOS_ERR_DESER_INV_LANEEN_PARM; - } - - if ((device->tx->deframer->deserializerLanesEnabled == 0x7) || (device->tx->deframer->deserializerLanesEnabled == 0xB) - || (device->tx->deframer->deserializerLanesEnabled == 0xD) || (device->tx->deframer->deserializerLanesEnabled == 0xE)) - { - /* 3 lanes not valid, only 1,2, or 4 lanes */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEEN_PARM)); - return MYKONOS_ERR_DESER_INV_LANEEN_PARM; - } - - if (device->tx->deframer->EQSetting > 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_EQ_PARM, getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_EQ_PARM)); - return MYKONOS_ERR_DESER_INV_EQ_PARM; - } - - if (device->tx->deframer->invertLanePolarity > 15) - { - /* only lower 4 bits of parameter are valid */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_LANEPN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_LANEPN_PARM)); - return MYKONOS_ERR_DESER_INV_LANEPN_PARM; - } - - //hsclkRate_kHz calculations - switch (device->clocks->clkPllVcoDiv) - { - case VCODIV_1: - hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz; - break; - case VCODIV_1p5: - hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 15) * 10; - break; - case VCODIV_2: - hsclkRate_kHz = device->clocks->clkPllVcoFreq_kHz >> 1; - break; - case VCODIV_3: - hsclkRate_kHz = (device->clocks->clkPllVcoFreq_kHz / 30) * 10; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITDES_INV_VCODIV_PARM, - getMykonosErrorMessage(MYKONOS_ERR_INITDES_INV_VCODIV_PARM)); - return MYKONOS_ERR_INITDES_INV_VCODIV_PARM; - } - - /* The deserializer clock needs to be in the range 3.8GHz to 6.144 GHz in reg x107. The rest of the division is in xDD */ - if (hsclkRate_kHz <= 6144000) - { - rxcdr_div = 1; - } - else if ((hsclkRate_kHz > 6144000) && (hsclkRate_kHz <= MAX_HSCLKRATE_KHZ)) - { - rxcdr_div = 2; - } - else if ((hsclkRate_kHz > MAX_HSCLKRATE_KHZ) && (hsclkRate_kHz < 24576000)) - { - rxcdr_div = 4; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DESER_INV_HSCLK_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DESER_INV_HSCLK_PARM)); - return MYKONOS_ERR_DESER_INV_HSCLK_PARM; - } - - switch (rxcdr_div) - { - case 1: - rxcdr_div_bitfield = 0; - break; - case 2: - rxcdr_div_bitfield = 1; - break; - - default: - /* Default case is when rxcdr_div == 4 */ - rxcdr_div_bitfield = 2; - break; - } - - /* performing integer multiple check on HS clock and lane rate clock */ - modHsLaneRate = (uint8_t)(hsclkRate_kHz % laneRate_kHz); - if (modHsLaneRate) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT, - getMykonosErrorMessage(MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT)); - return MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT; - } - - des_div = (uint8_t)(hsclkRate_kHz / laneRate_kHz / rxcdr_div); - - switch (des_div) - { - case 1: - des_div_bitfield = 0; - break; - case 2: - des_div_bitfield = 1; - break; - case 4: - des_div_bitfield = 2; - break; - case 8: - des_div_bitfield = 3; - break; - default: - des_div_bitfield = 0; - break; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_3, rxcdr_div_bitfield, 0x0C, 0x02); - - invertLanePolarity = (device->tx->deframer->invertLanePolarity & 0xF); - - lanePowerDown = (~(device->tx->deframer->deserializerLanesEnabled)) & 0xF; - - /* Deserializer: PLL clock enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_HS_DIV_RXCDR_CLK_EN, 0x01); - - /* Deserializer: Set Pdet control */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_PDET_CTL, 0x09); - - /* Deserializer: Set Power down control */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CTL_0, (0x80U | lanePowerDown | (uint8_t)(des_div_bitfield << 4))); - - /* Deserializer: Set Sine Shape */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_0, 0x00); - - /* Deserializer: Set ss gain and vga */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_1, 0x00); - - /* Deserializer: Enable EQ, AC coupled JESD204B lanes */ - /* TODO: add ability to set this for AC coupling or DC coupling */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1, 0x07); - - /* Deserializer: Clear Data present at negedge, disable peak adjust */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_MISC_CTL, 0x04); - - /* Deserializer: Set Equalizer for lanes 1 and 0 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1_TO_0, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting)); - - /* Deserializer: Set Equalizer for lanes 2 and 3 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_EQ_CTL_3_TO_2, ((uint8_t)(device->tx->deframer->EQSetting << 3) | device->tx->deframer->EQSetting)); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_DATA_CTL, invertLanePolarity); - - /* Reset Deserializers - toggle resetb bit in [0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x00); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_SPECIAL, 0x01); - - /* Start ALC cal */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DESERIALIZER_CDR_CAL_CTL, 0x02); - - /* Deframer: Enable clocks and lane clocks */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the JESD204B Framer - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->rx->framer->M - * - device->rx->realIfData - * - device->rx->framer->bankId - * - device->rx->framer->lane0Id - * - device->rx->framer->serializerLanesEnabled - * - device->rx->framer->obsRxSyncbSelect - * - device->rx->framer->K - * - device->rx->framer->externalSysref - * - device->rx->rxChannels - * - device->rx->framer->newSysrefOnRelink - * - device->rx->framer->enableAutoChanXbar - * - device->rx->framer->lmfcOffset - * - device->rx->framer->scramble - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM Invalid framer M, M can only = 1 in real IF mode - * \retval MYKONOS_ERR_FRAMER_INV_M_PARM Invalid framer M (valid 1,2,4) - * \retval MYKONOS_ERR_FRAMER_INV_BANKID_PARM Invalid BankId (valid 0-15) - * \retval MYKONOS_ERR_FRAMER_INV_LANEID_PARM Invalid Lane0Id (valid 0-31) - * \retval MYKONOS_ERR_RXFRAMER_INV_FK_PARAM - * \retval MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM - */ -mykonosErr_t MYKONOS_setupJesd204bFramer(mykonosDevice_t *device) -{ - uint8_t i = 0; - uint8_t fifoLaneEnable = 0; - uint8_t L = 0; - uint8_t ML = 0; - uint8_t framerConfigF = 0; - - uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */ - uint8_t subdata[29] = {0}; /* holds data for framer sub register map */ - - /* Setup submap registers */ - uint8_t SUBCLASSV = 1; /* JESD subclass 1 */ - uint8_t JESDV = 1; /* Version: JESD204B */ - uint8_t DID = 0; - uint8_t BID = 0; - uint8_t LID0 = 0; - uint8_t LID1 = 1; - uint8_t LID2 = 2; - uint8_t LID3 = 3; - uint8_t CS = 0; - uint8_t N = 0x0F; - uint8_t Np = 0x0F; - uint8_t S = 0; - uint8_t CF = 0; - uint8_t K = 31; - uint8_t HD = 0; - uint8_t FramerL = 1; - uint8_t FramerM = 2; - uint8_t FramerF = 1; - uint8_t framerADC_XBar = 0xE4; - uint16_t FK = 0; - - uint8_t regE0 = 0; - uint8_t regE2 = 0; - uint8_t framerLaneXbar = 0xE4; - uint16_t CheckSum = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bFramer()\n"); -#endif - - if (device->rx->framer->M == 1 && !(device->rx->realIfData)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM, - getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM)); - return MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM; - } - - if (device->rx->framer->M != 1 && device->rx->framer->M != 2 && device->rx->framer->M != 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM)); - return MYKONOS_ERR_FRAMER_INV_M_PARM; - } - - if (device->rx->framer->bankId > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_BANKID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_BANKID_PARM)); - return MYKONOS_ERR_FRAMER_INV_BANKID_PARM; - } - - /* no need to check deviceId, its range is full uint8_t range */ - if (device->rx->framer->lane0Id > 31) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_LANEID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_LANEID_PARM)); - return MYKONOS_ERR_FRAMER_INV_LANEID_PARM; - } - - //count number of lanes - L = 0; - ML = 0; - - for (i = 0; i < 4; i++) - { - L += ((device->rx->framer->serializerLanesEnabled >> i) & 0x01); - } - ML = (uint8_t)(device->rx->framer->M * 10) + L; - - FK = (uint16_t)(device->rx->framer->K * 2 * device->rx->framer->M / L); - - if (FK < 20 || FK > 256 || FK % 4 != 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RXFRAMER_INV_FK_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_RXFRAMER_INV_FK_PARAM)); - return MYKONOS_ERR_RXFRAMER_INV_FK_PARAM; - } - - if (device->rx->framer->externalSysref == 0) - { - /* Framer: Generate SYSREF internally */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_TEST_CNTR_CTL, 0x20); - } - - framerADC_XBar = 0xB1; - if (ML == 24) - { - if (device->rx->rxChannels == RX1) - { - /* adc 0 and 2 used */ - framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03); - } - else if (device->rx->rxChannels == RX2) - { - /* swap ADC xbar for Rx1 and Rx2 */ - framerADC_XBar = ((framerADC_XBar & 0xF) << 4) | ((framerADC_XBar & 0xF0) >> 4); - /* adc 0 and 2 used */ - framerADC_XBar = ((framerADC_XBar & 0x0C) << 2) | (framerADC_XBar & 0x03); - } - - /* Framer: Set ADC Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar); - } - else - { - /* Framer: Set ADC Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL, framerADC_XBar); - } - - if (device->rx->framer->enableManualLaneXbar == 1) - { - framerLaneXbar = device->rx->framer->serializerLaneCrossbar; - } - else - { - if (ML == 42) - { - /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */ - /* only 2 lane cases here */ - switch ((device->rx->framer->serializerLanesEnabled & 0x0F)) - { - case 3: - framerLaneXbar = 0x08; - break; - case 5: - framerLaneXbar = 0x20; - break; - case 6: - framerLaneXbar = 0x20; - break; - case 9: - framerLaneXbar = 0x80; - break; - case 10: - framerLaneXbar = 0x80; - break; - case 12: - framerLaneXbar = 0x80; - break; - default: - /* default to valid setting for Lane 0 */ - framerLaneXbar = 0x08; - break; - } - } - else - { - switch ((device->rx->framer->serializerLanesEnabled & 0x0F)) - { - /* all 4 lanes get framer 0 output */ - case 1: - framerLaneXbar = 0x00; - break; - case 2: - framerLaneXbar = 0x00; - break; - case 3: - framerLaneXbar = 0x04; - break; - case 4: - framerLaneXbar = 0x00; - break; - case 5: - framerLaneXbar = 0x10; - break; - case 6: - framerLaneXbar = 0x10; - break; - case 8: - framerLaneXbar = 0x00; - break; - case 9: - framerLaneXbar = 0x40; - break; - case 10: - framerLaneXbar = 0x40; - break; - case 12: - framerLaneXbar = 0x40; - break; - case 15: - framerLaneXbar = 0xE4; - break; - default: - /* default to valid setting for all Lanes */ - framerLaneXbar = 0xE4; - break; - } - } - } - - /* Framer: Set Lane Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_XBAR_SEL, framerLaneXbar); - - if (ML == 24) - { - /* Framer: Clear ADC Xbar channel auto switch */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x00); - } - else - { - /* Framer: Set ADC Xbar channel auto switch */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x04); - } - - /* enabling the SYSREF for relink if newSysrefOnRelink is set */ - if (device->rx->framer->newSysrefOnRelink) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); - } - - /* enabling auto channel if the enableAutoChanXbar structure member is set */ - if (device->rx->framer->enableAutoChanXbar) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2); - } - - /* determining F octets per frame based on 2*M/L */ - framerConfigF = (uint8_t)(2 * (device->rx->framer->M / L)); - - /* Framer: Soft Reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03); - - /* Framer: Clear Soft Reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00); - - /* Framer: Set F (Octets in Frame) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_F, framerConfigF); - - /* Framer: Enable framer clock and lane clocks */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0x03, 0x03, 0); - - /* Set Framer lane FIFO enable for each lane enabled */ - fifoLaneEnable = (((device->rx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01); - - /* Framer: Enable Lane FIFOs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LANE_CTL, fifoLaneEnable); - - /* Setup submap registers */ - SUBCLASSV = 1; /* JESD subclass 1 */ - JESDV = 1; /* Version: JESD204B */ - DID = device->rx->framer->deviceId; - BID = device->rx->framer->bankId; - LID0 = device->rx->framer->lane0Id; - LID1 = device->rx->framer->lane0Id + 1; - LID2 = device->rx->framer->lane0Id + 2; - LID3 = device->rx->framer->lane0Id + 3; - - CS = 0; - N = 0x0F; - Np = 0x0F; - S = 0; - CF = 0; - HD = 0; - K = device->rx->framer->K - 1; - FramerL = L - 1; - FramerM = device->rx->framer->M - 1; - FramerF = (uint8_t)(2 * device->rx->framer->M / L) - 1; - - if (ML == 11) - { - regE0 = 0x01; - regE2 = 0x01; - } - else if (ML == 12) - { - regE0 = 0x01; - regE2 = 0x03; - HD = 0x01; - } - else if (ML == 21) - { - regE0 = 0x03; - regE2 = 0x01; - } - else if (ML == 22) - { - regE0 = 0x03; - regE2 = 0x03; - } - else if (ML == 24) - { - regE0 = 0x05; - regE2 = 0x0F; - HD = 0x01; - } - else if (ML == 41) - { - regE0 = 0x0F; - regE2 = 0x01; - } - else if (ML == 42) - { - regE0 = 0x0F; - regE2 = 0x05; - } - else if (ML == 44) - { - regE0 = 0x0F; - regE2 = 0x0F; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_M_PARM)); - return MYKONOS_ERR_FRAMER_INV_M_PARM; - } - - /* setting K offset for framer */ - if (device->rx->framer->lmfcOffset < device->rx->framer->K) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_LMFC_K_OFFSET, device->rx->framer->lmfcOffset); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM)); - return MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM; - } - - subaddr[0] = 0x00; - subdata[0] = (DID & 0xFF); /* Device ID */ - subaddr[1] = 0x01; - subdata[1] = (BID & 0x0F); /* Bank ID */ - subaddr[2] = 0x02; - subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */ - subaddr[3] = 0x03; - subdata[3] = (uint8_t)(device->rx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */ - subaddr[4] = 0x04; - subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */ - subaddr[5] = 0x05; - subdata[5] = (K & 0x1F); /* K[4:0]-1 */ - subaddr[6] = 0x06; - subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */ - subaddr[7] = 0x07; - subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */ - subaddr[8] = 0x08; - subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */ - subaddr[9] = 0x09; - subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */ - subaddr[10] = 0x0A; - subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */ - subaddr[11] = 0x0B; - subdata[11] = 0x00; /* reserved */ - subaddr[12] = 0x0C; - subdata[12] = 0x00; /* reserved */ - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 0 */ - subaddr[13] = 0x0D; - subdata[13] = CheckSum & 0xFF; - - /* in JESD204B ML=42 case, framer ip lanes 0 and 2 are used, write lane 1 id and checksum to ip lane 2 regs */ - if (ML == 42) - { - /* Lane 1 ID */ - subaddr[14] = 0x1A; - subdata[14] = LID1; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 1 */ - subaddr[15] = 0x1D; - subdata[15] = CheckSum & 0xFF; - } - else - { - /* Lane 1 ID */ - subaddr[14] = 0x12; - subdata[14] = LID1; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 1 */ - subaddr[15] = 0x15; - subdata[15] = CheckSum & 0xFF; - - /* Lane 2 ID */ - subaddr[16] = 0x1A; - subdata[16] = LID2; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 2 */ - subaddr[17] = 0x1D; - subdata[17] = CheckSum & 0xFF; - - /* Lane 3 ID */ - subaddr[18] = 0x22; - subdata[18] = LID3; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->rx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - subaddr[19] = 0x25; - subdata[19] = CheckSum & 0xFF; - } - - subaddr[20] = 0xE0; - subdata[20] = regE0; /* Enable converter n logic */ - subaddr[21] = 0xE2; - subdata[21] = regE2; /* Enable Lane n logic */ - subaddr[22] = 0xE4; - subdata[22] = 0x00; - subaddr[23] = 0xE6; - subdata[23] = 0x00; - subaddr[24] = 0xF0; - subdata[24] = 0x00; /* #multiframes in ILAS */ - subaddr[25] = 0xF2; - subdata[25] = 0x00; - subaddr[26] = 0xF3; - subdata[26] = 0x00; - subaddr[27] = 0xF4; - subdata[27] = 0x00; - subaddr[28] = 0xC0; - subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */ - - for (i = 0; i <= 28; i++) - { - /* Set framer sub register map address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_ADDR, subaddr[i]); - - /* Set framer sub register map data word */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_DATA, subdata[i]); - - /* Write enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_WRITE_EN, 0x01); - } - - if (device->rx->framer->externalSysref > 0) - { - /* Framer: Enable lane FIFO sync (Enable CGS) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x30); - } - else - { - /* Framer: Enable lane FIFO sync (Enable CGS) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x10); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the JESD204B OBSRX Framer - * - * Dependencies - * - device->rxChannels - * - device->spiSettings->chipSelectIndex - * - device->obsRx->framer->bankId - * - device->obsRx->framer->M - * - device->obsRx->framer->serializerLanesEnabled - * - device->obsRx->framer->externalSysref - * - device->spiSettings - * - device->obsRx->framer->deviceId - * - device->obsRx->framer->lane0Id - * - device->obsRx->framer->K - * - device->obsRx->framer->lmfcOffset - * - device->obsRx->framer->scramble - * - device->obsRx->framer->obsRxSyncbSelect - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM M parameter can only be 1 when real IF data mode is enabled - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM ObsRx Framer M parameter can only be 1 or 2 - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM Invalid BankId (0-15) - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM Invalid lane0Id (0-31) - * \retval MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM Invalid F*K value (F * K must be > 20 and divisible by 4) - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM Invalid K offset, must be less than K - */ -mykonosErr_t MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t *device) -{ - uint8_t i = 0; - uint8_t laneFifoEnable = 0; - uint8_t L = 1; - uint8_t ML = 2; - uint8_t framerConfigF = 0; - - uint8_t subaddr[29] = {0}; /* holds address to framer sub register map */ - uint8_t subdata[29] = {0}; /* holds data for framer sub register map */ - - /* Setup submap registers */ - uint8_t SUBCLASSV = 1; /* JESD subclass 1 */ - uint8_t JESDV = 1; /* Version: JESD204B */ - uint8_t DID = 0; - uint8_t BID = 0; - uint8_t LID0 = 0; - uint8_t LID1 = 1; - uint8_t LID2 = 2; - uint8_t LID3 = 3; - uint8_t CS = 0; - uint8_t N = 0x0F; - uint8_t Np = 0x0F; - uint8_t S = 0; - uint8_t CF = 0; - uint8_t K = 31; - uint8_t HD = 0; - uint8_t FramerL = 1; - uint8_t FramerM = 2; - uint8_t FramerF = 1; - uint8_t framerADC_XBar = 0xE4; - uint8_t regE0 = 0; - uint8_t regE2 = 0; - uint8_t framerLaneXbar = 0xE4; - uint16_t CheckSum = 0; - uint16_t FK = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bObsRxFramer()\n"); -#endif - - if (device->obsRx->framer->M == 1 && !(device->obsRx->realIfData)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM; - } - - if (device->obsRx->framer->M != 1 && device->obsRx->framer->M != 2) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM; - } - - if (device->obsRx->framer->bankId > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM; - } - - /* no need to check deviceId, its range is full uint8_t range */ - if (device->obsRx->framer->lane0Id > 31) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM; - } - - //count number of lanes - L = 0; - ML = 0; - - for (i = 0; i < 4; i++) - { - L += ((device->obsRx->framer->serializerLanesEnabled >> i) & 0x01); - } - - ML = (uint8_t)(device->obsRx->framer->M * 10 + L); - - if (L == 0) - { - /* Disable framer and return successfully */ - /* Disable framer clock and lane clocks */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0); - - /* Disable lane FIFO enables */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, 0, 0xF0, 4); - return MYKONOS_ERR_OK; - } - - FK = (uint16_t)(device->obsRx->framer->K * 2 * device->obsRx->framer->M / L); - if (FK < 20 || FK > 256 || FK % 4 != 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM)); - return MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM; - } - - if (device->obsRx->framer->externalSysref == 0) - { - /* Framer: Generate SYSREF internally */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_TEST_CNTR_CTL, 0x20); - } - - /* Framer: Set ADC Crossbar */ - framerADC_XBar = 0xB1; - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADC_XBAR_SEL, framerADC_XBar); - - if (device->obsRx->framer->enableManualLaneXbar == 1) - { - framerLaneXbar = device->obsRx->framer->serializerLaneCrossbar; - } - else - { - if (ML == 42) - { - /* uses framer outputs 0 and 2 instead of 0 and 1...fix framer lane XBar */ - /* only 2 lane cases here */ - switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F)) - { - case 3: - framerLaneXbar = 0x08; - break; - case 5: - framerLaneXbar = 0x20; - break; - case 6: - framerLaneXbar = 0x20; - break; - case 9: - framerLaneXbar = 0x80; - break; - case 10: - framerLaneXbar = 0x80; - break; - case 12: - framerLaneXbar = 0x80; - break; - default: - /* default to valid setting for Lane 0 */ - framerLaneXbar = 0x08; - break; - } - } - else - { - switch ((device->obsRx->framer->serializerLanesEnabled & 0x0F)) - { - /* all 4 lanes get framer 0 output */ - case 1: - framerLaneXbar = 0x00; - break; - case 2: - framerLaneXbar = 0x00; - break; - case 3: - framerLaneXbar = 0x04; - break; - case 4: - framerLaneXbar = 0x00; - break; - case 5: - framerLaneXbar = 0x10; - break; - case 6: - framerLaneXbar = 0x10; - break; - case 8: - framerLaneXbar = 0x00; - break; - case 9: - framerLaneXbar = 0x40; - break; - case 10: - framerLaneXbar = 0x40; - break; - case 12: - framerLaneXbar = 0x40; - break; - case 15: - framerLaneXbar = 0xE4; - break; - default: - /* default to valid setting for all Lanes */ - framerLaneXbar = 0xE4; - break; - } - } - } - - /* Framer: set Lane Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_XBAR_SEL, framerLaneXbar); - - /* Framer: determine the framerConfigF value (2*M/L) */ - framerConfigF = (uint8_t)(2 * (device->obsRx->framer->M/L)); - - /* Framer: Soft Reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03); - - /* Framer: Clear Soft Reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00); - - /* Framer: Set F (Octets in Frame) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_F, framerConfigF); - - /* Framer: Enable framer clock and lane clocks */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0x03, 0x03, 0); - - /* Set Framer lane FIFO enable for each lane enabled */ - laneFifoEnable = (uint8_t)(((device->obsRx->framer->serializerLanesEnabled & 0x0F) << 4) | 0x01); - - /* Framer: Enable Lane FIFOs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LANE_CTL, laneFifoEnable); - - /* enabling the SYSREF for relink if newSysrefOnRelink is set */ - if (device->obsRx->framer->newSysrefOnRelink) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); - } - - /* enabling auto channel if the enableAutoChanXbar structure member is set */ - if (device->obsRx->framer->enableAutoChanXbar) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, 0x01, 0x04, 2); - } - - /* Setup submap registers */ - SUBCLASSV = 1; /* JESD subclass 1 */ - JESDV = 1; /* Version: JESD204B */ - DID = device->obsRx->framer->deviceId; - BID = device->obsRx->framer->bankId; - LID0 = device->obsRx->framer->lane0Id; - LID1 = device->obsRx->framer->lane0Id + 1; - LID2 = device->obsRx->framer->lane0Id + 2; - LID3 = device->obsRx->framer->lane0Id + 3; - - CS = 0; - N = 0x0F; - Np = 0x0F; - S = 0; - CF = 0; - K = device->obsRx->framer->K - 1; - HD = 0; - FramerL = L - 1; - FramerM = device->obsRx->framer->M - 1; - FramerF = (uint8_t)((2*device->obsRx->framer->M/L) - 1); - - if (ML == 11) - { - regE0 = 0x1; - regE2 = 0x1; - } - else if (ML == 12) - { - regE0 = 0x1; - regE2 = 0x3; - HD = 1; - } - else if (ML == 21) - { - regE0 = 0x3; - regE2 = 0x1; - } - else if (ML == 22) - { - regE0 = 0x3; - regE2 = 0x3; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM; - } - - /* setting K offset for framer */ - if (device->obsRx->framer->lmfcOffset < device->rx->framer->K) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_LMFC_K_OFFSET, device->obsRx->framer->lmfcOffset); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM; - } - - subaddr[0] = 0x00; - subdata[0] = (DID & 0xFF); /* Device ID */ - subaddr[1] = 0x01; - subdata[1] = (BID & 0x0F); /* Bank ID */ - subaddr[2] = 0x02; - subdata[2] = (LID0 & 0x1F); /* Lane 0 ID */ - subaddr[3] = 0x03; - subdata[3] = (uint8_t)(device->obsRx->framer->scramble << 7) | (FramerL & 0x1F); /* [7] Scramble, #Lanes[4:0]-1 */ - subaddr[4] = 0x04; - subdata[4] = (FramerF & 0xFF); /* F[7:0]-1 */ - subaddr[5] = 0x05; - subdata[5] = (K & 0x1F); /* K[4:0]-1 */ - subaddr[6] = 0x06; - subdata[6] = (FramerM & 0xFF); /* M[7:0]-1 */ - subaddr[7] = 0x07; - subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0]-1 */ - subaddr[8] = 0x08; - subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* NP[4:0] -1 */ - subaddr[9] = 0x09; - subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0]-1 */ - subaddr[10] = 0x0a; - subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7] = HD, CF[4:0] */ - subaddr[11] = 0x0b; - subdata[11] = 0x00; /* reserved */ - subaddr[12] = 0x0c; - subdata[12] = 0x00; /* reserved */ - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 0 */ - subaddr[13] = 0x0d; - subdata[13] = CheckSum & 0xFF; - - /* Lane 1 ID */ - subaddr[14] = 0x12; - subdata[14] = LID1; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID1 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 1 */ - subaddr[15] = 0x15; - subdata[15] = CheckSum & 0xFF; - - /* Lane 2 ID */ - subaddr[16] = 0x1a; - subdata[16] = LID2; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID2 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - /* Checksum Lane 2 */ - subaddr[17] = 0x1d; - subdata[17] = CheckSum & 0xFF; - - /* Lane 3 ID */ - subaddr[18] = 0x22; - subdata[18] = LID3; - - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID3 & 0x1F) + (device->obsRx->framer->scramble) + (FramerL & 0x1F) + (FramerF & 0xFF) + (K & 0x1F) + (FramerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - - subaddr[19] = 0x25; - subdata[19] = CheckSum & 0xFF; - - subaddr[20] = 0xe0; - subdata[20] = regE0; /* Enable converter n logic */ - subaddr[21] = 0xe2; - subdata[21] = regE2; /* Enable Lane n logic */ - subaddr[22] = 0xe4; - subdata[22] = 0x00; - subaddr[23] = 0xe6; - subdata[23] = 0x00; - subaddr[24] = 0xf0; - subdata[24] = 0x00; /* #multiframes in ILAS */ - subaddr[25] = 0xf2; - subdata[25] = 0x00; - subaddr[26] = 0xf3; - subdata[26] = 0x00; - subaddr[27] = 0xf4; - subdata[27] = 0x00; - subaddr[28] = 0xc0; - subdata[28] = 0x03; /* Framer enable, both sides perform lane sync */ - - for (i = 0; i <= 28; i++) - { - /* Set framer sub register map address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_ADDR, subaddr[i]); - - /* Set framer sub register map data word */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_DATA, subdata[i]); - - /* Write enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_WRITE_EN, 0x01); - } - - if (device->obsRx->framer->externalSysref > 0) - { - /* Framer: Enable lane FIFO sync (Enable CGS) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x30); - } - else - { - /* Framer: Enable lane FIFO sync (Enable CGS) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x10); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables/Disables the JESD204B Rx Framer - * - * This function is normally not necessary. In the event that the link needs to be reset, this - * function allows the Rx framer to be disabled and re-enabled. - * - * Dependencies - * - device->spiSettings - * - device->rx->framer->serializerLanesEnabled - * - * \param device is a pointer to the device settings structure - * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure - */ -mykonosErr_t MYKONOS_enableRxFramerLink(mykonosDevice_t *device, uint8_t enable) -{ - uint8_t enableLink = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableFramerLink()\n"); -#endif - - enableLink = (enable > 0) ? 1 : 0; - - if (enableLink) - { - /* Power Up serializer lanes */ - if (device->rx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM)); - return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->rx->framer->serializerLanesEnabled) & 0x0F), - device->rx->framer->serializerLanesEnabled, 0); - - /* Enable Clocks to Framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 3, 0x03, 0); - - /* Release reset to framer and lane FIFOs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x00); - } - else - { - /* Disable Link */ - /* Hold Rx framer in reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_RESET, 0x03); - - /* Disable Clocks to Framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CLK_EN, 0, 0x03, 0); - - /* Power down serializer lanes */ - if (device->rx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM)); - return MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->rx->framer->serializerLanesEnabled, device->rx->framer->serializerLanesEnabled, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables/Disables the JESD204B ObsRx Framer - * - * This function is normally not necessary. In the event that the link needs to be reset, this - * function allows the ObsRx framer to be disabled and re-enabled. - * - * Dependencies - * - device->spiSettings - * - device->obsRx->framer->serializerLanesEnabled - * - * \param device is a pointer to the device settings structure - * \param enable 0 = Disable the selected framer, 1 = enable the selected framer link - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM Invalid serializerLanesEnabled parameter in device data structure (Valid 0-15) - */ -mykonosErr_t MYKONOS_enableObsRxFramerLink(mykonosDevice_t *device, uint8_t enable) -{ - uint8_t enableLink = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerLink()\n"); -#endif - - enableLink = (enable > 0) ? 1 : 0; - - if (enableLink) - { - /* Power Up serializer lanes */ - if (device->rx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM)); - return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, ((~device->obsRx->framer->serializerLanesEnabled) & 0x0F), - device->obsRx->framer->serializerLanesEnabled, 0); - - /* Enable Clocks to Framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 3, 0x03, 0); - - /* Release reset to framer and lane FIFOs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x00); - } - else - { - /* Disable Link */ - /* Hold Rx framer in reset */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_RESET, 0x03); - - /* Disable Clocks to Framer */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CLK_EN, 0, 0x03, 0); - - /* Power down serializer lanes */ - if (device->obsRx->framer->serializerLanesEnabled > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM)); - return MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SERIALIZER_CTL_1, device->obsRx->framer->serializerLanesEnabled, - device->obsRx->framer->serializerLanesEnabled, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the JESD204B Deframer - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->tx->deframer->M - * - device->tx->deframer->bankId - * - device->tx->deframer->lane0Id - * - device->tx->deframer->K - * - device->tx->deframer->deserializerLanesEnabled - * - device->tx->deframer->externalSysref - * - device->tx->deframer->newSysrefOnRelink - * - device->tx->deframer->enableAutoChanXbar - * - device->tx->deframer->lmfcOffset - * - device->tx->deframer->scramble - * - * \param device Pointer to device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_DEFRAMER_INV_M_PARM Invalid M parameter in deframer structure - * \retval MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM Invalid BankId parameter in deframer structure (Valid 0-15) - * \retval MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM Invalid Lane0Id parameter in deframer structure (Valid 0-31) - * \retval MYKONOS_ERR_DEFRAMER_INV_K_PARAM Invalid K parameter in deframer structure (valid 1-32 with other constraints) - * \retval MYKONOS_ERR_DEFRAMER_INV_FK_PARAM Invalid F*K parameter (Valid F*K > 20, F*K must be divisible by 4), K must be <= 32 - * \retval MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM Invalid K offset parameter in deframer structure (must be less than K) - */ -mykonosErr_t MYKONOS_setupJesd204bDeframer(mykonosDevice_t *device) -{ - uint8_t i = 0; - uint8_t temp = 0; - uint8_t reg080 = 0; - uint8_t laneXbar = 0; - uint8_t L = 0; - uint8_t ML = 0; - - /* Setup submap registers */ - uint8_t SUBCLASSV = 1; - uint8_t JESDV = 1; - uint8_t DID = 0; - uint8_t BID = 0; - uint8_t LID0 = 0; - uint8_t CS = 2; /* 2 control bits */ - uint8_t N = 0x0D; /* 14 bits */ - uint8_t Np = 0x0F; /* 16 bits */ - uint8_t S = 0; - uint8_t CF = 0; - uint8_t K = 0x1F; - uint16_t FK = 0; - uint8_t HD = 0; /* only one case has HD == 1 */ - uint8_t CTRLREG0 = 0; - uint8_t DeframerL = 1; - uint8_t DeframerM = 2; - uint8_t DeframerF = 0; - uint8_t CTRLREG1 = 0; - uint8_t CTRLREG2 = 0; - uint8_t DeframerLaneEnable = 0x00; - uint16_t CheckSum = 0; - uint8_t subaddr[25] = {0}; - uint8_t subdata[25] = {0}; - - uint8_t deframerInput = 0; - uint8_t lane = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setupJesd204bDeframer()\n"); -#endif - - if (device->tx->deframer->M != 0 && device->tx->deframer->M != 2 && device->tx->deframer->M != 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM)); - return MYKONOS_ERR_DEFRAMER_INV_M_PARM; - } - - if (device->tx->deframer->bankId > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM)); - return MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM; - } - - if (device->tx->deframer->lane0Id > 31) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM)); - return MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM; - } - - //count number of lanes - L = 0; - ML = 0; - - for (i = 0; i < 4; i++) - { - L += ((device->tx->deframer->deserializerLanesEnabled >> i) & 0x01); - } - - ML = (uint8_t)(device->tx->deframer->M * 10 + L); - - if (device->tx->deframer->K > 32) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_K_PARAM; - } - - FK = (uint16_t)(device->tx->deframer->K * 2 * device->tx->deframer->M / L); - - if (FK < 20 || FK > 256 || FK % 4 != 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_FK_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_FK_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_FK_PARAM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYNC_REQ_RETIME, (device->tx->deframer->K - 1), 0x1F, 0x00); - - if (!device->tx->deframer->externalSysref) - { - /* Deframer: Generate SYSREF internally */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_TEST, 0x02); - } - - /* enabling the SYSREF for relink if newSysrefOnRelink is set */ - if (device->tx->deframer->newSysrefOnRelink) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x40, 6); - } - - /* enabling auto channel if the enableAutoChanXbar structure member is set */ - if (device->tx->deframer->enableAutoChanXbar) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x01, 0x04, 2); - } - - /* Fix bad default bit to allow deterministic latency on deframer (Clear bit 4)*/ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV, 0x00, 0x10, 4); - - /* Deframer: Set DAC Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DAC_XBAR_SEL, 0xB1); - - if (device->tx->deframer->enableManualLaneXbar == 1) - { - laneXbar = device->tx->deframer->deserializerLaneCrossbar; - } - else - { - /* Lane crossbar - Allow user to reorder lanes in deframer->deserializerLaneCrossbar, but this code still */ - /* maps used lanes to deframer inputs */ - deframerInput = 0; - for (lane = 0; lane < 4; lane++) - { - if ((device->tx->deframer->deserializerLanesEnabled >> lane) & 1) - { - laneXbar |= (uint8_t)(((device->tx->deframer->deserializerLaneCrossbar >> (lane << 1)) & 3) << (deframerInput << 1)); - deframerInput += 1; - } - } - - if (ML == 42) - { - /* M4L2 uses internal deframer ports 0 and 2 */ - /* swap bits 3:2 and 5:4, keep 1:0 and 7:6 in place */ - laneXbar = (laneXbar & 0xC3U) | ((laneXbar & 0x30) >> 2) | ((laneXbar & 0x0C) << 2); - } - } - - /* Deframer: Set Lane Crossbar */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_XBAR_SEL, laneXbar); - - //Find value for Framer F depending on M and L - switch (ML) - { - case 21: - reg080 = 0x04; - break; - case 22: - reg080 = 0x22; - break; - case 24: - reg080 = 0x41; - break; - case 41: - reg080 = 0x18; - break; - case 42: - reg080 = 0x34; - break; - case 44: - reg080 = 0x52; - break; - default: - reg080 = 0x04; - break; - } - - /* Deframer: Set F (Octets in Frame) */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CONFIG_F, reg080); - - /* Deframer: Enable clocks and lane clocks */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_CLK_EN, 0x03); - - /* Set deframer lane FIFO enable for each lane enabled */ - temp = (device->tx->deframer->deserializerLanesEnabled & 0x0F); - - /* Deframer: Enable Lane FIFOs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LANE_FIFO_CTL, temp); - - /* Setup submap registers */ - SUBCLASSV = 1; /* JESD subclass 1 */ - JESDV = 1; /* Version: JESD204B */ - DID = device->tx->deframer->deviceId; - BID = device->tx->deframer->bankId; - LID0 = device->tx->deframer->lane0Id; - CS = 2; /* 2 control bits */ - N = 0x0D; /* 14 bits */ - Np = 0x0F; - S = 0; - CF = 0; - K = device->tx->deframer->K - 1; - HD = 0; /* only one case has HD = 1 */ - CTRLREG0 = 1; - DeframerL = L - 1; - DeframerM = device->tx->deframer->M - 1; - DeframerF = (uint8_t)((2*device->tx->deframer->M/L) - 1); - CheckSum = 0; - - if (ML == 21) - { - CTRLREG1 = 4; - CTRLREG2 = 0x14; - DeframerLaneEnable = 1; - } - else if (ML == 22) - { - CTRLREG1 = 2; - CTRLREG2 = 4; - DeframerLaneEnable = 3; - } - else if (ML == 24) - { - HD = 1; - CTRLREG1 = 1; - CTRLREG2 = 0; - DeframerLaneEnable = 0x0F; - } - else if (ML == 41) - { - CTRLREG1 = 8; - CTRLREG2 = 0; - DeframerLaneEnable = 1; - } - else if (ML == 42) - { - CTRLREG1 = 4; - CTRLREG2 = 0; - DeframerLaneEnable = 5; - } - else if (ML == 44) - { - CTRLREG1 = 2; - CTRLREG2 = 0; - DeframerLaneEnable = 0x0F; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_M_PARM, getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_M_PARM)); - return MYKONOS_ERR_DEFRAMER_INV_M_PARM; - } - - /* LMFC offset limit check */ - if (device->tx->deframer->lmfcOffset < device->tx->deframer->K) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_LMFC_K_OFFSET, device->tx->deframer->lmfcOffset); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM; - } - - subaddr[0] = 0x50; - subdata[0] = DID & 0xFFU; /* Device ID */ - subaddr[1] = 0x51; - subdata[1] = BID & 0x0F; /* Bank ID */ - subaddr[2] = 0x52; - subdata[2] = LID0 & 0x1F; /* Lane 0 ID */ - subaddr[3] = 0x53; - subdata[3] = (uint8_t)(device->tx->deframer->scramble << 7) | (DeframerL & 0x1F); /* [7] = Scramble Enable, #Lanes[4:0] */ - subaddr[4] = 0x54; - subdata[4] = DeframerF & 0xFFU; /* F[7:0] */ - subaddr[5] = 0x55; - subdata[5] = K & 0x1F; /* K[4:0] */ - subaddr[6] = 0x56; - subdata[6] = DeframerM & 0xFFU; /* M[7:0] */ - subaddr[7] = 0x57; - subdata[7] = ((CS & 0x3) << 6) | (N & 0x1F); /* [7:6] = CS[1:0], N[4:0] */ - subaddr[8] = 0x58; - subdata[8] = ((SUBCLASSV & 7) << 5) | (Np & 0x1F); /* Np[4:0] */ - subaddr[9] = 0x59; - subdata[9] = ((JESDV & 7) << 5) | (S & 0x1F); /* S[4:0] */ - subaddr[10] = 0x5A; - subdata[10] = ((HD & 1) << 7) | (CF & 0x1F); /* [7]=HD, CF[4:0] */ - subaddr[11] = 0x5B; - subdata[11] = 0x00; /* reserved */ - subaddr[12] = 0x5C; - subdata[12] = 0x00; /* reserved */ - CheckSum = (DID & 0xFF) + (BID & 0xF) + (LID0 & 0x1F) + (device->tx->deframer->scramble) + (DeframerL & 0x1F) + (DeframerF & 0xFF) + (K & 0x1F) + (DeframerM & 0xFF) - + (CS & 0x3) + (N & 0x1F) + (Np & 0x1F) + (S & 0x1F) + (HD & 1) + (CF & 0x1F) + (SUBCLASSV & 7) + (JESDV & 7); - subaddr[13] = 0x5D; - subdata[13] = CheckSum & 0xFFU; /* Checksum Lane 0 */ - subaddr[14] = 0x6D; - subdata[14] = 0xA0U; /* Bad Disparity setup */ - subaddr[15] = 0x6E; - subdata[15] = 0xA0U; /* Not in Table setup */ - subaddr[16] = 0x6F; - subdata[16] = 0xA0U; /* UnExpected K character setup */ - subaddr[17] = 0x75; - subdata[17] = CTRLREG0; /* CTRLREG 0 */ - subaddr[18] = 0x76; - subdata[18] = CTRLREG1; /* CTRLREG 1 (Bytes per frame) */ - subaddr[19] = 0x77; - subdata[19] = CTRLREG2; /* CTRLREG 2 */ - subaddr[20] = 0x78; - subdata[20] = 0x01; /* # 4*K multiframes during ILAS */ - subaddr[21] = 0x7A; - subdata[21] = 0xE0U; /* Setup JESD interrupt sources */ - subaddr[22] = 0x7B; - subdata[22] = 0x08U; /* Sync assertion setup */ - subaddr[23] = 0x7C; - subdata[23] = 0xFFU; /* Error count threshold */ - subaddr[24] = 0x7D; - subdata[24] = DeframerLaneEnable & 0xFFU; /* Lane enable */ - - for (i = 0; i <= 24; i++) - { - /* Set deframer sub-register map address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, subaddr[i]); - - /* Set deframer sub-register map data word */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, subdata[i]); - - /* Set write enable to latch data into deframer sub register map */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x01); - } - - /* Deframer: Enable lane FIFO sync */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x10, 4); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets up the chip for multichip sync, and cleans up after MCS. - * - * When working with multiple transceivers or even only one transceiver that requires deterministic - * latency between the Tx and observation and or main Rx JESD204B data path, Multichip sync is - * necessary. This function should be run after all transceivers are initialized. - * - * After the SYSREF pulses have been sent, call the MYKONOS_enableMultichipSync() function again with the - * enableMcs parameter set to 0. When enableMcs = 0, the MCS status will be returned in the mcsStatus - * parameter. - * - * Typical sequence: - * 1) Initialize all Mykonos devices in system using MYKONOS_initialize() - * 2) Run MYKONOS_enableMultichipSync with enableMcs = 1 - * 3) Send at least 3 SYSREF pulses - * 4) Run MYKONOS_enableMultichipSync with enableMcs = 0 - * 5) Load ARM, run ARM cals and continue to active Transmit/Receive - * - * mcsStatus | bit Description - * -----------|-------------------------------------------------------- - * [0] | MCS JESD SYSREF Status (1 = sync occurred) - * [1] | MCS Digital Clocks Sync Status (1 = sync occurred) - * [2] | MCS CLKPLL SDM Sync Status (1 = sync occurred) - * [3] | MCS Device Clock divider Sync Status (1 = sync occurred) - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param enableMcs =1 will enable the MCS state machine, =0 will allow reading back MCS status - * \param mcsStatus optional parameter, if pointer is not null the function Which will be populated with the mcsStatus word described in the table above. - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableMultichipSync(mykonosDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus) -{ - uint8_t clkPllSdmBypass = 0; - uint8_t mcsEnable = 0x9B; /* [7] Keeps RF LO divider enabled, Enable MCS[4] and reset Device Clock divider[3], Digital clocks[1], and JESD204 SYSREF[0] */ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableMultichipSync()\n"); -#endif - - if (enableMcs) - { - /* If CLKPLL SDM not bypassed, reset CLKPLL SDM as well. */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1, &clkPllSdmBypass, 0x40, 6); - - if (clkPllSdmBypass == 0) - { - mcsEnable |= 0x04; /* enable MCS for CLKPLL SDM */ - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_MCS_CONTROL, mcsEnable); - } - - /* if mcsStatus is a valid pointer, return the MCS status */ - if (mcsStatus != NULL) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_MCS_STATUS, mcsStatus); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables or disables SYSREF to the transceiver's RX framer - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param enable = '1' enables SYSREF to RX framer, '0' disables SYSREF to framer - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableSysrefToRxFramer(mykonosDevice_t *device, uint8_t enable) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToRxFramer()\n"); -#endif - - if (enable) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); - } - else - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables or disables SYSREF to the transceiver's Observation RX framer - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param enable = '1' enables SYSREF to OBSRX framer, '0' disables SYSREF to framer - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t *device, uint8_t enable) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToObsRxFramer()\n"); -#endif - - if (enable) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); - } - else - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enables or disables SYSREF to the transceiver's deframer - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param enable = '1' enables SYSREF to deframer, '0' disables SYSREF to deframer - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_enableSysrefToDeframer(mykonosDevice_t *device, uint8_t enable) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableSysrefToDeframer()\n"); -#endif - - if (enable) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x01, 0x01, 0); - } - else - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN, 0x00, 0x01, 0); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the transceiver's RX framer status - * - * Dependencies - * - device->spiSettings - * - * framerStatus | Description - * -------------|----------------------------------------------------------------------------- - * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. - * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. - * [5] | Framer has received the SYSREF and has retimed its LMFC - * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete - * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data - * - * \param device is a pointer to the device settings structure - * \param framerStatus is the RX framer status byte read - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM Function parameter framerStatus has NULL pointer - */ -mykonosErr_t MYKONOS_readRxFramerStatus(mykonosDevice_t *device, uint8_t *framerStatus) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readRxFramerStatus()\n"); -#endif - - if (framerStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM)); - return MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS_STRB, 0x00); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_STATUS, framerStatus); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the transceiver's Observation RX framer status - * - * Dependencies - * * - device->spiSettings - * - * obsFramerStatus | Description - * ----------------|----------------------------------------------------------------------------- - * [7] | SYSREF phase error ? a new SYSREF had different timing than the first that set the LMFC timing. - * [6] | Framer lane FIFO read/write pointer delta has changed. Can help debug issues with deterministic latency. - * [5] | Framer has received the SYSREF and has retimed its LMFC - * [4:2] | Framer ILAS state: 0=CGS, 1= 1st Multframe, 2= 2nd Multiframe, 3= 3rd Multiframe, 4= 4th multiframe, 5= Last multiframe, 6=invalid, 7= ILAS complete - * [1:0] | Framer Tx state: 0=CGS, 1= ILAS, 2 = ADC Data - * - * \param device is a pointer to the device settings structure - * \param obsFramerStatus is the OBSRX framer status byte read - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM Function parameter obsFramerStatus has NULL pointer - */ -mykonosErr_t MYKONOS_readOrxFramerStatus(mykonosDevice_t *device, uint8_t *obsFramerStatus) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readOrxFramerStatus()\n"); -#endif - - if (obsFramerStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM)); - return MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB, 0x00); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_STATUS, obsFramerStatus); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the transceiver's deframer status - * - * Dependencies - * - device->spiSettings - * - * deframerStatus | Bit Name | Description - * ----------------|--------------------------|--------------------------------------------- - * [7] | Unused | Unused - * [6] | Deframer IRQ | This bit indicates that the IRQ interrupt was asserted. - * [5] | Deframer SYSREF Received | When this bit is set, it indicates that the SYSREF pulse was received by the deframer IP - * [4] | Deframer Receiver Error | This bit is set when PRBS has received an error. - * [3] | Valid Checksum | This bit is set when the received ILAS checksum is valid. - * [2] | EOF Event | This bit captures the internal status of the framer End of Frame event. Value =1 if framing error during ILAS - * [1] | EOMF Event | This bit captures the internal status of the framer End of Multi-Frame event. Value =1 if framing error during ILAS - * [0] | FS Lost | This bit captures the internal status of the framer Frame Symbol event. Value =1 if framing error during ILAS or user data (invalid replacement characters) - * - * - * \param device is a pointer to the device settings structure - * \param deframerStatus is the deframer status byte read - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM Function parameter deframerStatus has NULL pointer - */ -mykonosErr_t MYKONOS_readDeframerStatus(mykonosDevice_t *device, uint8_t *deframerStatus) -{ - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerStatus()\n"); -#endif - - if (deframerStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM)); - return MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT, deframerStatus); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the Mykonos JESD204b Deframer determinstic FIFO depth - * - * To verify that the deterministic latency FIFO is not close to a underflow or - * overflow condition, it is recommended to check the FIFO depth. If the FIFO - * is close to an overflow or underflow condition, it is possible that from - * power up to powerup, deterministic latency may not be met. If a underflow - * or overflow occurred, the data would still be correct, but would possibly - * slip by 1 multiframe (losing deterministic latency). To correct for an - * overflow/underflow, the BBIC would need to add delay from SYSREF until - * the first symbol in a multiframe - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param fifoDepth Return value that describes the depth of the Mykonos - * deterministic latency deframer FIFO. - * \param readEnLmfcCount Returns the LMFC count value when the deterministic FIFO read enable was asserted. - * Counts at the Mykonos internal deframer PCLK frequency. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM Error: function parameter fifoDepth is a NULL pointer - * \retval MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM Error: function parameter readEnLmfcCount is a NULL pointer - * - */ -mykonosErr_t MYKONOS_getDeframerFifoDepth(mykonosDevice_t *device, uint8_t *fifoDepth, uint8_t *readEnLmfcCount) -{ - uint8_t fifoReadPtr = 0; - uint8_t fifoWritePtr = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDeframerFifoDepth()\n"); -#endif - - if (fifoDepth == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM)); - return MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM; - } - - if (readEnLmfcCount == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM)); - return MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_STAT_STRB, 0x00); - - /* read/write pointers are 7 bits, (0 - 127) */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_RD_ADDR, &fifoReadPtr, 0x7F, 0); - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_ADDR, &fifoWritePtr, 0x7F, 0); - - /* Adding 128 and modulus 128 handle the wrap cases where the read pointer - * is less than write pointer - */ - *fifoDepth = (((fifoWritePtr + 128) - fifoReadPtr) % 128); - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DET_FIFO_PHASE, readEnLmfcCount); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Selects the PRBS type and enables or disables RX Framer PRBS20 generation - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3 - * \param enable '1' = enables PRBS RX framer PRBS generator, '0' = disables PRBS generator - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter, use ENUM - * - */ -mykonosErr_t MYKONOS_enableRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable) -{ - uint8_t wrmask = 0; - uint8_t enableBit = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableRxFramerPrbs()\n"); -#endif - - enableBit = (enable > 0) ? 1 : 0; - - if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) - { - wrmask = ((uint8_t)polyOrder << 1) | enableBit; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM)); - return MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, wrmask); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Selects the PRBS type and enables or disables OBSRX Framer PRBS20 generation - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param polyOrder selects the PRBS type based on a two-bit value range from 0-3 - * \param enable '1' = enables PRBS OBSRX framer PRBS generator, '0' = disables PRBS generator - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM polyOrder parameter is not a valid value - use ENUM - */ -mykonosErr_t MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable) -{ - uint8_t wrmask = 0; - uint8_t enableBit = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableObsRxFramerPrbs()\n"); -#endif - - enableBit = (enable > 0) ? 1 : 0; - - if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) - { - wrmask = ((uint8_t)polyOrder << 1) | enableBit; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM)); - return MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, wrmask); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Injects a PRBS error into the RX data path - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_rxInjectPrbsError(mykonosDevice_t *device) -{ - uint8_t prbsControl = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rxInjectPrbsError()\n"); -#endif - - /* reading current PRBS20 control register contents */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, &prbsControl); - - /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl |= 0x10); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FRAMER_PRBS20_CTL, prbsControl &= ~0x10); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Initiates a PRBS error injection into the Observation RX data path - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_obsRxInjectPrbsError(mykonosDevice_t *device) -{ - uint8_t prbsControl = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_obsRxInjectPrbsError()\n"); -#endif - - /* reading current PRBS20 control register contents */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, &prbsControl); - - /* setting bit 4 in framer PRBS20 control register and then clearing it for error injection */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl |= 0x10); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL, prbsControl &= ~0x10); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Configures and enables or disables the transceiver's deframer PRBS checker - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param lanes selects the lane for PRBS checking based on a 4-bit mask, where each weighted bit - * corresponds with a different lane selection as such: '1' = lane 0, '2' = lane 1, '4' = lane 2, '8' = lane 3 - * \param polyOrder selects the PRBS type based on enum values (MYK_PRBS7, MYK_PRBS15, MYK_PRBS31) - * \param enable '1' = enables checking, '0' = disables checking - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM Invalid polyOrder parameter - use ENUM - * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM Invalid enable (valid 0-1) or lanes (valid 0-15) parameter - */ -mykonosErr_t MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t *device, uint8_t lanes, mykonosPrbsOrder_t polyOrder, uint8_t enable) -{ - uint8_t wrmask = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDeframerPrbsChecker()\n"); -#endif - - if ((enable <= 0x01) && (lanes <= 0x0F)) - { - if ((polyOrder == MYK_PRBS7) || (polyOrder == MYK_PRBS15) || (polyOrder == MYK_PRBS31)) - { - wrmask = ((lanes << 4) | ((uint8_t)polyOrder << 1) | enable); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM; - } - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, wrmask); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the deframer PRBS counters - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * \param counterSelect selects the PRBS error counter to be read based on values between 0-3 - * If counterSelect exceeds this value an error is thrown. - * - * \param prbsErrorCount is return value after reading the PRBS error count - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM Function parameter prbsErrorCount has NULL pointer - * \retval MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM if counterSelect is out of bounds - */ -mykonosErr_t MYKONOS_readDeframerPrbsCounters(mykonosDevice_t *device, uint8_t counterSelect, uint32_t *prbsErrorCount) -{ - uint8_t wrmask = 0x00; - uint8_t errorCnt[3] = {0}; - const uint8_t COUNTER_SATURATE = 0x40; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readDeframerPrbsCounters()\n"); -#endif - - if (prbsErrorCount == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM)); - return MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM; - } - - if (counterSelect & ~0x03) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM)); - return MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM; - } - else - { - wrmask = (uint8_t)(COUNTER_SATURATE | (counterSelect << 4)); - *prbsErrorCount = 0x00000000; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask |= 0x01); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE, wrmask &= ~0x01); - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_7_TO_0, &errorCnt[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_15_TO_8, &errorCnt[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_23_TO_16, &errorCnt[2]); - - *prbsErrorCount = (uint32_t)(errorCnt[2] << 16) | (uint32_t)(errorCnt[1] << 8) | (uint32_t)(errorCnt[0]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Clears the deframer/deserializer PRBS counters - * - * Dependencies - * - device->spiSettings - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t *device) -{ - uint8_t spiReg = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_clearDeframerPrbsCounters()\n"); -#endif - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, &spiReg); - spiReg &= ~0x08; //make sure PRBS clear bit is 0 - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, (spiReg | 0xF8)); //clear counters for all lanes - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_PRBS20_CTL, spiReg); //set reg back to previous value - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the lane 0 JESD204B deframer configuration and compares it against the ILAS received values - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param mismatch [15-0] is a bit-encoded word which for mismatch[15] = '0' = no mismatch, '1' = mismatch for one or more parameters - * mismatch bits [14-0] are aligned with the mykonosJesd204bLane0Config_t structure members starting at '0' = DID. The aligned bit is set to - * '1' if the configuration parameter does not agree with its corresponding received ILAS value, otherwise '0' if they agree. - * - * The bit assignments for the 16-bit word are: - * mismatch | bit description - * -----------|-------------------------------------------------------- - * [0] | JESD204B DID: device ID - * [1] | JESD204B BID: bank ID - * [2] | JESD204B LID0: lane ID - * [3] | JESD204B L: lanes per data converter - * [4] | JESD204B SCR: scramble setting - * [5] | JESD204B F: octets per frame - * [6] | JESD204B K: frames per multiframe - * [7] | JESD204B M: number of data converters - * [8] | JESD204B N: data converter sample resolution - * [9] | JESD204B CS: number of control bits transferred per sample per frame - * [10] | JESD204B NP: JESD204B word size based on the highest data converter resolution - * [11] | JESD204B S: number of samples per converter per frame - * [12] | JESD204B CF: '0' = control bits appended to each sample, '1' = control bits appended to end of frame - * [13] | JESD204B HD: high density bit, where '0' = samples are contained with single lane, '1' = samples are divided over more than one lane - * [14] | JESD204B FCHK0: configuration checksum OK bit. where '1' = fail, '0' = pass - * [15] | MISMATCH DETECTED BIT: bits 0-14 are ored together to set this bit - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM Function parameter mismatch has NULL pointer - */ -mykonosErr_t MYKONOS_jesd204bIlasCheck(mykonosDevice_t *device, uint16_t *mismatch) -{ - uint8_t i = 0; - uint8_t ilasdata[15] = {0}; - uint8_t cfgdata[15] = {0}; - mykonosJesd204bLane0Config_t lane0ILAS; - mykonosJesd204bLane0Config_t lane0Cfg; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_jesd204bIlasCheck()\n"); -#endif - - if (mismatch == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM)); - return MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM; - } - - *mismatch = 0; - - /* setting deframer read received ILAS data */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_WR_EN, 0x00); - - /* reading deframer received ILAS register contents into array */ - for (i = 0; i < 15; i++) - { - /* setting the deframer sub-address for received ilas data */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_RECVD + i); - - /* reading the received ILAS data into byte array */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &ilasdata[i]); - } - - /* reading deframer config register contents into array */ - for (i = 0; i < 15; i++) - { - /* setting the deframer sub-address for received ilas data */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_ADDR, MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_CFG + i); - - /* reading the received ILAS data into byte array */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DEFRAMER_DATA, &cfgdata[i]); - } - - /* loading the structures with the read values for easier reading when doing compares */ - lane0ILAS.DID = ilasdata[0]; - lane0ILAS.BID = ilasdata[1] & 0x0F; - lane0ILAS.LID0 = ilasdata[2] & 0x1F; - lane0ILAS.L = ilasdata[3] & 0x1F; - lane0ILAS.SCR = ilasdata[3] >> 7; - lane0ILAS.F = ilasdata[4]; - lane0ILAS.K = ilasdata[5] & 0x1F; - lane0ILAS.M = ilasdata[6]; - lane0ILAS.N = ilasdata[7] & 0x1F; - lane0ILAS.CS = ilasdata[7] >> 6; - lane0ILAS.NP = ilasdata[8] & 0x1F; - lane0ILAS.S = ilasdata[9] & 0x1F; - lane0ILAS.CF = ilasdata[10] & 0x1F; - lane0ILAS.HD = ilasdata[10] >> 7; - lane0ILAS.FCHK0 = ilasdata[13]; - - lane0Cfg.DID = cfgdata[0]; - lane0Cfg.BID = cfgdata[1] & 0x0F; - lane0Cfg.LID0 = cfgdata[2] & 0x0F; - lane0Cfg.L = cfgdata[3] & 0x1F; - lane0Cfg.SCR = cfgdata[3] >> 7; - lane0Cfg.F = cfgdata[4]; - lane0Cfg.K = cfgdata[5] & 0x1F; - lane0Cfg.M = cfgdata[6]; - lane0Cfg.N = cfgdata[7] & 0x1F; - lane0Cfg.CS = cfgdata[7] >> 6; - lane0Cfg.NP = cfgdata[8] & 0x1F; - lane0Cfg.S = cfgdata[9] & 0x1F; - lane0Cfg.CF = cfgdata[10] & 0x1F; - lane0Cfg.HD = cfgdata[10] >> 7; - lane0Cfg.FCHK0 = cfgdata[13]; - - /* performing ILAS mismatch check */ - if (lane0ILAS.DID != lane0Cfg.DID) - { - *mismatch |= 0x0001; - } - - if (lane0ILAS.BID != lane0Cfg.BID) - { - *mismatch |= 0x0002; - } - - if (lane0ILAS.LID0 != lane0Cfg.LID0) - { - *mismatch |= 0x0004; - } - - if (lane0ILAS.L != lane0Cfg.L) - { - *mismatch |= 0x0008; - } - - if (lane0ILAS.SCR != lane0Cfg.SCR) - { - *mismatch |= 0x0010; - } - - if (lane0ILAS.F != lane0Cfg.F) - { - *mismatch |= 0x0020; - } - - if (lane0ILAS.K != lane0Cfg.K) - { - *mismatch |= 0x0040; - } - - if (lane0ILAS.M != lane0Cfg.M) - { - *mismatch |= 0x0080; - } - - if (lane0ILAS.N != lane0Cfg.N) - { - *mismatch |= 0x0100; - } - - if (lane0ILAS.CS != lane0Cfg.CS) - { - *mismatch |= 0x0200; - } - - if (lane0ILAS.NP != lane0Cfg.NP) - { - *mismatch |= 0x0400; - } - - if (lane0ILAS.S != lane0Cfg.S) - { - *mismatch |= 0x0800; - } - - if (lane0ILAS.CF != lane0Cfg.CF) - { - *mismatch |= 0x1000; - } - - if (lane0ILAS.HD != lane0Cfg.HD) - { - *mismatch |= 0x2000; - } - - if (lane0ILAS.FCHK0 != lane0Cfg.FCHK0) - { - *mismatch |= 0x4000; - } - - if (*mismatch) - { - *mismatch |= 0x8000; - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_ERR_JESD204B_ILAS_MISMATCH, - getMykonosErrorMessage(MYKONOS_ERR_JESD204B_ILAS_MISMATCH)); - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Select data to inject into the Rx framer input (ADC data or Loopback data from deframer output) - * - * This function allows inputting deframed data (IQ samples) from the Tx data path into the Rx framer. - * For this to work correctly, the IQ data rate of the Tx data path must match the Rx IQ data rate. - * Framer/Deframer JESD204 config parameters can vary as long as the Rx and Tx IQ rates match. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device A pointer to the device settings structure - * \param dataSource 0 = ADC data at Rx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Rx framer - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource) -{ - uint8_t enableLoopBack = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRxFramerDataSource()\n"); -#endif - - enableLoopBack = (dataSource > 0) ? 1 : 0; - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Select data to inject into the ObsRx framer input (ADC data or Loopback data from deframer output) - * - * This function allows inputting deframed data (IQ samples) from the Tx data path into the Obs Rx framer. - * For this to work correctly, the IQ data rate of the Tx data path must match the ORx IQ data rate. - * Framer/Deframer JESD204 config parameters can vary as long as the Obs Rx and Tx IQ rates match. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device A pointer to the device settings structure - * \param dataSource 0 = ADC data at ObsRx Framer input, 1 = Deframed Tx JESD204 IQ samples input into Obs Rx framer - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setObsRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource) -{ - uint8_t enableLoopBack = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setObsRxFramerDataSource()\n"); -#endif - - enableLoopBack = (dataSource > 0) ? 1 : 0; - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV, enableLoopBack, 0x10, 4); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Runs the Mykonos initialization calibrations - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * ENUM mykonosInitCalibrations_t can be used to OR together to generate the calMask parameter. - * - * calMask Bit | Calibration - * ------------|---------------------- - * 0 | Tx BB Filter - * 1 | ADC Tuner - * 2 | TIA 3dB Corner - * 3 | DC Offset - * 4 | Tx Attenuation Delay - * 5 | Rx Gain Delay - * 6 | Flash Cal - * 7 | Path Delay - * 8 | Tx LO Leakage Internal - * 9 | Tx LO Leakage External - * 10 | Tx QEC Init - * 11 | LoopBack Rx LO Delay - * 12 | LoopBack Rx Rx QEC Init - * 13 | Rx LO Delay - * 14 | Rx QEC Init - * 15 | DPD Init - * 16 | Tx CLGC (Closed Loop Gain Control) - * 17 | Tx VSWR Init - * [31-18] | Ignored - Future space for new calibrations - * - * \param device A pointer to the device settings structure - * \param calMask A bitmask that informs the Mykonos ARM processor which calibrations to run - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_runInitCals(mykonosDevice_t *device, uint32_t calMask) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - const uint8_t RUNINITCALS_OPCODE = 0x02; - uint8_t payload[4] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_runInitCals()\n"); -#endif - - payload[0] = (uint8_t)(calMask & 0xFF); - payload[1] = (uint8_t)((calMask >> 8) & 0xFF); - payload[2] = (uint8_t)((calMask >> 16) & 0xFF); - payload[3] = (uint8_t)((calMask >> 24) & 0xFF); - - retVal = MYKONOS_sendArmCommand(device, RUNINITCALS_OPCODE, &payload[0], sizeof(payload)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Blocking waits for the Mykonos initialization calibrations to complete - * - * The *errorFlag and *errorCode parameters are optional. If the pointers are - * set to null, no values will be returned. If the function returns an error - * that the init calibration failed, use the MYKONOS_getInitCalStatus() function - * to get more detailed information about why the init cal failed. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device A pointer to the device settings structure - * \param timeoutMs A timeout value in Ms to wait for the calibrations to complete - * \param errorFlag A 3bit error flag that helps identify what went wrong in the ARM. 0=No Error - * \param errorCode The value represents the init calibration object ID that caused a failure. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_WAIT_INITCALS_ARMERROR ARM returned error unrelated to init cals - */ -mykonosErr_t MYKONOS_waitInitCals(mykonosDevice_t *device, uint32_t timeoutMs, uint8_t *errorFlag, uint8_t *errorCode) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - mykonosErr_t retValCalStatus = MYKONOS_ERR_OK; - uint8_t cmdStatusByte = 0; - uint8_t _errorFlag = 0; /* Local version of parameter */ - mykonosInitCalStatus_t initCalStatus = {0}; - - const uint8_t INITCALS_CAL_ERROR = 0x07; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitInitCals()\n"); -#endif - - /* Clear before making any calls that can throw errors */ - if (errorFlag != NULL) - { - *errorFlag = 0; - } - - /* Clear before making any calls that can throw errors */ - if (errorCode != NULL) - { - *errorCode = 0; - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RUNINIT_OPCODE, timeoutMs, &cmdStatusByte); - _errorFlag = cmdStatusByte >> 1; /* remove pending bit in [0], error flag is in bits [3:1] */ - - if (errorFlag != NULL) - { - *errorFlag = _errorFlag; - } - - if (retVal != MYKONOS_ERR_OK) - { - if (_errorFlag == INITCALS_CAL_ERROR) - { - /* return Error code if a calibration had an error */ - retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus); - if (retValCalStatus == MYKONOS_ERR_OK) - { - if (errorCode != NULL) - { - *errorCode = initCalStatus.initErrCal; - } - } - - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED, - getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED)); - return MYKONOS_ERR_WAIT_INITCALS_CALFAILED; - } - else if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR)); - return MYKONOS_ERR_WAIT_INITCALS_ARMERROR; - } - } - - /* Same logic if MYKONOS_waitArmCmdStatus() did not return an error, but cmdStatusByte shows an ARM error */ - if (_errorFlag == INITCALS_CAL_ERROR) - { - /* return Error code if a calibration had an error */ - retValCalStatus = MYKONOS_getInitCalStatus(device, &initCalStatus); - if (retValCalStatus == MYKONOS_ERR_OK) - { - if (errorCode != NULL) - { - *errorCode = initCalStatus.initErrCal; - } - } - - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_CALFAILED, - getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_CALFAILED)); - return MYKONOS_ERR_WAIT_INITCALS_CALFAILED; - } - else if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAIT_INITCALS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_WAIT_INITCALS_ARMERROR)); - return MYKONOS_ERR_WAIT_INITCALS_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Aborts from an on going ARM init calibration operation. - * - * The ARM init calibrations can take several seconds. If for any reason the Baseband processor - * needs to stop the running ARM calibration sequence, call this function. The *calsCompleted - * parameter is an option parameter that will return which cals completed before the abort - * command was received. If *calsCompleted is a null pointer, no value will be returned. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device A pointer to the device settings structure - * \param calsCompleted A bitmask is returned which describes which cals completed during the previous - * MYKONOS_runInitCals() call. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM Function parameter calsCompleted has NULL pointer - */ -mykonosErr_t MYKONOS_abortInitCals(mykonosDevice_t *device, uint32_t *calsCompleted) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; //1 second timeout - uint8_t cmdStatusByte = 0; - uint8_t payload = 0x43; /* object ID to get INIT_CAL_DONE status */ - uint8_t calCompleteBitField[4] = {0, 0, 0, 0}; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_ABORT_OPCODE, 0, 0); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_ABORT_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if timeout occurred */ - } - - /* Read back Calibration Completion status */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload, sizeof(payload)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if timeout occurred */ - } - - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + 4), &calCompleteBitField[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (calsCompleted != NULL) - { - *calsCompleted = ((uint32_t)(calCompleteBitField[3]) << 24) | ((uint32_t)(calCompleteBitField[2]) << 16) | ((uint32_t)(calCompleteBitField[1]) << 8) - | ((uint32_t)(calCompleteBitField[0])); - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM)); - return MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Gets the device initialization calibration status - * - * This function requests the init cal status information from the Mykonos ARM - * processor. The ARM returns information including a bitmask that describes - * which calibrations have completed during the last cal of runInitCals, as - * well as the init cals that have run successfully since loading the ARM. If - * an ARM error does occur during one of the init calibrations, the initErrCal - * member returns the object ID of the failing calibration. The initErrCode - * returns the specific ARM error code that caused that calibration to fail. - * The calsMinimum structure member describes the minimum set of init calibrations - * required to complete by the ARM before it will allow the device to move to - * the radioOn state. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device A pointer to the device settings structure - * \param initCalStatus Pointer to a structure that returns cal status information such as cals completed since last run, and init error codes - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM if initCalStatus parameter is a NULL pointer - * \retval MYKONOS_ERR_GETINITCALSTATUS_ARMERROR if ARM returned an error while requesting the init cal status information - */ -mykonosErr_t MYKONOS_getInitCalStatus(mykonosDevice_t *device, mykonosInitCalStatus_t *initCalStatus) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t cmdStatusByte = 0; - uint8_t calStatusArray[14] = {0}; - uint8_t payload[1] = {MYKONOS_ARM_OBJECTID_INIT_CAL_DONE}; - - uint32_t timeoutMs = 1000; - - /* Verify function parameter pointer is not NULL */ - if (initCalStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM)); - return MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM; - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &payload[0], sizeof(payload)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR)); - return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR; - } - - return retVal; /* Will return if timeout occurred */ - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_GETINITCALSTATUS_ARMERROR)); - return MYKONOS_ERR_GETINITCALSTATUS_ARMERROR; - } - - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &calStatusArray[0], sizeof(calStatusArray), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - initCalStatus->calsDoneLifetime = ((uint32_t)(calStatusArray[3]) << 24) | ((uint32_t)(calStatusArray[2]) << 16) | ((uint32_t)(calStatusArray[1]) << 8) - | ((uint32_t)(calStatusArray[0])); - initCalStatus->calsDoneLastRun = ((uint32_t)(calStatusArray[7]) << 24) | ((uint32_t)(calStatusArray[6]) << 16) | ((uint32_t)(calStatusArray[5]) << 8) - | ((uint32_t)(calStatusArray[4])); - initCalStatus->calsMinimum = ((uint32_t)(calStatusArray[11]) << 24) | ((uint32_t)(calStatusArray[10]) << 16) | ((uint32_t)(calStatusArray[9]) << 8) - | ((uint32_t)(calStatusArray[8])); - initCalStatus->initErrCal = calStatusArray[12]; - initCalStatus->initErrCode = calStatusArray[13]; - - return MYKONOS_ERR_OK; -} - -/** - * \brief Instructs the ARM processor to move the radio state to the Radio ON state - * - * When the ARM to the Radio On state, the enabled Rx and Tx signal chains will power up, - * and the ARM tracking calibrations will begin. To exit this state back to a low power, - * offline state, call the MYKONOS_radioOff() function. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ARM_RADIOON_FAILED ARM returned error running this command - */ -mykonosErr_t MYKONOS_radioOn(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; //1 second timeout - uint8_t cmdStatusByte = 0; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_RADIOON_OPCODE, 0, 0); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_RADIOON_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED)); - return MYKONOS_ERR_ARM_RADIOON_FAILED; - } - - return retVal; /* Will return if timeout occurred */ - } - - /* If ARM command error flag is 2, the command was not accepted, RUN_INIT must complete first */ - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOON_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOON_FAILED)); - return MYKONOS_ERR_ARM_RADIOON_FAILED; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Instructs the ARM processor to move the radio state to the off state - * - * When the ARM moves from the Radio On state to Radio Off (Idle) the ARM tracking calibrations - * are stopped and the TxEnable/RxEnable, etc GPIO control pins will be ignored. This will also - * keep the receive and transmit chains powered down until the MYKONOS_radioOn() function - * is called again. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ARM_RADIOOFF_FAILED ARM returned error running this command - */ -mykonosErr_t MYKONOS_radioOff(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - const uint8_t ABORTCAL_OPCODE = 0x00; - uint32_t timeoutMs = 1000; //1 second timeout - uint8_t cmdStatusByte = 0; - - retVal = MYKONOS_sendArmCommand(device, ABORTCAL_OPCODE, 0, 0); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; /* Will return if mailbox busy bit is busy for more than 2 seconds */ - } - - retVal = MYKONOS_waitArmCmdStatus(device, ABORTCAL_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED)); - return MYKONOS_ERR_ARM_RADIOOFF_FAILED; - } - - return retVal; /* Will return if timeout occurred */ - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARM_RADIOOFF_FAILED, getMykonosErrorMessage(MYKONOS_ERR_ARM_RADIOOFF_FAILED)); - return MYKONOS_ERR_ARM_RADIOOFF_FAILED; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the current ARM radio state - * - * Currently, *radioStatus only returns data in the lower 8 bits, but - * is defined as a 32bit status to allow for more information to be returned - * in the future. - * - * radioStatus | Bitfield - * -------------|------------------ - * [1:0] | State[1:0], 0=POWERUP, 1=READY, 2=INIT, 3=RADIO ON - * [3:2] | unused - * [4] | TDD_nFDD , 1= TDD, 0=FDD - * [7:5] | unused - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param radioStatus The current ARM radio state is returned in this parameter - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM Function parameter radioStatus has a NULL pointer - */ -mykonosErr_t MYKONOS_getRadioState(mykonosDevice_t *device, uint32_t *radioStatus) -{ - uint8_t status = 0; - - /* if radioStatus is not null */ - if (radioStatus != NULL) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_0, &status); - *radioStatus = (uint32_t)status; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM)); - return MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets which ARM tracking cals are enabled during the radioOn state. - * - * This command must be called during radioOff state. If called during radioOn, - * an error will be returned. The enum mykonosTrackingCalibrations_t can be used to - * OR together to form the enableMask parameter. - * - * enableMask | Bit description - * ------------|------------ - * [0] | TRACK_RX1_QEC - * [1] | TRACK_RX2_QEC - * [2] | TRACK_ORX1_QEC - * [3] | TRACK_ORX2_QEC - * [4] | TRACK_TX1_LOL - * [5] | TRACK_TX2_LOL - * [6] | TRACK_TX1_QEC - * [7] | TRACK_TX2_QEC - * [8] | TRACK_TX1_DPD - * [9] | TRACK_TX2_DPD - * [10] | TRACK_TX1_CLGC - * [11] | TRACK_TX2_CLGC - * [12] | TRACK_TX1_VSWR - * [13] | TRACK_TX2_VSWR - * [16] | TRACK_ORX1_QEC_SNLO - * [17] | TRACK_ORX2_QEC_SNLO - * [18] | TRACK_SRX_QEC - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param enableMask A bitmask that selects which cals to run during radioOn state. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR Error: Tracking cals can only be enabled in the radioOff state. - * \retval MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR ARM returned error when executing this command - */ -mykonosErr_t MYKONOS_enableTrackingCals(mykonosDevice_t *device, uint32_t enableMask) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[4] = {0, 0, 0, 0}; - uint8_t extData[4] = {MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0x00, 0x00, 0x04}; //Target ARM Object ID, Offset LSB, Offset MSB, Length - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint32_t radioStatus = 0; - uint8_t allowTx1AttenUpdates = 0; - uint8_t allowTx2AttenUpdates = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableTrackingCals()\n"); -#endif - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* throw error if not in radioOff/IDLE state */ - if ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR, - getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR)); - return MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR; - } - - /* In the ARM, DPD tracking and CLGC tracking share the same cal. Must - * set extra enable bits in ARM Memory to tell which cal to run. */ - retVal = enableDpdTracking(device, ((enableMask & (uint32_t)TRACK_TX1_DPD) ? 1 : 0), ((enableMask & (uint32_t)TRACK_TX2_DPD) ? 1 : 0)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (((device->profilesValid & TX_PROFILE_VALID) > 0) && (device->tx->clgcConfig != NULL)) - { - allowTx1AttenUpdates = device->tx->clgcConfig->allowTx1AttenUpdates; - allowTx2AttenUpdates = device->tx->clgcConfig->allowTx2AttenUpdates; - } - else - { - allowTx1AttenUpdates = 0; - allowTx2AttenUpdates = 0; - } - - retVal = enableClgcTracking(device, ((allowTx1AttenUpdates > 0) ? 1 : 0), ((allowTx2AttenUpdates > 0) ? 1 : 0)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - armData[0] = (uint8_t)(enableMask & 0xFF); - armData[1] = (uint8_t)((enableMask >> 8) & 0xFF); - armData[2] = (uint8_t)((enableMask >> 16) & 0xFF); - armData[3] = (uint8_t)((enableMask >> 24) & 0xFF); - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR)); - return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR)); - return MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reschedules a tracking calibration to run. Can be used to - * override the tracking calibration timer and force a tracking calibration to run. - * Can be used to reschedule a tracking calibration after a tracking calibration - * error has been detected. Only one tracking calibration object can be scheduled - * per channel per function call. - * - * \pre Command can be called in either Radio On or Radio Off state. ARM must be - * initialized. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param trackingCal Selects the tracking calibration to schedule. - * - * \retval MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV Not valid calibration passed - * \retval MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG ARM error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_rescheduleTrackingCal(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extData[3] = {0}; - uint8_t cmdStatusByte = 0; - uint32_t timeoutMs = 1000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_rescheduleTrackingCal()\n"); -#endif - - switch (trackingCal) - { - case TRACK_RX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING; - extData[2] = 0; - break; - - case TRACK_RX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING; - extData[2] = 1; - break; - - case TRACK_ORX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING; - extData[2] = 0; - break; - - case TRACK_ORX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING; - extData[2] = 1; - break; - - case TRACK_TX1_LOL: - extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING; - extData[2] = 0; - break; - - case TRACK_TX2_LOL: - extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING; - extData[2] = 1; - break; - - case TRACK_TX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING; - extData[2] = 0; - break; - - case TRACK_TX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING; - extData[2] = 1; - break; - - case TRACK_TX1_DPD: - extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; - extData[2] = 0; - break; - - case TRACK_TX2_DPD: - extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; - extData[2] = 1; - break; - - case TRACK_TX1_CLGC: - extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; - extData[2] = 0; - break; - - case TRACK_TX2_CLGC: - extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; - extData[2] = 1; - break; - - case TRACK_TX1_VSWR: - extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; - extData[2] = 0; - break; - - case TRACK_TX2_VSWR: - extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; - extData[2] = 1; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV, - getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV)); - return MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV; - } - - extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_PENDING; - - /* sending ARM command */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG; - } - - return retVal; -} - -/** - * \brief Suspend or resume tracking calibrations in RADIO_ON. - * - * This function is used to suspend or resume active tracking calibrations based on the passed mask trackingCals. - * - * \pre Command can be called in Radio On. - * - * trackCals[bit] | Bit description - * ----------------|------------ - * [0] | TRACK_RX1_QEC - * [1] | TRACK_RX2_QEC - * [2] | TRACK_ORX1_QEC - * [3] | TRACK_ORX2_QEC - * [4] | TRACK_TX1_LOL - * [5] | TRACK_TX2_LOL - * [6] | TRACK_TX1_QEC - * [7] | TRACK_TX2_QEC - * [8] | TRACK_TX1_DPD - * [9] | TRACK_TX2_DPD - * [10] | TRACK_TX1_CLGC - * [11] | TRACK_TX2_CLGC - * [12] | TRACK_TX1_VSWR - * [13] | TRACK_TX2_VSWR - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param trackCals Selects the tracking calibrations to suspend or resume during the radio ON state. - * mykonosTrackingCalibrations_t enumerated types are or'd together to form the tracking calibration - * mask word. If the bit is high the calibration will resume, if the bit is low the calibration will be suspended. - * - * \retval MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV Not valid calibration mask passed for trackCals - * \retval MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG ARM error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setAllTrackCalState(mykonosDevice_t *device, uint32_t trackCals) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t cfgData[4] = {0}; - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME, 0x0F, 0}; - uint8_t cmdStatusByte = 0; - uint32_t enTrackCal = 0x00; - uint32_t timeoutMs = 1000; - - const uint32_t TRACKING_MASK = 0x3FFF; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setAllTrackCalState()\n"); -#endif - - /* reading enabled tracking calibrations */ - retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal); - - /* trackingCalMask check */ - if (((trackCals | enTrackCal) > enTrackCal) || (trackCals > TRACKING_MASK)) - { - /* invalid cal mask error return, tracking cal not enable so we can not resume it */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV)); - return MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV; - } - - /* convert tracking mask to array of uint8_t type */ - cfgData[0] = (uint8_t)(trackCals & 0xFF); - cfgData[1] = (uint8_t)((trackCals >> 8) & 0xFF); - cfgData[2] = (uint8_t)((trackCals >> 16) & 0x0FF); - cfgData[3] = (uint8_t)((trackCals >> 24) & 0xFF); - - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], sizeof(cfgData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG; - } - - return retVal; -} - -/** - * \brief Get the Suspended or Resumed state for tracking calibrations - * - * This function is used to get the suspend or resume state of all active tracking calibrations and the state is stored in trackCals. - * - * \pre Command can be called in Radio On. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param trackCals pointer to store the tracking calibration state. - * If the bit is set then the tracking calibration is resumed and if not set then the tracking cal is suspended, the bit field follows: - * - * trackCals[bit] | Bit description - * ---------------|------------ - * [0] | TRACK_RX1_QEC - * [1] | TRACK_RX2_QEC - * [2] | TRACK_ORX1_QEC - * [3] | TRACK_ORX2_QEC - * [4] | TRACK_TX1_LOL - * [5] | TRACK_TX2_LOL - * [6] | TRACK_TX1_QEC - * [7] | TRACK_TX2_QEC - * [8] | TRACK_TX1_DPD - * [9] | TRACK_TX2_DPD - * [10] | TRACK_TX1_CLGC - * [11] | TRACK_TX2_CLGC - * [12] | TRACK_TX1_VSWR - * [13] | TRACK_TX2_VSWR - * - * \retval MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM Null parameter passed for trackCals - * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG ARM error flag set. - * \retval MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR ARM command error. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getAllTrackCalState(mykonosDevice_t *device, uint32_t *trackCals) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; - uint8_t armData[4] = {0}; - uint8_t cmdStatusByte = 0; - uint32_t timeoutMs = 1000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getAllTrackCalState()\n"); -#endif - - /* Check for passed parameter */ - if (trackCals == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM)); - return MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM; - } - - /* sending ARM command */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG; - } - - /* read 32-bit tracking state from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - *trackCals = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24); - - return retVal; -} - -/** - * \brief Suspend or resume individual tracking calibration - * - * \pre The tracking calibration must have been enabled with MYKONOS_enableTrackingCals(), this command can be called in Radio On. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param trackingCal Selects the tracking calibration to resume or suspend. - * \param trackCalState if set then the selected tracking calibration will be resumed and if not set then the tracking cal will be suspended - * - * \retval MYKONOS_ERR_SETSTATE_TRACK_CAL_INV Not valid calibration passed - * \retval MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG ARM error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t trackCalState) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extData[2] = {0}; - uint8_t cmdStatusByte = 0; - uint8_t suspendTrack = 0x0F; - uint32_t timeoutMs = 1000; - uint32_t enTrackCal = 0x00; - - const uint8_t CHANNEL_1 = 0x00; - const uint8_t CHANNEL_2 = 0x10; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setTrackingCalState()\n"); -#endif - - if (trackCalState > 0) - { - suspendTrack = 0x2F; - } - - /* reading enabled tracking calibrations */ - retVal = MYKONOS_getEnabledTrackingCals(device, &enTrackCal); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* trackingCalMask check */ - if (((uint8_t)trackingCal & enTrackCal) != (uint8_t)trackingCal) - { - /* invalid cal mask error return, tracking cal not enable so we can not resume or suspend it */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV)); - return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV; - } - - switch (trackingCal) - { - case TRACK_RX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_RX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_RXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_ORX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_ORX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_TX1_LOL: - extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_TX2_LOL: - extData[1] = MYKONOS_ARM_OBJECTID_TXLOL_TRACKING & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_TX1_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_TX2_QEC: - extData[1] = MYKONOS_ARM_OBJECTID_TXQEC_TRACKING & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_TX1_DPD: - extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_TX2_DPD: - extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_TX1_CLGC: - extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_TX2_CLGC: - extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - case TRACK_TX1_VSWR: - extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack; - extData[1] |= CHANNEL_1; - break; - - case TRACK_TX2_VSWR: - extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG & suspendTrack; - extData[1] |= CHANNEL_2; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_CAL_INV)); - return MYKONOS_ERR_SETSTATE_TRACK_CAL_INV; - } - - extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; - - /* sending ARM command */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG; - } - } - - return retVal; -} - -/** - * \brief Get the Suspended or Resumed state for individual tracking calibration - * - * \pre Command can be called in Radio On. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param trackingCal Selects the tracking calibration to get the resumed or suspended state. - * \param trackCalState pointer to store the tracking calibration state, - * if set then the selected tracking calibration is resumed and if not set then the tracking cal is suspended - * - * \retval MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM Null parameter passed to trackCalState - * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG ARM command error flag set. - * \retval MYKONOS_ERR_GETSTATE_TRACK_ARMERROR ARM command error. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t *trackCalState) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extData = MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME; - uint8_t armData[4] = {0}; - uint8_t cmdStatusByte = 0; - uint32_t timeoutMs = 1000; - uint32_t trackMask = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTrackingCalState()\n"); -#endif - - /* Check for passed parameter */ - if (trackCalState == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM)); - return MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM; - } - - /* sending ARM command */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData, sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG; - } - - /* read 32-bit tracking state from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - trackMask = (uint32_t)armData[0] | ((uint32_t)armData[1] << 8) | ((uint32_t)armData[2] << 16) | ((uint32_t)armData[3] << 24); - - if (trackMask & (uint32_t)trackingCal) - { - *trackCalState = 1; - } - else - { - *trackCalState = 0; - } - - return retVal; -} - -/** - * \brief Reads back which ARM tracking cals are enabled - * - * enableMask | Bit description - * ------------|---------------------- - * [0] | TRACK_RX1_QEC - * [1] | TRACK_RX2_QEC - * [2] | TRACK_ORX1_QEC - * [3] | TRACK_ORX2_QEC - * [4] | TRACK_TX1_LOL - * [5] | TRACK_TX2_LOL - * [6] | TRACK_TX1_QEC - * [7] | TRACK_TX2_QEC - * [8] | TRACK_TX1_DPD - * [9] | TRACK_TX2_DPD - * [10] | TRACK_TX1_CLGC - * [11] | TRACK_TX2_CLGC - * [12] | TRACK_TX1_VSWR - * [13] | TRACK_TX2_VSWR - * [16] | TRACK_ORX1_QEC_SNLO - * [17] | TRACK_ORX1_QEC_SNLO - * [18] | TRACK_SRX_QEC - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param enableMask Returned bitmask that shows which tracking cals are enabled - * to run during radioOn state. See mykonosTrackingCalibrations_t enum of tracking cals. - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getEnabledTrackingCals(mykonosDevice_t *device, uint32_t *enableMask) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[4] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getEnabledTrackingCals()\n"); -#endif - - /* Ask ARM to read tracking cal enable bits and place in mailbox buffer memory */ - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CALSCHEDULER, 0, &armData[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - *enableMask = ((uint32_t)(armData[0]) | ((uint32_t)(armData[1]) << 8) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[3]) << 24)); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns the tracking calibration pending and error status. - * - * When in radioOn state, the enabled tracking calibrations will set the pending - * flag when the particular calibration is ready to be run, but has not completed - * yet. For Tx tracking cals to complete, the BBIC must set the ObsRx path to - * the INTERNAL CALS mode. If a tracking calibration had an error, the corresponding - * error flag will be asserted. - * - * pendingCalMask | bit Description - * ----------------|-------------------------------------------------------- - * [0] | Rx1 QEC tracking pending - * [1] | Rx1 QEC tracking error - * [2] | Rx2 QEC tracking pending - * [3] | Rx2 QEC tracking error - * [4] | ORx1 QEC tracking pending - * [5] | ORx1 QEC tracking error - * [6] | ORx2 QEC tracking pending - * [7] | ORx2 QEC tracking error - * [8] | Tx1 LOL tracking pending - * [9] | Tx1 LOL tracking error - * [10] | Tx2 LOL tracking pending - * [11] | Tx2 LOL tracking error - * [12] | Tx1 QEC tracking pending - * [13] | Tx1 QEC tracking error - * [14] | Tx2 QEC tracking pending - * [15] | Tx2 QEC tracking error - * [16] | Tx1 DPD tracking pending - * [17] | Tx1 DPD tracking error - * [18] | Tx2 DPD tracking pending - * [19] | Tx2 DPD tracking error - * [20] | Tx1 CLGC tracking pending - * [21] | Tx1 CLGC tracking error - * [22] | Tx2 CLGC tracking pending - * [23] | Tx2 CLGC tracking error - * [24] | Tx1 VSWR tracking pending - * [25] | Tx1 VSWR tracking error - * [26] | Tx2 VSWR tracking pending - * [27] | Tx2 VSWR tracking error - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param pendingCalMask Bit mask that describes which tracking cals are pending - * or had errors - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM Function parameter pendingCalMask is a NULL pointer - */ -mykonosErr_t MYKONOS_getPendingTrackingCals(mykonosDevice_t *device, uint32_t *pendingCalMask) -{ - uint8_t readData[4] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPendingTrackingCals()\n"); -#endif - - if (pendingCalMask == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM)); - return MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_3, &readData[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_4, &readData[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_5, &readData[2]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_OPCODE_STATE_6, &readData[3]); - *pendingCalMask = ((uint32_t)readData[3] << 24) | ((uint32_t)readData[2] << 16) | ((uint32_t)readData[1] << 8) | ((uint32_t)readData[0]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns the status of the TxLOL external tracking calibration - * - * The Tx LOL external tracking calibration is run during the radioOn state. - * The function can be called to read back the status of the TxLOL external - * calibration including metrics like error codes, percentage of data - * collected for current cal, the performance of the cal and the number of - * times the cal has run and updated the hardware. - * - * \pre Before the function is called, the device must be initialized, the ARM - * loaded, and init cals run. These functions can be called in radioOff or - * radioOn state. - * - * \param device Pointer to the device settings structure - * \param txChannel The channel (Tx1/Tx2) whose status is to be read back - * \param txLolStatus Status of the TxLOL external calibration, as a structure - * of type mykonosTxLolStatus_t is returned to this pointer address - * - * \retval MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM Function parameter mykonosTxLolStatus_t is a NULL pointer - * \retval MYKONOS_ERR_GETTXLOLSTATUS_INV_CH Channel selection not valid - * \retval MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG ARM command error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getTxLolStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxLolStatus_t *txLolStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXLOL_TRACKING, 0}; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - uint32_t timeoutMs = 0; - uint8_t armReadBack[20] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxLolStatus()\n"); -#endif - - if (txLolStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - extData[2] = 0; - break; - case TX2: - extData[2] = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_INV_CH)); - return MYKONOS_ERR_GETTXLOLSTATUS_INV_CH; - } - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Assign to data structure */ - txLolStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); - txLolStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) - | ((uint32_t)armReadBack[4]); - txLolStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) - | ((uint32_t)armReadBack[8]); - txLolStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); - txLolStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) - | ((uint32_t)armReadBack[16]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns the status of the TxQEC tracking calibration - * - * The Tx QEC tracking calibration is run during the radioOn state. - * The function can be called to read back the status of the TxQEC - * calibration including metrics like error codes, percentage of data - * collected for current cal, the performance of the cal and the number of - * times the cal has run and updated the hardware. - * - * \pre Before the function is called, the device must be initialized, the ARM - * loaded, and init cals run. These functions can be called in radioOff or - * radioOn state. - * - * \param device Pointer to the device settings structure - * \param txChannel The channel (Tx1/Tx2) whose status is to be read back - * \param txQecStatus Status of the TxQEC external calibration, as a structure - * of type mykonosTxQecStatus_t is returned to this pointer address - * - * \retval MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM Function parameter txQecStatus is a NULL pointer - * \retval MYKONOS_ERR_GETTXQECSTATUS_INV_CH Channel selection not valid - * \retval MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG ARM command error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getTxQecStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxQecStatus_t *txQecStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_TXQEC_TRACKING, 0}; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - uint32_t timeoutMs = 0; - uint8_t armReadBack[20] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getTxQecStatus()\n"); -#endif - - if (txQecStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - extData[2] = 0; - break; - case TX2: - extData[2] = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_INV_CH)); - return MYKONOS_ERR_GETTXQECSTATUS_INV_CH; - } - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Assign to data structure */ - txQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); - txQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) - | ((uint32_t)armReadBack[4]); - txQecStatus->performanceMetric = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) - | ((uint32_t)armReadBack[8]); - txQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); - txQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) - | ((uint32_t)armReadBack[16]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns the status of the RxQEC tracking calibration - * - * The Rx QEC tracking calibration is run during the radioOn state. - * The function can be called to read back the status of the RxQEC external - * calibration including metrics like error codes, percentage of data - * collected for current cal, the performance of the cal and the number of - * times the cal has run and updated the hardware. - * - * \pre Before the function is called, the device must be initialized, the ARM - * loaded, and init cals run. These functions can be called in radioOff or - * radioOn state. - * - * \param device Pointer to the device settings structure - * \param rxChannel The channel (Rx1/Rx2) whose status is to be read back - * \param rxQecStatus Status of the RxQEC calibration, as a structure - * of type mykonosRxQecStatus_t is returned to this pointer address - * - * \retval MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM Function parameter rxQecStatus is a NULL pointer - * \retval MYKONOS_ERR_GETRXQECSTATUS_INV_CH Channel selection not valid - * \retval MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG ARM command error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRxQecStatus(mykonosDevice_t *device, mykonosRxChannels_t rxChannel, mykonosRxQecStatus_t *rxQecStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_RXQEC_TRACKING, 0}; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - uint32_t timeoutMs = 0; - uint8_t armReadBack[20] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRxQecStatus()\n"); -#endif - - if (rxQecStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM; - } - - switch (rxChannel) - { - case RX1: - extData[2] = 0; - break; - case RX2: - extData[2] = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_INV_CH)); - return MYKONOS_ERR_GETRXQECSTATUS_INV_CH; - } - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Assign to data structure */ - rxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); - rxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) - | ((uint32_t)armReadBack[4]); - rxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) - | ((uint32_t)armReadBack[8]); - rxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) | ((uint32_t)armReadBack[12]); - rxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) - | ((uint32_t)armReadBack[16]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Returns the status of the ORxQEC tracking calibration - * - * The ORx QEC tracking calibration is run during the radioOn state. - * The function can be called to read back the status of the ORxQEC external - * calibration including metrics like error codes, percentage of data - * collected for current cal, the performance of the cal and the number of - * times the cal has run and updated the hardware. - * - * \pre Before the function is called, the device must be initialized, the ARM - * loaded, and init cals run. These functions can be called in radioOff or - * radioOn state. - * - * \param device Pointer to the device settings structure - * \param orxChannel The channel whose status is to be read back - * \param orxQecStatus Status of the ORxQEC external calibration, as a structure - * of type mykonosOrxQecStatus_t is returned to this pointer address - * - * \retval MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM Function parameter orxQecStatus is a NULL pointer - * \retval MYKONOS_ERR_GETORXQECSTATUS_INV_CH Channel selection not valid - * \retval MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG ARM command error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getOrxQecStatus(mykonosDevice_t *device, mykonosObsRxChannels_t orxChannel, mykonosOrxQecStatus_t *orxQecStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING, 0}; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - uint32_t timeoutMs = 0; - uint8_t armReadBack[20] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getOrxQecStatus()\n"); -#endif - - if (orxQecStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM; - } - - switch (orxChannel) - { - case OBS_RX1_TXLO: - case OBS_RX1_SNIFFERLO: - extData[2] = 0; - break; - case OBS_RX2_TXLO: - case OBS_RX2_SNIFFERLO: - extData[2] = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_INV_CH)); - return MYKONOS_ERR_GETORXQECSTATUS_INV_CH; - } - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armReadBack[0], sizeof(armReadBack), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Assign to data structure */ - orxQecStatus->errorCode = (((uint32_t)armReadBack[3]) << 24) | (((uint32_t)armReadBack[2]) << 16) | (((uint32_t)armReadBack[1]) << 8) | ((uint32_t)armReadBack[0]); - orxQecStatus->percentComplete = (((uint32_t)armReadBack[7]) << 24) | (((uint32_t)armReadBack[6]) << 16) | (((uint32_t)armReadBack[5]) << 8) - | ((uint32_t)armReadBack[4]); - orxQecStatus->selfcheckIrrDb = (((uint32_t)armReadBack[11]) << 24) | (((uint32_t)armReadBack[10]) << 16) | (((uint32_t)armReadBack[9]) << 8) - | ((uint32_t)armReadBack[8]); - orxQecStatus->iterCount = (((uint32_t)armReadBack[15]) << 24) | (((uint32_t)armReadBack[14]) << 16) | (((uint32_t)armReadBack[13]) << 8) - | ((uint32_t)armReadBack[12]); - orxQecStatus->updateCount = (((uint32_t)armReadBack[19]) << 24) | (((uint32_t)armReadBack[18]) << 16) | (((uint32_t)armReadBack[17]) << 8) - | ((uint32_t)armReadBack[16]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Selects the Sniffer RF input to use for the observation receiver when in ObsRx pin mode and ORX_MODE = SNIFFER(4) - * - * This function is only valid when using the ObsRx Pin mode. In pin mode, 3 GPIO pins select an Observation Rx source. - * See mykonosObsRxChannels_t enum values less than 7. When the ORX_MODE GPIO pins are set to 4 for Sniffer, Sniffer inputs - * A, B, and C can be chosen by calling this function. This function can be called any time after the ARM is loaded and running. - * It can be called in radioOn or radioOff state. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param snifferChannel Desired channel to set. This channel will be enabled when ORX_MODE = SNIFFER. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR ARM returned an error - */ -mykonosErr_t MYKONOS_setSnifferChannel(mykonosDevice_t *device, mykonosSnifferChannel_t snifferChannel) -{ - uint8_t armData[2] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - - armData[0] = 0x6A; /* SET SRX_SOURCE ARM object ID */ - armData[1] = (uint8_t)snifferChannel; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &armData[0], sizeof(armData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); - retVal = (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); - return (mykonosErr_t)MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Resets the ARM processor and performs initialization - * - * Sets ARM Run = 0, Disables parity checks, sets ARM and SPI reg clock selects, - * resets ARM, and enables ARM SPI register access - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->rx->rxProfile->iqRate_kHz - * - device->deviceClock_kHz - * - device->rx->rxProfile->rfBandwidth_Hz - * - device->tx->txProfile->rfBandwidth_Hz - * - device->rx->rxProfile->rxFirDecimation - * - device->rx->rxProfile->rhb1Decimation - * - device->spiSettings - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_INITARM_INV_VCODIV - * \retval MYKONOS_ERR_INITARM_INV_REGCLK Could not calculate a valid ARM Register clock divider - * \retval MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM Could not calculate a valid ARM clock divider - */ -mykonosErr_t MYKONOS_initArm(mykonosDevice_t *device) -{ - uint8_t regClkSel = 0; - uint8_t armClkSel = 0; - uint32_t hsClkRateDiv4or5_Khz = 0; - uint32_t hb1Clk = 0; - uint32_t vcoDivTimes10 = 1; - uint8_t adcDiv = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_initArm()\n"); -#endif - - /* Finish init - this is part of init that must run after Multi Chip Sync */ - retVal = MYKONOS_initSubRegisterTables(device); - if (retVal != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - switch (device->clocks->clkPllVcoDiv) - { - case VCODIV_1: - vcoDivTimes10 = 10; - break; - case VCODIV_1p5: - vcoDivTimes10 = 15; - break; - case VCODIV_2: - vcoDivTimes10 = 20; - break; - case VCODIV_3: - vcoDivTimes10 = 30; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_VCODIV, - getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_VCODIV)); - return MYKONOS_ERR_INITARM_INV_VCODIV; - } - } - - hsClkRateDiv4or5_Khz = device->clocks->clkPllVcoFreq_kHz * 10 / vcoDivTimes10 / 20; - - /* If ADC divider is set, divide hsClkRateDiv4or5_kHz by 2 (ADC divider) */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_CLOCK_CONTROL_1, &adcDiv, 0x01, 0); - hb1Clk = (adcDiv == 1) ? (hsClkRateDiv4or5_Khz >> 1) : (hsClkRateDiv4or5_Khz); - - /* the ARM clock should not exceed 250 Mhz */ - if (hb1Clk <= 250000) - { - armClkSel = 0x00; - } - else if (hb1Clk > 250000 && hb1Clk <= 500000) - { - armClkSel = 0x02; - } - else if (hb1Clk > 500000 && hb1Clk <= 1000000) - { - armClkSel = 0x04; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM)); - return MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM; - } - - /* the SPI read reg clock must be equal or less than 100MHz and the SPI write reg clock must be less equal or less than 200 Mhz*/ - if (hb1Clk <= 100000) - { - regClkSel = 0x00; - } - else if (hb1Clk > 100000 && hb1Clk <= 200000) - { - regClkSel = 0x04; - } - else if (hb1Clk > 200000 && hb1Clk <= 400000) - { - regClkSel = 0x09; - } - else if (hb1Clk > 400000 && hb1Clk <= 800000) - { - regClkSel = 0x0E; - } - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INITARM_INV_REGCLK, getMykonosErrorMessage(MYKONOS_ERR_INITARM_INV_REGCLK)); - return MYKONOS_ERR_INITARM_INV_REGCLK; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=0 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel |= 0x41); /* setting the ARM clock rate, resetting the PC, and enabling the ARM clock */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CLK_CTL, armClkSel &= ~0x40); /* maintaining the ARM clock rate, disabling the PC reset, and maintaining ARM clock enable */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BRIDGE_CLK_CTL, regClkSel); /* setting the SPI read and write clock rates */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AHB_SPI_BRIDGE, 0x13); /* blockout_window_size[4:1] = 9, ahb_spi_bridge_enable[0] = 1 */ - - retVal = MYKONOS_writeArmProfile(device); - if (retVal != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - retVal = MYKONOS_loadAdcProfiles(device); - if (retVal != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Loads binary byte array into ARM program memory - * - * This function assumes the ARM auto increment bit is set in 0x0D00[2]. Valid memory - * addresses are: Program Memory (0x01000000 - 0x01017FFF) - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file) - * \param count is the number of bytes in the byte array - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_LOADBIN_NULL_PARAM Function parameter binary has a NULL pointer - * \retval MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT Count parameter must be 98304 bytes - */ -mykonosErr_t MYKONOS_loadArmFromBinary(mykonosDevice_t *device, uint8_t *binary, uint32_t count) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t stackPtr[4] = {0}; - uint8_t bootAddr[4] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmFromBinary()\n"); -#endif - - if (binary == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_NULL_PARAM)); - return MYKONOS_ERR_LOADBIN_NULL_PARAM; - } - - if (count != 98304) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT, - getMykonosErrorMessage(MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT)); - return MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT; - } - else - { - /* extraction of stack pointer and boot address from top of array */ - stackPtr[0] = binary[0]; - stackPtr[1] = binary[1]; - stackPtr[2] = binary[2]; - stackPtr[3] = binary[3]; - - bootAddr[0] = binary[4]; - bootAddr[1] = binary[5]; - bootAddr[2] = binary[6]; - bootAddr[3] = binary[7]; - - /* writing binary data to ARM memory */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR, &binary[0], count); - } - - if (retVal != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - else - { - /* writing the stack pointer address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */ - - /* writing the boot address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */ - - /* setting the ARM run bit */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D); /* arm_debug_enable[7]=1, mem_hresp_mask[3]=1, auto_incr[2]=1, arm_m3_run[0]=1 */ - } - - /* verifying ARM checksum */ - if ((retVal = MYKONOS_verifyArmChecksum(device)) != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - /* verifying ARM state is in MYKONOS_ARM_READY state, otherwise return error */ - if ((retVal = MYKONOS_checkArmState(device, MYK_ARM_READY)) != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - /* Setup ARM GPIO pins and program ARMs radio control structure */ - if ((retVal = (mykonosErr_t)MYKONOS_setArmGpioPins(device)) != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - if ((retVal = MYKONOS_setRadioControlPinMode(device)) != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - /* Set the default ObsRx Path source for when the device moves to RadioOn */ - if ((retVal = MYKONOS_setDefaultObsRxPath(device, device->obsRx->defaultObsRxChannel)) != MYKONOS_ERR_OK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, retVal, getMykonosErrorMessage(retVal)); - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Loads binary byte array into ARM program memory. This API function allows user to load the ARM concurrently. - * This is specially to reduce the system initialization time. - * - * \pre MYKONOS_initArm() function must be called before calling this API. - * - * \post after calling this function the user must verify: - * Arm Checksum using MYKONOS_verifyArmChecksum(mykonosDevice_t *device) - * verify ARM state is in MYKONOS_ARM_READY state using MYKONOS_checkArmState(device, MYK_ARM_READY); - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param binary is a byte array containing ARM program memory data bytes (directly from .bin file) - * \param count is the number of bytes in the byte array - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_LOADARMCON_NULL_PARAM Function parameter binary has a NULL pointer - * \retval MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT Count parameter must be 98304 bytes - * \retval MYKONOS_ERR_ARM_INV_ADDR_PARM Invalid memory address - */ -mykonosErr_t MYKONOS_loadArmConcurrent(mykonosDevice_t *device, uint8_t *binary, uint32_t count) -{ - uint8_t stackPtr[4] = {0}; - uint8_t bootAddr[4] = {0}; - uint32_t i; - uint32_t address = MYKONOS_ADDR_ARM_START_PROG_ADDR; - -#if MYK_ENABLE_SPIWRITEARRAY == 1 - uint32_t addrIndex = 0; - uint32_t dataIndex = 0; - uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE; - uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; -#endif - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadArmConcurrent()\n"); -#endif - - if (binary == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_NULL_PARAM, getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_NULL_PARAM)); - return MYKONOS_ERR_LOADARMCON_NULL_PARAM; - } - - if (count != 98304) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT, - getMykonosErrorMessage(MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT)); - return MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT; - } - else - { - /* extraction of stack pointer and boot address from top of array */ - stackPtr[0] = binary[0]; - stackPtr[1] = binary[1]; - stackPtr[2] = binary[2]; - stackPtr[3] = binary[3]; - - bootAddr[0] = binary[4]; - bootAddr[1] = binary[5]; - bootAddr[2] = binary[6]; - bootAddr[3] = binary[7]; - - /* set auto increment address bit */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8C); - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10)); - - /* start write at correct byte offset */ - /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */ - /* with address auto increment set, after x407 is written, the address will automatically increment */ - -#if (MYK_ENABLE_SPIWRITEARRAY == 0) - - for (i = 0; i < byteCount; i++) - { - CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]); - } - -#elif (MYK_ENABLE_SPIWRITEARRAY == 1) - - addrIndex = 0; - dataIndex = 0; - for (i = 0; i < count; i++) - { - addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)); - - if (addrIndex == spiBufferSize) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex); - dataIndex = dataIndex + addrIndex; - addrIndex = 0; - } - } - - if (addrIndex > 0) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &binary[dataIndex], addrIndex); - } - -#endif - - /* writing the stack pointer address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0, stackPtr[0]); /* stack pointer [7:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1, stackPtr[1]); /* stack pointer [15:8] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2, stackPtr[2]); /* stack pointer [23:16] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3, stackPtr[3]); /* stack pointer [31:24] */ - - /* writing the boot address */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0, bootAddr[0]); /* boot address [7:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1, bootAddr[1]); /* boot address [15:8] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2, bootAddr[2]); /* boot address [23:16] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3, bootAddr[3]); /* boot address [31:24] */ - - /* setting the ARM run bit */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x8D); - - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Verifies the ARM checksum value - * - * The checksum which is written into the .hex file is verified with the calculated checksum - * in the Mykonos ARM after the hex file has been loaded - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device) -{ - uint32_t buildTimeChecksum = 0x00000000; - uint32_t calculatedChecksum = 0x00000000; - uint8_t buildData[4] = {0}; - uint8_t calcData[4] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - - const uint8_t CHECKSUM_BYTES = 0x4; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_verifyArmChecksum()\n"); -#endif - - /* disabling auto increment and reading four (4) bytes at ARM checksum memory location */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_BUILD_CHKSUM_ADDR, buildData, CHECKSUM_BYTES, 0); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - /* determining build time checksum */ - buildTimeChecksum = (((uint32_t)buildData[3] << 24) | ((uint32_t)buildData[2] << 16) | ((uint32_t)buildData[1] << 8) | (uint32_t)buildData[0]); - - /* using 200 msec timeout for exit out of while loop [maximum checksum calculation time = 5 ms] */ - CMB_setTimeout_ms(200); - - /* determining calculated checksum */ - do - { - if ((retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR, calcData, CHECKSUM_BYTES, 0)) != MYKONOS_ERR_OK) - { - return retVal; - } - calculatedChecksum = (((uint32_t)calcData[3] << 24) | ((uint32_t)calcData[2] << 16) | ((uint32_t)calcData[1] << 8) | (uint32_t)calcData[0]); - } while ((!calculatedChecksum) && (!CMB_hasTimeoutExpired())); - - /* performing consistency check */ - if (buildTimeChecksum == calculatedChecksum) - { - return MYKONOS_ERR_OK; - } - else - { - return MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM; - } -} - -/** - * \brief Verifies the ARM status once it is start running - * - * Wait for ARM to go into radio state, if takes longer there is and ARM error - * get error in Application layer calling MYKONOS_getRadioState() - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param armStateCheck if the ARM is not in this state it will return an error, - * - * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM system problem has been detected. - * \retval MYKONOS_ERR_ARMSTATE_CAL_ERROR ARM has detected an error in the tracking calibrations. - * \retval MYKONOS_ERR_ARMSTATE_EXCEPTION ARM has detected an illegal profile. - * \retval MYKONOS_ERR_WAITARMCSTATE_TIMEOUT Timeout occurred in check ARM state. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t armStateCheck) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t armStatus = 0x00; - uint32_t armStatusMapped = 0x00; - uint32_t timeoutMs = 500; /* 500ms timeOut */ - uint8_t endCheck = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_checkArmState()\n"); -#endif - - CMB_setTimeout_ms(timeoutMs); - - do - { - if ((retVal = MYKONOS_getRadioState(device, &armStatus)) != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Mapping of the armStatus bit to the enum value. */ - switch(armStatus) - { - case 0: - armStatusMapped = (uint32_t)MYK_ARM_POWERUP; - break; - case 1: - armStatusMapped = (uint32_t)MYK_ARM_READY; - break; - case 2: - armStatusMapped = (uint32_t)MYK_ARM_IDLE; - break; - case 3: - armStatusMapped = (uint32_t)MYK_ARM_RADIO_ON; - break; - case 4: - armStatusMapped = (uint32_t)MYK_ARM_PROFILE_ERROR; - break; - default: - armStatusMapped = armStatus; - break; - } - - if (armStateCheck && armStatusMapped) - { - retVal = MYKONOS_ERR_OK; - break; - } - - if (CMB_hasTimeoutExpired()) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WAITARMCSTATE_TIMEOUT, - getMykonosErrorMessage(MYKONOS_ERR_WAITARMCSTATE_TIMEOUT)); - retVal = MYKONOS_ERR_WAITARMCSTATE_TIMEOUT; - break; - } - - switch (armStatusMapped) - { - /* this cases are not ARM errors */ - case MYK_ARM_POWERUP: - case MYK_ARM_READY: - case MYK_ARM_IDLE: - case MYK_ARM_RADIO_ON: - break; - - case MYK_ARM_PROFILE_ERROR: - /* return error directly */ - retVal = MYKONOS_ERR_ARMSTATE_PROFILE_ERROR; - endCheck = 1; - break; - - case MYK_ARM_CAL_ERROR: - /* return error directly */ - retVal = MYKONOS_ERR_ARMSTATE_CAL_ERROR; - endCheck = 1; - break; - - case MYK_ARM_EXCEPTION: - /* return error directly */ - retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION; - endCheck = 1; - break; - - case (uint32_t)MYK_ARM_EXCEPTION | (uint32_t)MYK_ARM_PROFILE_ERROR: - /* return error directly */ - retVal = MYKONOS_ERR_ARMSTATE_EXCEPTION; - endCheck = 1; - break; - - default: - endCheck = 0; - break; - } - - } while (!endCheck); - - return retVal; -} - -/** - * \brief Reads back the version of the ARM binary loaded into the Mykonos ARM memory - * - * This function reads the ARM memory to read back the major.minor.releaseCandidate - * version for the ARM binary loaded into ARM memory. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param majorVer The Major version is returned in this parameter - * \param minorVer The Minor version is returned in this parameter - * \param rcVer The release candidate version (build number) is returned in this parameter - * \param buildType The Type of the build [Debug / Test_Object / Release] - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETARMVER_NULL_PARM One of the function parameters has a NULL pointer - */ -mykonosErr_t MYKONOS_getArmVersion(mykonosDevice_t *device, uint8_t *majorVer, uint8_t *minorVer, uint8_t *rcVer, mykonosBuild_t *buildType) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t ver[5] = {0}; - uint32_t fullVersion = 0; - uint8_t validBuilds = 0x05; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getArmVersion()\n"); -#endif - - if ((majorVer == NULL) || (minorVer == NULL) || (rcVer == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETARMVER_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_GETARMVER_NULL_PARM)); - return MYKONOS_ERR_GETARMVER_NULL_PARM; - } - - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_VERSION, &ver[0], sizeof(ver), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - fullVersion = ((uint32_t)(ver[0]) | (uint32_t)((uint32_t)(ver[1]) << 8) | (uint32_t)((uint32_t)(ver[2]) << 16) | (uint32_t)((uint32_t)(ver[3]) << 24)); - *rcVer = (uint8_t)(fullVersion % 100); - *minorVer = (uint8_t)((fullVersion / 100) % 100); - *majorVer = (uint8_t)(fullVersion / 10000); - - switch (ver[4] & validBuilds) - { - case MYK_BUILD_DEBUG: - *buildType = MYK_BUILD_DEBUG; - break; - case MYK_BUILD_TEST_OBJECT: - *buildType = MYK_BUILD_TEST_OBJECT; - break; - default: - *buildType = MYK_BUILD_RELEASE; - break; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function will configure DPD settings - * - * A DPD-enabled transceiver is required for DPD to be enabled. The DPD has several user - * adjustable settings that can be configured before running the runInitCals - * with the calMask set for the DPD init cal. Call this function with desired - * settings set before running the DPD init cal or enabling DPD tracking. - * - * This function can be called in either Radio On or Off state. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->dpdConfig (All members) - * - * - * \retval MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV ERROR: to use these features, a valid Tx and ORx profile must exist in the device data structure - * \retval MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT ERROR: device->tx->dpdConfig is a NULL pointer - * \retval MYKONOS_ERR_CFGDPD_INV_DPDDAMPING ERROR: damping parameter is out of range - * \retval MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES ERROR: samples parameter is out of range - * \retval MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS ERROR: numWeights parameter is out of range (0-3) - * \retval MYKONOS_ERR_CFGDPD_INV_MODELVERSION ERROR: modelVersion parameter is out of range (0-3) - * \retval MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH ERROR: outlierThreshold parameter is out of range - * \retval MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY ERROR: additionalDelayOffset parameter is out of range - * \retval MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL ERROR: pathDelayPnSeqLevel parameter is out of range - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_configDpd(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[6] = {0}; - uint8_t byteOffset = 0; - uint16_t negPnLevel = 0; - uint8_t highPowerModelUpdate = 0; - uint8_t robustModeling = 0; - uint32_t radioStatus = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configDpd()\n"); -#endif - - /* DPD requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV)); - return MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV; - } - - if (device->tx->dpdConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT)); - return MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT; - } - - /* check DPD damping and samples parameters */ - if (device->tx->dpdConfig->damping > 15) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDDAMPING, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDDAMPING)); - return MYKONOS_ERR_CFGDPD_INV_DPDDAMPING; - } - - if ((device->tx->dpdConfig->samples < 64) || (device->tx->dpdConfig->samples > 32768)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES)); - return MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES; - } - - if (device->tx->dpdConfig->numWeights > 3) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS)); - return MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS; - } - - if (device->tx->dpdConfig->modelVersion > 3) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_MODELVERSION, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_MODELVERSION)); - return MYKONOS_ERR_CFGDPD_INV_MODELVERSION; - } - - highPowerModelUpdate = (device->tx->dpdConfig->highPowerModelUpdate > 0) ? 1 : 0; - robustModeling = (device->tx->dpdConfig->robustModeling > 0) ? 1 : 0; - - armFieldValue[0] = (uint8_t)(((device->tx->dpdConfig->numWeights & 3) << 4) | (device->tx->dpdConfig->damping & 0xF)); - armFieldValue[1] = (uint8_t)((robustModeling << 3) | (highPowerModelUpdate << 2) | (device->tx->dpdConfig->modelVersion & 3)); - armFieldValue[2] = (device->tx->dpdConfig->samples & 0xFF); - armFieldValue[3] = ((device->tx->dpdConfig->samples >> 8) & 0xFF); - byteOffset = 0; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set DPD outlier threshold parameter */ - if ((device->tx->dpdConfig->outlierThreshold < 1) || (device->tx->dpdConfig->outlierThreshold > 8192)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH)); - return MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH; - } - - armFieldValue[0] = (device->tx->dpdConfig->outlierThreshold & 0xFF); - armFieldValue[1] = ((device->tx->dpdConfig->outlierThreshold >> 8) & 0xFF); - byteOffset = 10; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set DPD Model Prior Weight parameter */ - if (device->tx->dpdConfig->modelPriorWeight > 32) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT)); - return MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT; - } - armFieldValue[0] = (device->tx->dpdConfig->modelPriorWeight & 0xFF); - armFieldValue[1] = 0; - byteOffset = 12; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* no need to verify weights min/max as all int8 values are valid */ - armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->weights[0].real); - armFieldValue[1] = (uint8_t)(device->tx->dpdConfig->weights[0].imag); - armFieldValue[2] = (uint8_t)(device->tx->dpdConfig->weights[1].real); - armFieldValue[3] = (uint8_t)(device->tx->dpdConfig->weights[1].imag); - armFieldValue[4] = (uint8_t)(device->tx->dpdConfig->weights[2].real); - armFieldValue[5] = (uint8_t)(device->tx->dpdConfig->weights[2].imag); - - byteOffset = 14; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], 6); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set DPD additional delay offset parameter */ - if ((device->tx->dpdConfig->additionalDelayOffset < -64) || (device->tx->dpdConfig->additionalDelayOffset > 64)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY)); - return MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY; - } - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Radio state check */ - if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY)) - { - armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->additionalDelayOffset & 0xFF); - armFieldValue[1] = (uint8_t)(((uint16_t)device->tx->dpdConfig->additionalDelayOffset >> 8) & 0xFF); - byteOffset = 2; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if ((device->tx->dpdConfig->pathDelayPnSeqLevel < 1) || (device->tx->dpdConfig->pathDelayPnSeqLevel > 8191)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL, - getMykonosErrorMessage(MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL)); - return MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL; - } - - /* Set Path Delay PN sequence amplitude - positive and negative */ - armFieldValue[0] = (uint8_t)(device->tx->dpdConfig->pathDelayPnSeqLevel & 0xFF); - armFieldValue[1] = (uint8_t)((device->tx->dpdConfig->pathDelayPnSeqLevel >> 8) & 0xFF); - - negPnLevel = ((~device->tx->dpdConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ - armFieldValue[2] = (uint8_t)(negPnLevel & 0xFF); - armFieldValue[3] = (uint8_t)(((negPnLevel) >> 8) & 0xFF); - byteOffset = 10; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armFieldValue[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - else - { - /* record warning about not updated members */ - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, - getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE)); - } - - return MYKONOS_ERR_OK; -} - -/* \brief Reads the DPD config structure from ARM memory - * - * This function reads the DPD structure - * from ARM memory and returns in the device->tx->dpdConfig structure. - * - * A DPD-enabled transceiver is required for DPD to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->dpdConfig (All members) - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for DPD functions - * \retval MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT Error: NULL pointer to device->tx->dpdConfig structure - */ -mykonosErr_t MYKONOS_getDpdConfig(mykonosDevice_t *device) -{ - uint16_t byteOffset = 0; - uint8_t armMem[20] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdConfig()\n"); -#endif - - /* DPD requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV)); - return MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV; - } - - if (device->tx->dpdConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT)); - return MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT; - } - - byteOffset = 0; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armMem[0], 20); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->dpdConfig->damping = (armMem[0] & 0x0F); - device->tx->dpdConfig->numWeights = ((armMem[0] >> 4) & 0x03); - - device->tx->dpdConfig->modelVersion = (armMem[1] & 0x03); - device->tx->dpdConfig->highPowerModelUpdate = ((armMem[1] >> 2) & 0x01); - device->tx->dpdConfig->robustModeling = 0; - device->tx->dpdConfig->samples = ((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2]); - - device->tx->dpdConfig->outlierThreshold = ((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10]); - device->tx->dpdConfig->modelPriorWeight = armMem[12]; - device->tx->dpdConfig->weights[0].real = (int8_t)(armMem[14]); - device->tx->dpdConfig->weights[0].imag = (int8_t)(armMem[15]); - device->tx->dpdConfig->weights[1].real = (int8_t)(armMem[16]); - device->tx->dpdConfig->weights[1].imag = (int8_t)(armMem[17]); - device->tx->dpdConfig->weights[2].real = (int8_t)(armMem[18]); - device->tx->dpdConfig->weights[2].imag = (int8_t)(armMem[19]); - - byteOffset = 2; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->dpdConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - byteOffset = 10; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->dpdConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function reads the DPD calibration status from the Mykonos ARM processor. - * - * The dpdStatus is read back from the ARM processor and returned in the function - * parameter dpdStatus. - * - * A DPD-enabled transceiver is required for this feature to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM values: TX1 or TX2 only) - * \param dpdStatus Pointer to a structure to return the status information to - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETDPDSTATUS_NULLPARAM dpdStatus function parameter is a NULL pointer - * \retval MYKONOS_ERR_GETDPDSTATUS_INV_CH txChannel parameter is a non-supported value. - * \retval MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command - */ -mykonosErr_t MYKONOS_getDpdStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdStatus_t *dpdStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0}; - uint8_t armData[64] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint8_t channelSelect = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdStatus()\n"); -#endif - - if (dpdStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETDPDSTATUS_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - channelSelect = 0; - break; - case TX2: - channelSelect = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_INV_CH)); - return MYKONOS_ERR_GETDPDSTATUS_INV_CH; - } - } - - extData[2] = channelSelect; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - dpdStatus->dpdErrorStatus = ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); /* Only lower 16 bits */ - dpdStatus->dpdTrackCount = ((uint32_t)(armData[11]) << 24) | ((uint32_t)(armData[10]) << 16) | ((uint32_t)(armData[9]) << 8) | (uint32_t)(armData[8]); - dpdStatus->dpdModelErrorPercent = ((uint32_t)(armData[15]) << 24) | ((uint32_t)(armData[14]) << 16) | ((uint32_t)(armData[13]) << 8) | (uint32_t)(armData[12]); - dpdStatus->dpdExtPathDelay = ((uint32_t)(armData[26]) * 16) + (uint32_t)(armData[24]); - dpdStatus->dpdMaxAdaptationCurrent = ((uint16_t)(armData[41]) << 8) + (uint16_t)(armData[40]); - dpdStatus->dpdMaxAdaptation = ((uint16_t)(armData[43]) << 8) + (uint16_t)(armData[42]); - dpdStatus->dpdIterCount = ((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This private helper function called during RadioOff, will allow DPD tracking to be scheduled - * by the ARM when back in the RadioOn state. - * - * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask - * and this setting are both set, then the ARM will schedule DPD tracking to occur - * in the radioOn ARM state. - * - * A DPD-enabled transceiver is required for DPD to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->tx->dpdConfig - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param tx1Enable 0=disable DPD Tx1 tracking, 1= enable DPD Tx1 tracking - * \param tx2Enable 0=disable DPD Tx2 tracking, 1= enable DPD Tx2 tracking - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() - */ -static mykonosErr_t enableDpdTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable) -{ - uint32_t radioStatus = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t enableBit[4] = {0}; - uint8_t byteOffset = 20; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableDpdTracking()\n"); -#endif - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* throw error if not in radioOff/IDLE state */ - if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR, - getMykonosErrorMessage(MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR)); - return MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR; - } - - enableBit[0] = (tx1Enable > 0) ? 1 : 0; - enableBit[1] = 0; - enableBit[2] = (tx2Enable > 0) ? 1 : 0; - enableBit[3] = 0; - - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &enableBit[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function will allow loading of the DPD model file. - * - * This function writes a copy of the user's DPD model to ARM memory and instructs the ARM to install that DPD model - * into hardware. Note that initializing the device will over write DPD model data. Note that the DPD model being - * restored must match the PA for which it is configured. Restoring a DPD model to a different PA than for which it - * is configured will not yield the desired performance. The user is responsible to insure the DPD model matches the - * PA configuration. - * - * \param device Structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired transmit channel to which to write the DPD model file (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2) - * \param modelDataBuffer Pointer to the user buffer containing the history/model data to be loaded to a txChannel - * Valid sizes: 182 bytes for a single model load to either TX1 or TX2. - * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes - * and TX2 model data will occupy the second 182 bytes. - * \param modelNumberBytes Total buffer size of the user history/model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and - * 364 bytes for TX1_TX2. - * - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE User suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364 - * \retval MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL User supplied txChannel does not match TX1 or TX2 or TX1_TX2 - * \retval MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG ARM returned error for Set ARM Command - */ -mykonosErr_t MYKONOS_restoreDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes) -{ - uint32_t radioStatus = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[4] = {0}; - uint32_t armBufferAddr = 0; - uint8_t *bufferPtr = 0; - uint8_t extendedData[4] = {0}; - uint8_t cmdStatusByte = 0; - - const uint8_t RESTORE = 0x08; - const uint32_t timeoutMs = 1000; - const uint32_t MODEL_SIZE = 182; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_restoreDpdModel()\n"); -#endif - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if (txChannel == TX1) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != MODEL_SIZE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; - } - - /* retrieve the arm TX1 model buffer address */ - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* write the TX1 model */ - bufferPtr = modelDataBuffer; - retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */ - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - }/*end TX1 */ - - else if (txChannel == TX2) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != MODEL_SIZE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; - } - - /* retrieve the arm TX2 model buffer address */ - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* write the TX2 model */ - bufferPtr = modelDataBuffer; - retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - }/* end TX2 */ - - /* check for dual txChannel type */ - else if (txChannel == TX1_TX2) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != (2 * MODEL_SIZE)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE; - } - - /* retrieve the arm TX1 model buffer address */ - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* write the TX1 model */ - bufferPtr = modelDataBuffer; - retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX1 model */ - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - bufferPtr += MODEL_SIZE; - - /* retrieve the arm TX2 model buffer address */ - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR), &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* write the TX2 model */ - retVal = MYKONOS_writeArmMem(device, armBufferAddr, bufferPtr, MODEL_SIZE); /* write TX2 model */ - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - }/*end two txChannel model data load */ - - /* invalid txChannel for this API command */ - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL)); - return MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL; - }/* end invalid txChannel check */ - - /* instruct ARM to load DPD Model */ - extendedData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS; - extendedData[1] = MYKONOS_ARM_DPD_RESET; - extendedData[2] = (uint8_t)txChannel + RESTORE; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extendedData[0], sizeof(extendedData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* wait max of 1sec for command to complete */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG)); - return MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG; - } - return retVal; - } - - return MYKONOS_ERR_OK; -} - - -/** - * \brief This function called during RadioOff, will allow retrieval of the DPD model file. - * - * This function reads a copy of the DPD model from ARM memory to user memory specified by the modelDataBuffer pointer. - * The user must provide the correct buffer size with the modelNumberBytes argument. - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to read back DPD status for (Valid ENUM type mykonosTxChannels_t: TX1 or TX2 or TX1_TX2) - * \param modelDataBuffer a pointer to the user buffer where the model data is to be written. - * Valid sizes: 182 bytes for a single model load to either TX1 or TX2. - * 364 bytes for a dual model load to both TX1_TX2, where the TX1 model data will occupy the first 182 bytes - * and TX2 model data will occupy the second 182 bytes. - * \param modelNumberBytes is the total buffer size of the user model data buffer. Allowed sizes are 182 bytes for TX1 or TX2 and - * 364 bytes for TX1_TX2. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SAVEDPDMODEL_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() - * \retval MYKONOS_ERR_SAVEDPDMODEL_BUFFERSIZE_ERROR suppled modelNumberBytes size is incorrect. TX1 or TX2 = 182, TX1_TX2 = 364 - * \retval MYKONOS_ERR_SAVEDPDMODEL_INVALID_TXCHANNEL_ERROR supplied txChannel does not match TX1 or TX2 or TX1_TX2 - */ -mykonosErr_t MYKONOS_saveDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes) -{ - uint32_t radioStatus = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t modelSize = 0; - uint8_t armData[4] = {0}; - uint32_t armBufferAddr = 0; - - const uint32_t MODEL_SIZE = 182; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_saveDpdModel()\n"); -#endif - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* throw error if not in radioOff/IDLE state */ - if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_ARMSTATE, getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_ARMSTATE)); /* radio not off or initialized */ - return MYKONOS_ERR_SAVDPDMOD_ARMSTATE; - } - - if (txChannel == TX1) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != MODEL_SIZE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ - } - - /* retrieve the arm TX1 model buffer address */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* read the TX1 model */ - retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - modelDataBuffer += modelSize; - }/*end TX1 */ - - else if (txChannel == TX2) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != MODEL_SIZE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ - } - - /* retrieve the arm TX2 model buffer address */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* read the TX2 model */ - retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - }/*end TX2 */ - - /* check for dual txChannel type */ - else if (txChannel == TX1_TX2) - { - /* check for single valid provided buffer size */ - if (modelNumberBytes != (2 * MODEL_SIZE)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, - getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE)); - return MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE; /* wrong buffer size */ - } - - /* retrieve the arm TX1 model buffer address */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* read the TX1 model */ - retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - modelDataBuffer += MODEL_SIZE; - - /* retrieve the arm TX2 model buffer address */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_PROG_ADDR + MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR, &armData[0], 4, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - armBufferAddr = (((uint32_t)armData[0]) | (((uint32_t)armData[1]) << 8) | (((uint32_t)armData[2]) << 16) | (((uint32_t)armData[3]) << 24)); - - /* read the TX2 model */ - retVal = MYKONOS_readArmMem(device, armBufferAddr, modelDataBuffer, MODEL_SIZE, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - }/* end TX1_TX2 txChannel */ - - /* invalid txChannel for this API command */ - else - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL)); - return MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL; /* invalid txChannel */ - }/* end invalid txChannel check */ - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function sets the state of the DPD actuator. - * - * This function can be called in either Radio On or Off state. - * - * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to set the Actuator State (Valid ENUM values: TX1, TX2 or TX1_TX2) - * \param actState Desired actuator state for the DPD, valid states are 0-disable and 1-enable - * - * \retval MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2) - * \retval MYKONOS_ERR_SETDPDACT_INV_STATE ERROR: Invalid Actuator state, valid states are 0-disable and 1-enable. - * \retval MYKONOS_ERR_SETDPDACT_ARMERRFLAG ERROR: ARM command flag error set - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setDpdActState(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t actState) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; - uint8_t extData[3] = {0}; - uint8_t actuatorSet = 0x00; - uint8_t cmdStatusByte = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActState()\n"); -#endif - - switch (txChannel) - { - case TX1: - break; - case TX2: - break; - case TX1_TX2: - break; - - default: - /* this function allow single channel gain only */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL)); - return MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL; - } - switch (actState) - { - case 0: - actuatorSet = DISABLE_DPD_ACTUATOR; - break; - case 1: - actuatorSet = ENABLE_DPD_ACTUATOR; - break; - - default: - /* this function allow single channel gain only */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_STATE, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_STATE)); - return MYKONOS_ERR_SETDPDACT_INV_STATE; - } - - extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL; - extData[1] = actuatorSet; - extData[2] = (uint8_t)txChannel; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG)); - return MYKONOS_ERR_SETDPDACT_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_ARMERRFLAG)); - return MYKONOS_ERR_SETDPDACT_ARMERRFLAG; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function resets the DPD model. - * - * This function allows the user to reset the DPD actuator and prior model in radioOn or radioOff mode. - * The reset can restore prior model if the parameter passed is set to 2: this resets DPD first and then restores the previously loaded - * model into ARM memory for use with subsequent iterations of DPD. - * - * If reset is 1 then the reset function just reset the DPD actuator and not use any model. - * - * \pre A DPD-enabled transceiver is required for DPD to be enabled. DPD init cal has been run and DPD tracking enable. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to be reseted (Valid ENUM values: TX1, TX2 or TX1_TX2) - * \param reset is the required reset condition that is needed, the available options are given by the enum - * ::mykonosDpdResetMode_t - * - * \retval MYKONOS_ERR_RESETDPD_INV_TXCHANNEL: Tx channel is not valid (Valid ENUM values: TX1, TX2 or TX1_TX2) - * \retval MYKONOS_ERR_RESETDPD_WRONG_PARAM ERROR: reset parameter is not valid (Valid values: MYK_DPD_RESET_FULL, MYK_DPD_RESET_PRIOR or MYK_DPD_RESET_CORRELATOR) - * \retval MYKONOS_ERR_RESETDPD_ARMERRFLAG ERROR: ARM command flag error set - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_resetDpd(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdResetMode_t reset) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; - uint8_t extData[3] = {0}; - uint8_t cmdStatusByte = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetDpd()\n"); -#endif - - switch (txChannel) - { - case TX1: - break; - case TX2: - break; - case TX1_TX2: - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_INV_TXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_INV_TXCHANNEL)); - return MYKONOS_ERR_RESETDPD_INV_TXCHANNEL; - } - - if ((reset >= MYK_DPD_RESET_END) || (reset == MYK_DPD_NO_ACTION)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_WRONG_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_WRONG_PARAM)); - return MYKONOS_ERR_RESETDPD_WRONG_PARAM; - } - - /* instruct ARM to reset DPD Model */ - extData[0] = MYKONOS_ARM_OBJECTID_GS_TRACKCALS; - extData[1] = MYKONOS_ARM_DPD_RESET; - extData[2] = (uint8_t)(reset << 2) + (uint8_t)txChannel; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* wait max of 1sec for command to complete */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESETDPD_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_RESETDPD_ARMERRFLAG)); - return MYKONOS_ERR_RESETDPD_ARMERRFLAG; - } - return retVal; - } - - return MYKONOS_ERR_OK; -} -/** - * \brief This function will configure CLGC settings - * - * A DPD-enabled transceiver is required for CLGC to be enabled. The CLGC has several user - * adjustable settings that can be configured before running the runInitCals - * with the calMask set for the CLGC init cal. Call this function with desired - * settings set before running the CLGC init cal or enabling CLGC tracking. - * - * This function can be called in either Radio On or Off state. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->clgcConfig (All members) - * - * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the CLGC feature - * \retval MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig - * \retval MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN ERROR: CLGC tx1DesiredGain or tx2DesiredGain parameter is out of range - * \retval MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT ERROR: CLGC tx1AttenLimit or tx2AttenLimit parameter is out of range - * \retval MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO ERROR: clgcControlRatio parameter is out of range - * \retval MYKONOS_ERR_CFGCLGC_INV_THRESHOLD Error: tx1RelThreshold or tx2RelThreshold parameter is out of range - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_configClgc(mykonosDevice_t *device) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[4] = {0}; - uint8_t byteOffset = 0; - uint16_t negPnLevel = 0; - uint32_t radioStatus = 0x00; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configClgc()\n"); -#endif - - /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV)); - return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV; - } - - if (device->tx->clgcConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT)); - return MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT; - } - - /* set CLGC desired gain parameter */ - if ((device->tx->clgcConfig->tx1DesiredGain < -10000) || (device->tx->clgcConfig->tx1DesiredGain > 10000) || (device->tx->clgcConfig->tx2DesiredGain < -10000) - || (device->tx->clgcConfig->tx2DesiredGain > 10000)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN)); - return MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN; - } - - armFieldValue[0] = (device->tx->clgcConfig->tx1DesiredGain & 0xFF); - armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->tx1DesiredGain >> 8) & 0xFF); - armFieldValue[2] = (device->tx->clgcConfig->tx2DesiredGain & 0xFF); - armFieldValue[3] = (((uint16_t)device->tx->clgcConfig->tx2DesiredGain >> 8) & 0xFF); - - byteOffset = 0; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set CLGC Tx Atten limit parameter */ - if ((device->tx->clgcConfig->tx1AttenLimit > 40) || (device->tx->clgcConfig->tx2AttenLimit > 40)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT)); - return MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT; - } - - armFieldValue[0] = (device->tx->clgcConfig->tx1AttenLimit & 0xFF); - armFieldValue[1] = ((device->tx->clgcConfig->tx1AttenLimit >> 8) & 0xFF); - armFieldValue[2] = (device->tx->clgcConfig->tx2AttenLimit & 0xFF); - armFieldValue[3] = ((device->tx->clgcConfig->tx2AttenLimit >> 8) & 0xFF); - - byteOffset = 8; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set CLGC Control Ratio parameter */ - if ((device->tx->clgcConfig->tx1ControlRatio < 1) || (device->tx->clgcConfig->tx1ControlRatio > 100) || (device->tx->clgcConfig->tx2ControlRatio < 1) - || (device->tx->clgcConfig->tx2ControlRatio > 100)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO)); - return MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO; - } - - armFieldValue[0] = (device->tx->clgcConfig->tx1ControlRatio & 0xFF); - armFieldValue[1] = ((device->tx->clgcConfig->tx1ControlRatio >> 8) & 0xFF); - armFieldValue[2] = (device->tx->clgcConfig->tx2ControlRatio & 0xFF); - armFieldValue[3] = ((device->tx->clgcConfig->tx2ControlRatio >> 8) & 0xFF); - - byteOffset = 12; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set enable threshold for channel 1 */ - armFieldValue[0] = (device->tx->clgcConfig->tx1RelThresholdEn > 0) ? 1 : 0; - byteOffset = 0x24; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set enable threshold for channel 2 */ - armFieldValue[0] = (device->tx->clgcConfig->tx2RelThresholdEn > 0) ? 1 : 0; - byteOffset = 0x26; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set thresholds */ - if ((device->tx->clgcConfig->tx1RelThreshold > 10000) || (device->tx->clgcConfig->tx2RelThreshold > 10000)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_THRESHOLD, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_THRESHOLD)); - return MYKONOS_ERR_CFGCLGC_INV_THRESHOLD; - } - - /* set threshold for channel 1 */ - armFieldValue[0] = (device->tx->clgcConfig->tx1RelThreshold & 0xFF); - armFieldValue[1] = ((device->tx->clgcConfig->tx1RelThreshold >> 8) & 0xFF); - byteOffset = 0x28; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set threshold for channel 2 */ - armFieldValue[0] = (device->tx->clgcConfig->tx2RelThreshold & 0xFF); - armFieldValue[1] = ((device->tx->clgcConfig->tx2RelThreshold >> 8) & 0xFF); - byteOffset = 0x2A; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL)); - return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL; - } - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Radio state check */ - if (((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_IDLE) || ((radioStatus & 0x03) == MYKONOS_ARM_SYSTEMSTATE_READY)) - { - /* set CLGC additional delay offset parameter (init cal)*/ - if ((device->tx->clgcConfig->additionalDelayOffset < -64) || (device->tx->clgcConfig->additionalDelayOffset > 64)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY)); - return MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY; - } - - armFieldValue[0] = (device->tx->clgcConfig->additionalDelayOffset & 0xFF); - armFieldValue[1] = (((uint16_t)device->tx->clgcConfig->additionalDelayOffset >> 8) & 0xFF); - byteOffset = 2; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if ((device->tx->clgcConfig->pathDelayPnSeqLevel < 1) || (device->tx->clgcConfig->pathDelayPnSeqLevel > 8191)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL)); - return MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL; - } - - /* Can not be changed in radio on */ - /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/ - armFieldValue[0] = (device->tx->clgcConfig->pathDelayPnSeqLevel & 0xFF); - armFieldValue[1] = ((device->tx->clgcConfig->pathDelayPnSeqLevel >> 8) & 0xFF); - - negPnLevel = ((~device->tx->clgcConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ - armFieldValue[2] = (negPnLevel & 0xFF); - armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF); - byteOffset = 10; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = enableClgcTracking(device, ((device->tx->clgcConfig->allowTx1AttenUpdates > 0) ? 1 : 0), ((device->tx->clgcConfig->allowTx2AttenUpdates > 0) ? 1 : 0)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - } - else - { - /* record warning about not updated members */ - CMB_writeToLog(ADIHAL_LOG_WARNING, device->spiSettings->chipSelectIndex, MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, - getMykonosErrorMessage(MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE)); - } - - return MYKONOS_ERR_OK; -} - -/* \brief Reads the CLGC config structure from ARM memory - * - * This function reads the Closed Loop Gain Control structure - * from ARM memory and returns in the device->tx->clgcConfig structure. - * - * A DPD-enabled transceiver is required for CLGC to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->clgcConfig (All members) - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for CLGC functions - * \retval MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->clgcConfig structure - */ -mykonosErr_t MYKONOS_getClgcConfig(mykonosDevice_t *device) -{ - uint16_t byteOffset = 0; - uint8_t armMem[16] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcConfig()\n"); -#endif - - /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV)); - return MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV; - } - - if (device->tx->clgcConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT)); - return MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT; - } - - byteOffset = 0; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], sizeof(armMem)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->tx1DesiredGain = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - device->tx->clgcConfig->tx2DesiredGain = (int16_t)(((uint16_t)(armMem[3]) << 8) | (uint16_t)(armMem[2])); - device->tx->clgcConfig->tx1AttenLimit = (((uint16_t)(armMem[9]) << 8) | (uint16_t)(armMem[8])); - device->tx->clgcConfig->tx2AttenLimit = (((uint16_t)(armMem[11]) << 8) | (uint16_t)(armMem[10])); - device->tx->clgcConfig->tx1ControlRatio = (((uint16_t)(armMem[13]) << 8) | (uint16_t)(armMem[12])); - device->tx->clgcConfig->tx2ControlRatio = (((uint16_t)(armMem[15]) << 8) | (uint16_t)(armMem[14])); - - byteOffset = 2; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - byteOffset = 10; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - /* need to figure out if this are the right addresses */ - byteOffset = 0x24; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->tx1RelThresholdEn = (uint8_t)armMem[0]; - - byteOffset = 0x26; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->tx2RelThresholdEn = (uint8_t)armMem[0]; - - byteOffset = 0x28; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->tx1RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - byteOffset = 0x2A; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->clgcConfig->tx2RelThreshold = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function reads the CLGC calibration status from the Mykonos ARM processor. - * - * The Closed Loop Gain Control Status is read back from the ARM processor and - * returned in the function parameter clgcStatus. - * - * A DPD-enabled transceiver is required for this feature to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to read back CLGC status for (Valid ENUM values: TX1 or TX2 only) - * \param clgcStatus Pointer to a structure to return the status information to - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM clgcStatus function parameter is a NULL pointer - * \retval MYKONOS_ERR_GETCLGCSTATUS_INV_CH txChannel parameter is a non supported value. - * \retval MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command - */ -mykonosErr_t MYKONOS_getClgcStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosClgcStatus_t *clgcStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_CLGCCONFIG, 0}; - uint8_t armData[52] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t channelSelect = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcStatus()\n"); -#endif - - if (clgcStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - channelSelect = 0; - break; - case TX2: - channelSelect = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_INV_CH)); - return MYKONOS_ERR_GETCLGCSTATUS_INV_CH; - } - } - - extData[2] = channelSelect; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - clgcStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); - clgcStatus->desiredGain = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20])); - clgcStatus->currentGain = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24])); - clgcStatus->txGain = ((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36]); - clgcStatus->txRms = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40])); - clgcStatus->orxRms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44])); - clgcStatus->trackCount = ((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48]); - - return retVal; -} - -/** - * \brief This private helper function called during RadioOff, will allow CLGC tracking to be scheduled - * by the ARM when back in the RadioOn state. - * - * This function sets a flag in the ARM memory that if the enableDpd tracking cal mask - * and this setting are both set, then the ARM will schedule closed loop gain control - * tracking to occur in the radioOn ARM state. - * - * A DPD-enabled transceiver is required for this feature to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->tx->dpdConfig - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param tx1Enable 0=disable CLGC Tx1 tracking, 1= enable CLGC Tx1 tracking - * \param tx2Enable 0=disable CLGC Tx2 tracking, 1= enable CLGC Tx2 tracking - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR ARM is not in the RadioOff state, call MYKONOS_radioOff() - */ -static mykonosErr_t enableClgcTracking(mykonosDevice_t *device, uint8_t tx1Enable, uint8_t tx2Enable) -{ - uint32_t radioStatus = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t enableBit[4] = {0}; - uint8_t byteOffset = 4; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_enableClgcTracking()\n"); -#endif - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* throw error if not in radioOff/IDLE state */ - if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR, - getMykonosErrorMessage(MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR)); - return MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR; - } - - enableBit[0] = (tx1Enable > 0) ? 1 : 0; - enableBit[1] = 0; - enableBit[2] = (tx2Enable > 0) ? 1 : 0; - enableBit[3] = 0; - - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &enableBit[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function updates the CLGC desired gain parameter. - * - * This function can be called in either Radio On or Off state. - * - * \pre A DPD-enabled transceiver is required for CLGC to be enabled. CLGC init cal has been run and CLGC tracking enable. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to set the (Valid ENUM values: TX1 or TX2 only) - * \param gain Total gain and attenuation (dB * 100) for the selected channel txChannel - * - * \retval MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL ERROR: Tx channel is not valid (Valid ENUM values: TX1 or TX2 only) - * \retval MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG ERROR: ARM command flag error set - * \retval MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN ERROR: CLGC gain parameter is out of range, valid range is from -10000 to 10000. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setClgcGain(mykonosDevice_t *device, mykonosTxChannels_t txChannel, int16_t gain) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; - uint8_t extData[4] = {0}; - uint8_t clcgChannel = 0x00; - uint8_t cmdStatusByte = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcGain()\n"); -#endif - - /* Range check for desired gain parameter */ - if ((gain < -10000) || (gain > 10000)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN, - getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN)); - return MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN; - } - - switch (txChannel) - { - case TX1: - clcgChannel = SET_CLGC_DESIRED_GAIN_1; - break; - case TX2: - clcgChannel = SET_CLGC_DESIRED_GAIN_2; - break; - - default: - /* this function allow single channel gain only */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL, - getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL)); - return MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL; - } - - extData[0] = MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL; - extData[1] = clcgChannel; - extData[2] = (gain & 0xFF); - extData[3] = (((uint16_t)gain >> 8) & 0xFF); - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* check for completion */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG)); - return MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function, when called during RadioOff, will configure VSWR settings - * - * A DPD-enabled transceiver is required for VSWR to be enabled. The VSWR has several user - * adjustable settings that can be configured before running the runInitCals - * with the calMask set for the VSWR init cal. Call this function with desired - * settings set before running the VSWR init cal or enabling VSWR tracking. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->vswrConfig (All members) - * - * \retval MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV ERROR: Tx and ObsRx profiles must be valid to use the VSWR feature - * \retval MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT ERROR: CLGC config structure pointer is null in device->tx->clgcConfig - * \retval MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR ERROR: ARM is not in the IDLE(radioOff) or Ready state. - */ -mykonosErr_t MYKONOS_configVswr(mykonosDevice_t *device) -{ - uint32_t radioStatus = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[16] = {0}; - uint8_t byteOffset = 0; - uint16_t negPnLevel = 0; - - const uint8_t ENABLE_VSWR = 1; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_configVswr()\n"); -#endif - - /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV)); - return MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV; - } - - if (device->tx->vswrConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT)); - return MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT; - } - - /* read radio state to make sure ARM is in radioOff /IDLE */ - retVal = MYKONOS_getRadioState(device, &radioStatus); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* throw error if not in radioOff/IDLE state */ - if (((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_IDLE) && ((radioStatus & 0x03) != MYKONOS_ARM_SYSTEMSTATE_READY)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR)); - return MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR; - } - - /* range check valid 3p3 GPIO pin */ - if ((device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin > 11) || (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin > 11)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN)); - return MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN; - } - - armFieldValue[0] = ENABLE_VSWR; - armFieldValue[1] = 0; - armFieldValue[2] = ENABLE_VSWR; - armFieldValue[3] = 0; - armFieldValue[4] = (device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin & 0xFF); - armFieldValue[5] = 0; - armFieldValue[6] = (device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin & 0xFF); - armFieldValue[7] = 0; - armFieldValue[8] = (device->tx->vswrConfig->tx1VswrSwitchPolarity > 0) ? 1 : 0; - armFieldValue[9] = 0; - armFieldValue[10] = (device->tx->vswrConfig->tx2VswrSwitchPolarity > 0) ? 1 : 0; - armFieldValue[11] = 0; - armFieldValue[12] = device->tx->vswrConfig->tx1VswrSwitchDelay_us; /* support full 0 to 255 us range */ - armFieldValue[13] = 0; - armFieldValue[14] = device->tx->vswrConfig->tx2VswrSwitchDelay_us; /* support full 0 to 255 us range */ - armFieldValue[15] = 0; - byteOffset = 0; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armFieldValue[0], 16); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* set VSWR additional delay offset parameter (init cal)*/ - if ((device->tx->vswrConfig->additionalDelayOffset < -64) || (device->tx->vswrConfig->additionalDelayOffset > 64)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY)); - return MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY; - } - - armFieldValue[0] = (device->tx->vswrConfig->additionalDelayOffset & 0xFF); - armFieldValue[1] = (((uint16_t)device->tx->vswrConfig->additionalDelayOffset >> 8) & 0xFF); - byteOffset = 2; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - if ((device->tx->vswrConfig->pathDelayPnSeqLevel < 1) || (device->tx->vswrConfig->pathDelayPnSeqLevel > 8191)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL, - getMykonosErrorMessage(MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL)); - return MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL; - } - - /* Set Path Delay PN sequence amplitude - positive and negative (init cal)*/ - armFieldValue[0] = (device->tx->vswrConfig->pathDelayPnSeqLevel & 0xFF); - armFieldValue[1] = ((device->tx->vswrConfig->pathDelayPnSeqLevel >> 8) & 0xFF); - - negPnLevel = ((~device->tx->vswrConfig->pathDelayPnSeqLevel) + 1); /* times -1 */ - armFieldValue[2] = (negPnLevel & 0xFF); - armFieldValue[3] = (((negPnLevel) >> 8) & 0xFF); - byteOffset = 10; - - /* Set for Tx1 channel */ - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Set for Tx2 channel */ - byteOffset = 30; - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armFieldValue[0], 4); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/* \brief Reads the VSWR config structure from ARM memory - * - * This function reads the VSWR structure - * from ARM memory and returns in the device->tx->vswrConfig structure. - * - * A DPD-enabled transceiver is required for VSWR to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - device->tx->vswrConfig (All members) - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV Error: Tx and ORx profiles must be valid for VSWR functions - * \retval MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT Error: NULL pointer to device->tx->vswrConfig structure - */ -mykonosErr_t MYKONOS_getVswrConfig(mykonosDevice_t *device) -{ - uint16_t byteOffset = 0; - uint8_t armMem[12] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrConfig()\n"); -#endif - - /* VSWR requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV)); - return MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV; - } - - if (device->tx->vswrConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT)); - return MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT; - } - - byteOffset = 4; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRCONFIG, byteOffset, &armMem[0], sizeof(armMem)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->vswrConfig->tx1VswrSwitchGpio3p3Pin = armMem[0]; - device->tx->vswrConfig->tx2VswrSwitchGpio3p3Pin = armMem[2]; - device->tx->vswrConfig->tx1VswrSwitchPolarity = armMem[4]; - device->tx->vswrConfig->tx2VswrSwitchPolarity = armMem[6]; - device->tx->vswrConfig->tx1VswrSwitchDelay_us = armMem[8]; - device->tx->vswrConfig->tx2VswrSwitchDelay_us = armMem[10]; - - byteOffset = 2; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->vswrConfig->additionalDelayOffset = (int16_t)(((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - byteOffset = 10; - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG, byteOffset, &armMem[0], 2); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - device->tx->vswrConfig->pathDelayPnSeqLevel = (((uint16_t)(armMem[1]) << 8) | (uint16_t)(armMem[0])); - - return MYKONOS_ERR_OK; -} - -/** - * \brief This function reads the VSWR calibration status from the Mykonos ARM processor. - * - * The VSWR Status is read back from the ARM processor and - * returned in the function parameter vswrStatus. - * - * A DPD-enabled transceiver is required for this feature to be enabled. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param txChannel Desired Transmit channel to read back VSWR status for (Valid ENUM values: TX1 or TX2 only) - * \param vswrStatus Pointer to a structure to return the status information to - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM vswrStatus function parameter is a NULL pointer - * \retval MYKONOS_ERR_GETVSWRSTATUS_INV_CH txChannel parameter is a non supported value. - * \retval MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG ARM reported an error while processing the GET ARM command - */ -mykonosErr_t MYKONOS_getVswrStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosVswrStatus_t *vswrStatus) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0}; - uint8_t armData[64] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint32_t offset = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t channelSelect = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getVswrStatus()\n"); -#endif - - if (vswrStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM)); - return MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - channelSelect = 0; - break; - case TX2: - channelSelect = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_INV_CH)); - return MYKONOS_ERR_GETVSWRSTATUS_INV_CH; - } - } - - extData[2] = channelSelect; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - /* throw more specific error message instead of returning error code from waitArmCmdStatus */ - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG)); - return MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG; - } - - /* read status from ARM memory */ - offset = 0; - retVal = MYKONOS_readArmMem(device, (MYKONOS_ADDR_ARM_START_DATA_ADDR + offset), &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - vswrStatus->errorStatus = ((uint32_t)(armData[3]) << 24) | ((uint32_t)(armData[2]) << 16) | ((uint32_t)(armData[1]) << 8) | (uint32_t)(armData[0]); - vswrStatus->forwardGainRms_dB = (int32_t)(((uint32_t)(armData[23]) << 24) | ((uint32_t)(armData[22]) << 16) | ((uint32_t)(armData[21]) << 8) | (uint32_t)(armData[20])); - vswrStatus->forwardGainReal = (int32_t)(((uint32_t)(armData[27]) << 24) | ((uint32_t)(armData[26]) << 16) | ((uint32_t)(armData[25]) << 8) | (uint32_t)(armData[24])); - vswrStatus->forwardGainImag = (int32_t)(((uint32_t)(armData[31]) << 24) | ((uint32_t)(armData[30]) << 16) | ((uint32_t)(armData[29]) << 8) | (uint32_t)(armData[28])); - vswrStatus->reflectedGainRms_dB = (int32_t)(((uint32_t)(armData[35]) << 24) | ((uint32_t)(armData[34]) << 16) | ((uint32_t)(armData[33]) << 8) | (uint32_t)(armData[32])); - vswrStatus->reflectedGainReal = (int32_t)(((uint32_t)(armData[39]) << 24) | ((uint32_t)(armData[38]) << 16) | ((uint32_t)(armData[37]) << 8) | (uint32_t)(armData[36])); - vswrStatus->reflectedGainImag = (int32_t)(((uint32_t)(armData[43]) << 24) | ((uint32_t)(armData[42]) << 16) | ((uint32_t)(armData[41]) << 8) | (uint32_t)(armData[40])); - vswrStatus->trackCount = ((uint32_t)(armData[63]) << 24) | ((uint32_t)(armData[62]) << 16) | ((uint32_t)(armData[61]) << 8) | (uint32_t)(armData[60]); - vswrStatus->vswr_forward_tx_rms = (int32_t)(((uint32_t)(armData[47]) << 24) | ((uint32_t)(armData[46]) << 16) | ((uint32_t)(armData[45]) << 8) | (uint32_t)(armData[44])); - vswrStatus->vswr_forward_orx_rms = (int32_t)(((uint32_t)(armData[51]) << 24) | ((uint32_t)(armData[50]) << 16) | ((uint32_t)(armData[49]) << 8) | (uint32_t)(armData[48])); - vswrStatus->vswr_reflection_tx_rms = (int32_t)(((uint32_t)(armData[55]) << 24) | ((uint32_t)(armData[54]) << 16) | ((uint32_t)(armData[53]) << 8) | (uint32_t)(armData[52])); - vswrStatus->vswr_reflection_orx_rms = (int32_t)(((uint32_t)(armData[59]) << 24) | ((uint32_t)(armData[58]) << 16) | ((uint32_t)(armData[57]) << 8) | (uint32_t)(armData[56])); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Read from the Mykonos ARM program or data memory - * - * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF), - * Data Memory (0x20000000 - 0x2000FFFF) - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param address The 32bit ARM address to read from. - * \param returnData Byte(uint8_t) array containing the data read from the ARM memory. - * \param bytesToRead Number of bytes in the returnData array. - * \param autoIncrement is boolean flag to enable or disable autoincrement of ARM register address - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READARMMEM_INV_ADDR_PARM ARM memory address is out of range - * - */ -mykonosErr_t MYKONOS_readArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *returnData, uint32_t bytesToRead, uint8_t autoIncrement) -{ - uint8_t dataMem; - uint32_t i; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmMem()\n"); -#endif - - /* check that start and stop address are in valid range */ - if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) - && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM)); - return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM; - } - - if ((!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) - && (!(((address + bytesToRead - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && (address + bytesToRead - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READARMMEM_INV_ADDR_PARM)); - return MYKONOS_ERR_READARMMEM_INV_ADDR_PARM; - } - - if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR) - { - dataMem = 1; - } - else - { - dataMem = 0; - } - - /* NOT assuming auto increment bit is already set from MYKONOS_initARM function call */ - /* setting auto increment address bit if autoIncrement evaluates true */ - if (autoIncrement) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2); - } - else - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x04, 2); - } - - /* setting up for ARM read */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x20, 5); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); /* write address[9:2] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7)); /* write address[15:10] */ - - /* start read-back at correct byte offset */ - /* read data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24]. */ - /* with address auto increment set, after xD07 is read, the address will automatically increment */ - /* without address auto increment set, 0x4 must be added to the address for correct indexing */ - if (autoIncrement) - { - for (i = 0; i < bytesToRead; i++) - { - CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]); - } - } - else - { - for (i = 0; i < bytesToRead; i++) - { - CMB_SPIReadByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), &returnData[i]); - - if ((MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)) == MYKONOS_ADDR_ARM_DATA_BYTE_3) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)(((address + 0x4) & 0x3FF) >> 2)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, ((address + 0x4) & 0x1FC00U) >> 10 | (uint8_t)(dataMem << 7)); - } - } - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Write to the Mykonos ARM program or data memory - * - * Valid memory addresses are: Program Memory (0x01000000 - 0x01017FFF), - * Data Memory (0x20000000 - 0x2000FFFF) - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param address The 32bit ARM address to write to. - * \param data Byte(uint8_t) array containing the data to write to the ARM memory. - * \param byteCount Number of bytes in the data array. - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_WRITEARMMEM_NULL_PARM Function parameter data has NULL pointer when byteCount is >0 - * \retval MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM ARM memory address is out of range of valid ARM memory - */ -mykonosErr_t MYKONOS_writeArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *data, uint32_t byteCount) -{ - /* write address, then data with auto increment enabled. */ - uint8_t dataMem; - uint32_t i; - -#if MYK_ENABLE_SPIWRITEARRAY == 1 - uint32_t addrIndex = 0; - uint32_t dataIndex = 0; - uint32_t spiBufferSize = MYK_SPIWRITEARRAY_BUFFERSIZE; - uint16_t addrArray[MYK_SPIWRITEARRAY_BUFFERSIZE] = {0}; -#endif - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmMem()\n"); -#endif - - if ((data == NULL) && (byteCount > 0)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_NULL_PARM)); - return MYKONOS_ERR_WRITEARMMEM_NULL_PARM; - } - - if ((!(address >= MYKONOS_ADDR_ARM_START_PROG_ADDR && address <= MYKONOS_ADDR_ARM_END_PROG_ADDR)) - && !(address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, - getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM)); - return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM; - } - - if ((!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_PROG_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_PROG_ADDR))) - && (!(((address + byteCount - 1) >= MYKONOS_ADDR_ARM_START_DATA_ADDR) && ((address + byteCount - 1) <= MYKONOS_ADDR_ARM_END_DATA_ADDR)))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, - getMykonosErrorMessage(MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM)); - return MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM; - } - - if (address >= MYKONOS_ADDR_ARM_START_DATA_ADDR && address <= MYKONOS_ADDR_ARM_END_DATA_ADDR) - { - dataMem = 1; - } - else - { - dataMem = 0; - } - - /* set auto increment address bit */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x01, 0x04, 2); - - /* writing the address */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_ARM_CTL_1, 0x00, 0x20, 5); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_0, (uint8_t)((address) >> 2)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_ADDR_BYTE_1, (uint8_t)(address >> 10) | (uint8_t)(dataMem << 7)); - - /* start write at correct byte offset */ - /* write data is located at SPI address 0xD04=data[7:0], 0xD05=data[15:8], 0xD06=data[23:16], 0xD07=data[31:24] */ - /* with address auto increment set, after x407 is written, the address will automatically increment */ - -#if (MYK_ENABLE_SPIWRITEARRAY == 0) - - for (i = 0; i < byteCount; i++) - { - CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)), data[i]); - } - -#elif (MYK_ENABLE_SPIWRITEARRAY == 1) - - addrIndex = 0; - dataIndex = 0; - for (i = 0; i < byteCount; i++) - { - addrArray[addrIndex++] = (MYKONOS_ADDR_ARM_DATA_BYTE_0 | (((address & 0x3) + i) % 4)); - - if (addrIndex == spiBufferSize) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex); - dataIndex = dataIndex + addrIndex; - addrIndex = 0; - } - } - - if (addrIndex > 0) - { - CMB_SPIWriteBytes(device->spiSettings, &addrArray[0], &data[dataIndex], addrIndex); - } - -#endif - - return MYKONOS_ERR_OK; -} - -/** - * \brief Low level helper function used by Mykonos API to write the ARM memory config structures - * - * Normally this function should not be required to be used directly by the BBIC. This is a helper - * function used by other Mykonos API commands to write settings into the ARM memory. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param objectId ARM id of a particular structure or setting in ARM memory - * \param offset Byte offset from the start of the objectId's memory location in ARM memory - * \param data A byte array containing data to write to the ARM memory buffer. - * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG ARM write config command failed with a nonzero error code - */ -mykonosErr_t MYKONOS_writeArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */ - uint32_t timeoutMs = 1000; - uint8_t cmdStatusByte = 0; - - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - extendedData[0] = objectId; - extendedData[1] = (offset & 0xFF); - extendedData[2] = ((offset >> 8) & 0xFF); - extendedData[3] = byteCount; - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extendedData[0], sizeof(extendedData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG)); - return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG)); - return MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Low level helper function used by Mykonos API to read the ARM memory config structures - * - * Normally this function should not be required to be used directly by the BBIC. This is a helper - * function used by other Mykonos API commands to read settings from the ARM memory. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param objectId ARM id of a particular structure or setting in ARM memory - * \param offset Byte offset from the start of the objectId's memory location in ARM memory - * \param data A byte array containing data to write to the ARM memory buffer. - * \param byteCount Number of bytes in the data array (Valid size = 1-255 bytes) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READARMCFG_ARMERRFLAG ARM read config command failed with a nonzero error code - */ -mykonosErr_t MYKONOS_readArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extendedData[4] = {0}; /* ARM Object id, byte offset LSB, offset MSB = 0, copy 2 bytes */ - uint32_t timeoutMs = 1000; - uint8_t cmdStatusByte = 0; - const uint8_t AUTO_INCREMENT = 1; - extendedData[0] = objectId; - extendedData[1] = (offset & 0xFF); - extendedData[2] = ((offset >> 8) & 0xFF); - extendedData[3] = byteCount; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_READCFG_OPCODE, &extendedData[0], sizeof(extendedData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_READCFG_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG)); - return MYKONOS_ERR_READARMCFG_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCFG_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_READARMCFG_ARMERRFLAG)); - return MYKONOS_ERR_READARMCFG_ARMERRFLAG; - } - - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &data[0], byteCount, AUTO_INCREMENT); - - return retVal; -} - -/** - * \brief Sends a command to the Mykonos ARM processor - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param opCode Value (0-30, even only) indicating the desired function to run in the ARM. - * \param extendedData A byte array containing extended data to write to the ARM command interface. - * \param extendedDataNumBytes Number of bytes in the extendedData array (Valid size = 0-4 bytes) - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ARMCMD_NULL_PARM Function parameter extendedData is NULL and extendedDataNumBytes is positive - * \retval MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only) - * \retval MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM Number of extended bytes parameter is out of range (valid 0-4) - * \retval MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY ARM control interface is busy, command could not be executed by ARM - */ -mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uint8_t *extendedData, uint8_t extendedDataNumBytes) -{ - uint8_t armCommandBusy = 0; - uint8_t i = 0; - uint16_t extCmdByteStartAddr = MYKONOS_ADDR_ARM_EXT_CMD_BYTE_1; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_sendArmCommand()\n"); -#endif - - if ((extendedData == NULL) && (extendedDataNumBytes > 0)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_NULL_PARM, getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_NULL_PARM)); - return MYKONOS_ERR_ARMCMD_NULL_PARM; - } - - /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ - if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM)); - return MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM; - } - - /* the number of valid extended data bytes is from 0-4 */ - if (extendedDataNumBytes > 4) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM)); - return MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM; - } - - /* setting a 2 sec timeout for mailbox busy bit to be clear (can't send an arm mailbox command until mailbox is ready) */ - CMB_setTimeout_ms(2000); - - do - { - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_ARM_CMD, &armCommandBusy, 0x80, 7); - - if (CMB_hasTimeoutExpired()) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY, - getMykonosErrorMessage(MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY)); - return MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY; - } - } while (armCommandBusy); - - if (extendedDataNumBytes) - { - for (i = 0; i < extendedDataNumBytes; i++) - { - CMB_SPIWriteByte(device->spiSettings, extCmdByteStartAddr + i, extendedData[i]); - } - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD, opCode); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Reads the Mykonos ARM 64-bit command status register - * - * A 64-bit status register consisting of a pending bit and three-bit error type is read one byte at - * a time for opcodes 0-30. The function parses the pending bits and error bits into - * two (2) separate 16-bit words containing pending bits, and error bits if the error type > 0 - * The words are weighted according to each even-numbered opcode from 0-30, - * where, 0x0001 = opcode '0', 0x0002 = opcode '2', 0x0004 = opcode '4', 0x0008 = opcode '6' and so on. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param errorWord 16-bit error word comprised of weighted bits according to each opcode number - * The weighted bit = '1' if error type > 0, '0' if OK - * \param statusWord 16-bit pending bits word comprised of weighted bits according to each opcode number - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM Function parameters errorWord or statusWord have a NULL pointer - */ -mykonosErr_t MYKONOS_readArmCmdStatus(mykonosDevice_t *device, uint16_t *errorWord, uint16_t *statusWord) -{ - uint8_t i = 0; - uint8_t bytes[8] = {0}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatus()\n"); -#endif - - if (errorWord == NULL || statusWord == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM)); - return MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM; - } - - /* making sure the errorWord and statusWord are clear */ - *errorWord = 0; - *statusWord = 0; - - /* read in the entire 64-bit status register into a byte array for parsing */ - for (i = 0; i < 8; i++) - { - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + i, &bytes[i]); - } - - /* parse the byte array for pending bits and error types and generate statusWord and errorWord bits */ - for (i = 0; i < 8; i++) - { - *statusWord |= (uint16_t)((uint16_t)(((bytes[i] & 0x10) >> 3) | (bytes[i] & 0x01)) << (i * 2)); - - if (bytes[i] & 0x0E) - { - *errorWord |= (uint16_t)(0x0001 << (i * 2)); - } - else if (bytes[i] & 0xE0) - { - *errorWord |= (uint16_t)(0x0002 << (i * 2)); - } - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Isolated byte read of the Mykonos ARM 64-bit command status register based on the opcode - * - * A single byte read is performed on the 64-bit command status register according to - * the opcode of interest. The pending bit and the error type are extracted from the status - * register and returned as a single byte in the lower nibble. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which status register byte to read - * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM Function parameter cmdStatByte has NULL pointer - * \retval MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM ARM opcode is out of range (valid 0-30, even only) - */ -mykonosErr_t MYKONOS_readArmCmdStatusByte(mykonosDevice_t *device, uint8_t opCode, uint8_t *cmdStatByte) -{ - uint8_t cmdByteIndex = 0; - uint8_t cmdByte = 0; - -#if 0 -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_readArmCmdStatByte()\n"); -#endif -#endif - - if (cmdStatByte == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM)); - return MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM; - } - - /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ - if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM)); - return MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM; - } - else - { - cmdByteIndex = (opCode / 4); - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_ARM_CMD_STATUS_0 + cmdByteIndex, &cmdByte); - - if ((opCode / 2) % 2) - { - *cmdStatByte = ((cmdByte >> 4) & 0x0F); - } - else - { - *cmdStatByte = (cmdByte & 0x0F); - } - - return MYKONOS_ERR_OK; - } -} - -/** - * \brief Mykonos ARM command status wait function polls command status until opcode completes - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param opCode Valid values are even increments from 0-30. The ARM opCode is used to determine which pending bit to wait for - * \param timeoutMs conveys the time-out period in milliseconds - * \param cmdStatByte returns cmdStatByte[3:1] = error type, cmdStatByte[0] = pending flag for selected opCode - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM Function parameter cmdStatByte has NULL pointer - * \retval MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM Invalid ARM opcode (valid 0-30, even numbers only) - * \retval MYKONOS_ERR_ARMCMDSTATUS_ARMERROR ARM Mailbox error flag for requested opcode returned a nonzero error flag - * \retval MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT Timeout occurred before ARM command completed - */ -mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, uint32_t timeoutMs, uint8_t *cmdStatByte) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_waitArmCmdStatus()\n"); -#endif - - if (cmdStatByte == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM)); - return MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM; - } - - /* check for even-numbered opCodes only including opcode 0, but not must be greater than opCode 30 */ - if ((opCode != 0) && ((opCode % 2) || (opCode > 30))) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM, - getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM)); - return MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM; - } - - /* start wait */ - CMB_setTimeout_ms(timeoutMs); - - do - { - retVal = MYKONOS_readArmCmdStatusByte(device, opCode, cmdStatByte); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* If error flag is non zero in [3:1], - return error */ - if ((*cmdStatByte & 0x0E) > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_ARMCMDSTATUS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_ARMCMDSTATUS_ARMERROR)); - return MYKONOS_ERR_ARMCMDSTATUS_ARMERROR; - } - - if (CMB_hasTimeoutExpired()) - { - return MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT; - } - } while (*cmdStatByte & 0x01); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Mykonos ARM configuration write - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_writeArmProfile(mykonosDevice_t *device) -{ - const uint8_t length = 100; - - int32_t i = 0; - uint8_t vcoDiv = 0; - uint8_t hsDiv = 0; - uint16_t channelsEnabled = 0; - uint8_t cfgData[100] = {0}; - - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_writeArmConfig()\n"); -#endif - - /* reading in required mykonosDevice_t structure data into array - not pretty but it works */ - for (i = 0; i < 4; i++) - { - cfgData[i] = (uint8_t)(((device->clocks->deviceClock_kHz * 1000) >> (i * 8)) & 0x000000FF); - } - - for (i = 4; i < 8; i++) - { - cfgData[i] = (uint8_t)(((device->clocks->clkPllVcoFreq_kHz) >> ((i - 4) * 8)) & 0x000000FF); - } - - vcoDiv = (uint8_t)(device->clocks->clkPllVcoDiv); - hsDiv = device->clocks->clkPllHsDiv; - - cfgData[8] = vcoDiv; /* uint8_t vco_div */ - cfgData[9] = hsDiv; /* uint8_t hs_div */ - - channelsEnabled |= ((uint16_t)device->tx->txChannels & 0x03); - channelsEnabled |= ((uint16_t)device->rx->rxChannels & 0x03) << 2; - if (device->profilesValid & ORX_PROFILE_VALID) - { - channelsEnabled |= (((uint16_t)device->obsRx->obsRxChannelsEnable & 3) << 4); - } - - if (device->profilesValid & SNIFF_PROFILE_VALID) - { - channelsEnabled |= ((((uint16_t)device->obsRx->obsRxChannelsEnable >> 2) & 7) << 6); - } - - for (i = 10; i < 12; i++) - { - cfgData[i] = (uint8_t)((channelsEnabled >> ((i - 10) * 8)) & 0xFF); - } - - cfgData[12] = ((device->rx->rxPllUseExternalLo & 0x01) << 1) | (device->tx->txPllUseExternalLo & 0x01); - cfgData[13] = 0x00; /* Not used...padding */ - cfgData[14] = 0x00; /* Not used...padding */ - cfgData[15] = 0x00; /* Not used...padding */ - - if (device->profilesValid & TX_PROFILE_VALID) - { - /* start of Tx profile data */ - cfgData[16] = (uint8_t)device->tx->txProfile->dacDiv; - cfgData[17] = device->tx->txProfile->txFirInterpolation; - cfgData[18] = device->tx->txProfile->thb1Interpolation; - cfgData[19] = device->tx->txProfile->thb2Interpolation; - - for (i = 20; i < 24; i++) - { - cfgData[i] = (uint8_t)(((device->tx->txProfile->iqRate_kHz * 1000) >> ((i - 20) * 8)) & 0x000000FF); - } - - for (i = 24; i < 28; i++) - { - cfgData[i] = (uint8_t)(((device->tx->txProfile->primarySigBandwidth_Hz) >> ((i - 24) * 8)) & 0x000000FF); - } - - for (i = 28; i < 32; i++) - { - cfgData[i] = (uint8_t)(((device->tx->txProfile->rfBandwidth_Hz) >> ((i - 28) * 8)) & 0x000000FF); - } - - for (i = 32; i < 36; i++) - { - cfgData[i] = (uint8_t)(((device->tx->txProfile->txDac3dBCorner_kHz) >> ((i - 32) * 8)) & 0x000000FF); - } - - for (i = 36; i < 40; i++) - { - cfgData[i] = (uint8_t)(((device->tx->txProfile->txBbf3dBCorner_kHz * 1000) >> ((i - 36) * 8)) & 0x000000FF); - } - } - else - { - cfgData[16] = 0; - cfgData[17] = 0; - cfgData[18] = 0; - cfgData[19] = 0; - cfgData[20] = 0; - cfgData[21] = 0; - cfgData[22] = 0; - cfgData[23] = 0; - cfgData[24] = 0; - cfgData[25] = 0; - cfgData[26] = 0; - cfgData[27] = 0; - cfgData[28] = 0; - cfgData[29] = 0; - cfgData[30] = 0; - cfgData[31] = 0; - cfgData[32] = 0; - cfgData[33] = 0; - cfgData[34] = 0; - cfgData[35] = 0; - cfgData[36] = 0; - cfgData[37] = 0; - cfgData[38] = 0; - cfgData[39] = 0; - } - - if (device->profilesValid & RX_PROFILE_VALID) - { - /* start of Rx profile data */ - cfgData[40] = device->rx->rxProfile->adcDiv; - cfgData[41] = device->rx->rxProfile->rxFirDecimation; - cfgData[42] = device->rx->rxProfile->rxDec5Decimation; - cfgData[43] = device->rx->rxProfile->rhb1Decimation; - - for (i = 44; i < 48; i++) - { - cfgData[i] = (uint8_t)(((device->rx->rxProfile->iqRate_kHz * 1000) >> ((i - 44) * 8)) & 0x000000FF); - } - - for (i = 48; i < 52; i++) - { - /* sig bw placeholder */ - cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 48) * 8)) & 0x000000FF); - } - - for (i = 52; i < 56; i++) - { - cfgData[i] = (uint8_t)(((device->rx->rxProfile->rfBandwidth_Hz) >> ((i - 52) * 8)) & 0x000000FF); - } - - for (i = 56; i < 60; i++) - { - cfgData[i] = (uint8_t)(((device->rx->rxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 56) * 8)) & 0x000000FF); - } - } - else - { - cfgData[40] = 0; - cfgData[41] = 0; - cfgData[42] = 0; - cfgData[43] = 0; - cfgData[44] = 0; - cfgData[45] = 0; - cfgData[46] = 0; - cfgData[47] = 0; - cfgData[48] = 0; - cfgData[49] = 0; - cfgData[50] = 0; - cfgData[51] = 0; - cfgData[52] = 0; - cfgData[53] = 0; - cfgData[54] = 0; - cfgData[55] = 0; - cfgData[56] = 0; - cfgData[57] = 0; - cfgData[58] = 0; - cfgData[59] = 0; - } - - if (device->profilesValid & ORX_PROFILE_VALID) - { - /* start of ObsRx profile data */ - cfgData[60] = device->obsRx->orxProfile->adcDiv; - cfgData[61] = device->obsRx->orxProfile->rxFirDecimation; - cfgData[62] = device->obsRx->orxProfile->rxDec5Decimation; - cfgData[63] = device->obsRx->orxProfile->rhb1Decimation; - - for (i = 64; i < 68; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->iqRate_kHz * 1000) >> ((i - 64) * 8)) & 0x000000FF); - } - - for (i = 68; i < 72; i++) - { - /* sig bw placeholder */ - cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 68) * 8)) & 0x000000FF); - } - - for (i = 72; i < 76; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rfBandwidth_Hz) >> ((i - 72) * 8)) & 0x000000FF); - } - - for (i = 76; i < 80; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->orxProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 76) * 8)) & 0x000000FF); - } - } - else - { - cfgData[60] = 0; - cfgData[61] = 0; - cfgData[62] = 0; - cfgData[63] = 0; - cfgData[64] = 0; - cfgData[65] = 0; - cfgData[66] = 0; - cfgData[67] = 0; - cfgData[68] = 0; - cfgData[69] = 0; - cfgData[70] = 0; - cfgData[71] = 0; - cfgData[72] = 0; - cfgData[73] = 0; - cfgData[74] = 0; - cfgData[75] = 0; - cfgData[76] = 0; - cfgData[77] = 0; - cfgData[78] = 0; - cfgData[79] = 0; - } - - if (device->profilesValid & SNIFF_PROFILE_VALID) - { - /* start of SnRx profile data */ - cfgData[80] = device->obsRx->snifferProfile->adcDiv; - cfgData[81] = device->obsRx->snifferProfile->rxFirDecimation; - cfgData[82] = device->obsRx->snifferProfile->rxDec5Decimation; - cfgData[83] = device->obsRx->snifferProfile->rhb1Decimation; - - for (i = 84; i < 88; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->iqRate_kHz * 1000) >> ((i - 84) * 8)) & 0x000000FF); - } - - for (i = 88; i < 92; i++) - { - /* sig bw placeholder */ - cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 88) * 8)) & 0x000000FF); - } - - for (i = 92; i < 96; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rfBandwidth_Hz) >> ((i - 92) * 8)) & 0x000000FF); - } - - for (i = 96; i < 100; i++) - { - cfgData[i] = (uint8_t)(((device->obsRx->snifferProfile->rxBbf3dBCorner_kHz * 1000) >> ((i - 96) * 8)) & 0x000000FF); - } - } - else - { - cfgData[80] = 0; - cfgData[81] = 0; - cfgData[82] = 0; - cfgData[83] = 0; - cfgData[84] = 0; - cfgData[85] = 0; - cfgData[86] = 0; - cfgData[87] = 0; - cfgData[88] = 0; - cfgData[89] = 0; - cfgData[90] = 0; - cfgData[91] = 0; - cfgData[92] = 0; - cfgData[93] = 0; - cfgData[94] = 0; - cfgData[95] = 0; - cfgData[96] = 0; - cfgData[97] = 0; - cfgData[98] = 0; - cfgData[99] = 0; - } - - /* writing to the ARM memory with the array data */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &cfgData[0], length); - - return retVal; -} - -/** - * \brief Function called automatically that loads the ADC profiles into the ARM - * - * User should not need to call this function normally. It is called automatically - * during MYKONOS_initArm() to load the ADC profiles (tunes the ADC performance). - * - * Rx ADC profile is only loaded if the Rx Profile is valid, ORx ADC profile is - * only loaded if the ORx Profile is valid. Sniffer ADC profile is only loaded - * if the Sniffer profile is valid. The Loopback ADC profile is always - * loaded. If Tx profile is valid, the loopback ADC profile is chosen based - * on the Tx Primary Signal bandwidth. If no valid Tx Profile, the Rx profile - * is used to set the Loopback ADC profile. Else, ORx, then sniffer profiles - * are used to set the loopback ADC profile. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV Mykonos CLKPLL has invalid VCO divider in the clocks structure - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE When Tx Profile used, a matching ORx Profile must be provided with a valid ADC divider. - * The ORx digital filters and clock dividers are used with the Loopback Rx path for Tx calibrations. - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED ADC Profile Lookup table does not have a match - * for current Rx Profile settings. Custom ADC profile required - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED ADC Profile Lookup table does not have a match - * for current ORx Profile settings. Custom ADC profile required - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED ADC Profile Lookup table does not have a match - * for current Sniffer Rx Profile settings. Custom ADC profile required - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED ADC Profile Lookup table does not have a match - * for Loopback passband BW and ADC Clock frequency settings. Custom ADC profile required - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO Rx Profile has invalid ADC divider = 0, causing a divide by zero error - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO ORx profile has invalid ADC divider = 0, causing a divide by zero error - * \retval MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO Sniffer profile has invalid ADC divider = 0, causing a divide by zero error - * \retval MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Rx ADC profile to ARM memory - * \retval MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED Error returned while trying to write ORx ADC profile to ARM memory - * \retval MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED Error returned while trying to write Sniffer ADC profile into ARM memory - * \retval MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED Error returned while trying to write Loopback ADC profile into ARM memory - */ -mykonosErr_t MYKONOS_loadAdcProfiles(mykonosDevice_t *device) -{ - uint8_t adcProfile[32] = {0}; - uint8_t i = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint32_t hsDigClk_MHz = 0; - uint32_t adcClk_MHz = 0; - uint32_t vcoDiv = 0; - uint32_t vcoDivTimes10 = 10; - uint8_t profileIndex = 0; - const uint8_t ARM_CONFIG_OFFSET = 100; /* number of bytes written in MYKONOS_writeArmProfile() to ARM memory */ - - const uint8_t NUM_ADCPROFILE_COEFS = 16; - const uint8_t NUM_ADC_PROFILES = 20; - static const uint16_t adcProfileLut[20][18] = { - /* Max RFBW, ADCCLK_MHz, adcProfile[16] */ - { 20, 491, 1494, 564, 201, 98, 1280, 134, 945, 40, 529, 10, 326, 39, 30, 16, 9, 201}, - { 60, 983, 712, 462, 201, 98, 1280, 291, 1541, 149, 1054, 46, 645, 34, 48, 32, 18, 193}, - { 75, 983, 680, 477, 201, 98, 1280, 438, 1577, 242, 1046, 73, 636, 30, 48, 31, 18, 192}, - {100, 983, 655, 446, 201, 98, 1280, 336, 1631, 334, 1152, 207, 733, 33, 48, 32, 21, 212}, - { 75, 1228, 569, 369, 201, 98, 1280, 291, 1541, 149, 1320, 58, 807, 34, 48, 40, 23, 189}, - {100, 1228, 534, 386, 201, 98, 1280, 491, 1591, 279, 1306, 104, 792, 28, 48, 39, 23, 187}, - {160, 1228, 491, 375, 201, 98, 1280, 514, 1728, 570, 1455, 443, 882, 27, 48, 39, 25, 205}, - {200, 1228, 450, 349, 201, 98, 1280, 730, 1626, 818, 1476, 732, 834, 20, 41, 36, 24, 200}, - { 80, 1250, 555, 365, 201, 98, 1280, 317, 1547, 165, 1341, 65, 819, 33, 48, 40, 24, 188}, - {102, 1250, 524, 379, 201, 98, 1280, 494, 1592, 281, 1328, 107, 805, 28, 48, 40, 23, 187}, - { 80, 1333, 526, 339, 201, 98, 1280, 281, 1539, 143, 1433, 60, 877, 35, 48, 43, 25, 188}, - {217, 1333, 414, 321, 201, 98, 1280, 730, 1626, 818, 1603, 794, 905, 20, 41, 40, 26, 199}, - { 75, 1474, 486, 302, 199, 98, 1280, 206, 1523, 101, 1578, 47, 977, 37, 48, 48, 28, 186}, - {100, 1474, 465, 311, 201, 98, 1280, 353, 1556, 187, 1581, 86, 964, 32, 48, 47, 28, 185}, - {150, 1474, 436, 296, 190, 98, 1280, 336, 1631, 334, 1638, 293, 1102, 33, 48, 46, 31, 205}, - { 40, 1536, 479, 285, 190, 98, 1280, 112, 1505, 53, 1574, 25, 1026, 40, 48, 48, 29, 186}, - {100, 1536, 450, 297, 193, 98, 1280, 328, 1550, 171, 1586, 79, 1006, 33, 48, 48, 29, 184}, - {150, 1536, 421, 283, 182, 98, 1280, 313, 1620, 306, 1638, 269, 1153, 34, 48, 46, 33, 204}, - {200, 1536, 392, 299, 180, 98, 1280, 514, 1728, 570, 1638, 498, 1104, 27, 48, 44, 32, 200}, - {240, 1536, 366, 301, 178, 98, 1280, 686, 1755, 818, 1638, 742, 1056, 22, 45, 41, 31, 196}}; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_loadAdcProfiles\n"); -#endif - - vcoDiv = (uint32_t)device->clocks->clkPllVcoDiv; - switch (vcoDiv) - { - case VCODIV_1: - vcoDivTimes10 = 10; - break; - case VCODIV_1p5: - vcoDivTimes10 = 15; - break; - case VCODIV_2: - vcoDivTimes10 = 20; - break; - case VCODIV_3: - vcoDivTimes10 = 30; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV)); - return MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV; - } - } - - hsDigClk_MHz = device->clocks->clkPllVcoFreq_kHz / vcoDivTimes10 / 100 / device->clocks->clkPllHsDiv; - - /* If Tx Profile is valid, set loopback ADC profile based on Tx primary signal BW */ - if ((device->profilesValid & TX_PROFILE_VALID) > 0) - { - /* If custom profile, load it */ - if (device->obsRx->customLoopbackAdcProfile != NULL) - { - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = device->obsRx->customLoopbackAdcProfile[i] & 0xFF; - adcProfile[i * 2 + 1] = (device->obsRx->customLoopbackAdcProfile[i] >> 8) & 0xFF; - } - } - else - { - /* Tx requires ORx profile is configured */ - if (((device->profilesValid & TX_PROFILE_VALID) > 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE)); - return MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE; - } - - if (device->obsRx->orxProfile->adcDiv == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO)); - return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO; - } - - adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv; - - /* find correct ADC profile in the LUT */ - profileIndex = NUM_ADC_PROFILES; - for (i = 0; i < NUM_ADC_PROFILES; i++) - { - /* Find a row in the LUT that matches the ADC clock frequency */ - if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->tx->txProfile->primarySigBandwidth_Hz / 1000000))) - { - profileIndex = i; - break; - } - } - - /* Verify that a profile was found in the LUT, if not return error */ - /* In this case a custom profile would need to be passed in */ - if (profileIndex >= NUM_ADC_PROFILES) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED)); - return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED; - } - - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; - adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; - } - } - - /* writing to the ARM memory: Set Loopback ADC Profile based on Tx Primary signal Bandwidth */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; - } - } - - if ((device->profilesValid & RX_PROFILE_VALID) > 0) - { - /* If custom profile, load it */ - if (device->rx->rxProfile->customAdcProfile != NULL) - { - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = device->rx->rxProfile->customAdcProfile[i] & 0xFF; - adcProfile[i * 2 + 1] = (device->rx->rxProfile->customAdcProfile[i] >> 8) & 0xFF; - } - } - else - { - if (device->rx->rxProfile->adcDiv == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO)); - return MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO; - } - - adcClk_MHz = hsDigClk_MHz / device->rx->rxProfile->adcDiv; - - /* find correct ADC profile in the LUT */ - profileIndex = NUM_ADC_PROFILES; - for (i = 0; i < NUM_ADC_PROFILES; i++) - { - /* Find a row in the LUT that matches the ADC clock frequency */ - if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->rx->rxProfile->rfBandwidth_Hz / 1000000))) - { - profileIndex = i; - break; - } - } - - /* Verify that a profile was found in the LUT, if not return error */ - /* In this case a custom profile would need to be passed in */ - if (profileIndex >= NUM_ADC_PROFILES) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED)); - return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED; - } - - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; - adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; - } - } - - /* writing to the ARM memory with ADC Profile for Rx path */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED; - } - - /* writing to the ARM memory: Set Loopback ADC Profile = Rx ADC Profile ONLY if Tx profile is not valid */ - if ((device->profilesValid & TX_PROFILE_VALID) == 0) - { - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; - } - } - } - - if ((device->profilesValid & ORX_PROFILE_VALID) > 0) - { - /* If custom profile, load it */ - if (device->obsRx->orxProfile->customAdcProfile != NULL) - { - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = device->obsRx->orxProfile->customAdcProfile[i] & 0xFF; - adcProfile[i * 2 + 1] = (device->obsRx->orxProfile->customAdcProfile[i] >> 8) & 0xFF; - } - } - else - { - if (device->obsRx->orxProfile->adcDiv == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO)); - return MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO; - } - - adcClk_MHz = hsDigClk_MHz / device->obsRx->orxProfile->adcDiv; - - /* find correct ADC profile in the LUT */ - profileIndex = NUM_ADC_PROFILES; - for (i = 0; i < NUM_ADC_PROFILES; i++) - { - /* Find a row in the LUT that matches the ADC clock frequency */ - if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->orxProfile->rfBandwidth_Hz / 1000000))) - { - profileIndex = i; - break; - } - } - - /* Verify that a profile was found in the LUT, if not return error */ - /* In this case a custom profile would need to be passed in */ - if (profileIndex >= NUM_ADC_PROFILES) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED)); - return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED; - } - - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; - adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; - } - } - - /* writing to the ARM memory with ADC Profile for ORx path */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 32, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED; - } - - /* If Rx and Tx Profiles are not valid, set Loopback ADC profile to ORx ADC Profile */ - if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0)) - { - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; - } - } - } - - if ((device->profilesValid & SNIFF_PROFILE_VALID) > 0) - { - /* If custom profile, load it */ - if (device->obsRx->snifferProfile->customAdcProfile != NULL) - { - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = device->obsRx->snifferProfile->customAdcProfile[i] & 0xFF; - adcProfile[i * 2 + 1] = (device->obsRx->snifferProfile->customAdcProfile[i] >> 8) & 0xFF; - } - } - else - { - - if (device->obsRx->snifferProfile->adcDiv == 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO)); - return MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO; - } - - adcClk_MHz = hsDigClk_MHz / device->obsRx->snifferProfile->adcDiv; - - /* find correct ADC profile in the LUT */ - profileIndex = NUM_ADC_PROFILES; - for (i = 0; i < NUM_ADC_PROFILES; i++) - { - /* Find a row in the LUT that matches the ADC clock frequency */ - if ((adcProfileLut[i][1] == adcClk_MHz) && (adcProfileLut[i][0] >= (device->obsRx->snifferProfile->rfBandwidth_Hz / 1000000))) - { - profileIndex = i; - break; - } - } - - /* Verify that a profile was found in the LUT, if not return error */ - /* In this case a custom profile would need to be passed in */ - if (profileIndex >= NUM_ADC_PROFILES) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED)); - return MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED; - } - - for (i = 0; i < NUM_ADCPROFILE_COEFS; i++) - { - adcProfile[i * 2] = adcProfileLut[profileIndex][i + 2] & 0xFF; - adcProfile[i * 2 + 1] = (adcProfileLut[profileIndex][i + 2] >> 8) & 0xFF; - } - } - - /* writing to the ARM memory with ADC Profile for sniffer Rx path */ - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 64, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED; - } - - /* If Tx, Rx, and ORx Profiles are not valid, set Loopback ADC profile to Sniffer Rx ADC Profile */ - if (((device->profilesValid & TX_PROFILE_VALID) == 0) && ((device->profilesValid & RX_PROFILE_VALID) == 0) && ((device->profilesValid & ORX_PROFILE_VALID) == 0)) - { - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR + ARM_CONFIG_OFFSET + 96, &adcProfile[0], sizeof(adcProfile)); - if (retVal) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, - getMykonosErrorMessage(MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED)); - return MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED; - } - } - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Helper function to calculate commonly used digital clock frequencies in the device - * - * User should not need to call this function normally. It is called automatically - * within other API functions to calculate the main digital clock. If the pointers - * to the return parameters are NULL, that calculation will be skipped and not - * returned. - * - * - * Dependencies - * -device->clocks->clkPllVcoFreq_kHz; - * -device->clocks->clkPllVcoDiv; - * -device->clocks->clkPllHsDiv; - * - * \param device Pointer to the device settings structure - * \param hsDigClk_kHz Return value for the calculated Mykonos high speed Digital clock at the output of the CLKPLL in kHz - * \param hsDigClkDiv4or5_kHz Return value for the Mykonos high speed digital clock divided by 4 or 5 in kHz - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM device parameter is a NULL pointer - * \retval MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT device->clocks structure is a NULL pointer - * \retval MYKONOS_ERR_CLKPLL_INV_VCODIV Invalid CLKPLL VCO divider in device->clocks->clkPllVcoDiv - * \retval MYKONOS_ERR_CLKPLL_INV_HSDIV Invalid CLKPLL High speed divider in device->clocks->clkPllHsDiv - */ -static mykonosErr_t MYKONOS_calculateDigitalClocks(mykonosDevice_t *device, uint32_t *hsDigClk_kHz, uint32_t *hsDigClkDiv4or5_kHz) -{ - uint32_t hsclkRate_kHz = 0; - uint32_t clkPllVcoFrequency_kHz = 0; - mykonosVcoDiv_t vcoDiv = VCODIV_1; - uint8_t hsDiv = 4; - - if (device == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, 0, MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM, getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM)); - return MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM; - } - - if ((device->clocks == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT)); - return MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT; - } - - clkPllVcoFrequency_kHz = device->clocks->clkPllVcoFreq_kHz; - vcoDiv = device->clocks->clkPllVcoDiv; - hsDiv = device->clocks->clkPllHsDiv; - - switch (vcoDiv) - { - case VCODIV_1: - hsclkRate_kHz = clkPllVcoFrequency_kHz; - break; - case VCODIV_1p5: - hsclkRate_kHz = (clkPllVcoFrequency_kHz / 15) * 10; - break; - case VCODIV_2: - hsclkRate_kHz = clkPllVcoFrequency_kHz >> 1; - break; - case VCODIV_3: - hsclkRate_kHz = (clkPllVcoFrequency_kHz / 30) * 10; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_VCODIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_VCODIV)); - return MYKONOS_ERR_CLKPLL_INV_VCODIV; - } - } - - switch (hsDiv) - { - case 4: - hsDiv = 4; - break; - case 5: - hsDiv = 5; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLKPLL_INV_HSDIV, getMykonosErrorMessage(MYKONOS_ERR_CLKPLL_INV_HSDIV)); - return MYKONOS_ERR_CLKPLL_INV_HSDIV; - } - } - - if (hsDigClk_kHz != NULL) - { - *hsDigClk_kHz = hsclkRate_kHz / hsDiv; - } - - if (hsDigClkDiv4or5_kHz != NULL) - { - /* This digital div 4 or 5 is always mutually exclusive with the HS Divider (4 or 5) to always - * create a /20 from the hsclk. - */ - *hsDigClkDiv4or5_kHz = hsclkRate_kHz / 20; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Performs reset to the External Tx LO Leakage tracking calibration channel estimate - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param channelSel Enum selects the channel to reset - * - * \retval MYKONOS_ERR_RESET_TXLOL_INV_PARAM Selected channel is not valid - * \retval MYKONOS_ERR_RESET_TXLOL_ARMERROR ARM error - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_resetExtTxLolChannel(mykonosDevice_t *device, mykonosTxChannels_t channelSel) -{ - const uint8_t TXLOL_RESET_CHANNEL_ESTIMATE = 0x01; - const uint32_t GETTXLOLSTATUS_TIMEOUT_MS = 1000; - - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_GS_TRACKCALS, TXLOL_RESET_CHANNEL_ESTIMATE, 0}; - uint8_t cmdStatusByte = 0; - uint8_t armErrorFlag = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_resetExtTxLolChannel()\n"); -#endif - - /* Check Channel */ - switch (channelSel) - { - case TX1: - extData[2] = 0x01; - break; - case TX2: - extData[2] = 0x02; - break; - case TX1_TX2: - extData[2] = 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_RESET_TXLOL_INV_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_RESET_TXLOL_INV_PARAM)); - return MYKONOS_ERR_RESET_TXLOL_INV_PARAM; - } - - /* throw error if not in the right state */ - retVal = MYKONOS_checkArmState(device, (MYK_ARM_IDLE | MYK_ARM_RADIO_ON)); - if (retVal) - { - return retVal; - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - if (retVal) - { - return retVal; - } - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, GETTXLOLSTATUS_TIMEOUT_MS, &cmdStatusByte); - - /* Error check WaitArmCmdStatus return */ - armErrorFlag = (cmdStatusByte >> 1); - if (armErrorFlag > 0) - { - return MYKONOS_ERR_RESET_TXLOL_ARMERROR; - } - - return retVal; -} - -/** - * \brief Configures the Radio power up/down control for Rx and Tx paths to be controlled by pins - * (TX1/2_ENABLE, RX1/2_ENABLE, and GPIO pins) or an API function call. - * - * The BBP should not have to call this as it will automatically be setup at the end of the - * MYKONOS_loadArmFromBinary() function call. If the BBP wishes to change the radio power up/down - * control method this function can be called again to change the configuration while - * the ARM is in the radioOff state. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->armGpio->useRx2EnablePin - * - device->auxIo->armGpio->useTx2EnablePin - * - device->auxIo->armGpio->txRxPinMode - * - device->auxIo->armGpio->orxPinMode - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR ARM returned an error and did not accept the command. - */ -mykonosErr_t MYKONOS_setRadioControlPinMode(mykonosDevice_t *device) -{ - uint8_t extData[4] = {0x81, 0, 0, 4}; /*Object ID 0x81 (radio control structure), offset lsb, offset msb, length*/ - uint8_t armRadioControlStruct[4] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - mykonosErr_t retval = MYKONOS_ERR_OK; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRadioControlPinMode()\n"); -#endif - - /* write ARM radio control structure to enable pin mode/command mode */ - if (device->auxIo->armGpio->useRx2EnablePin > 0) - { - armRadioControlStruct[0] = 0x01; - } - - if (device->auxIo->armGpio->useTx2EnablePin > 0) - { - armRadioControlStruct[1] = 0x01; - } - - if (device->auxIo->armGpio->txRxPinMode > 0) - { - armRadioControlStruct[2] = 0x01; - } - - if (device->auxIo->armGpio->orxPinMode > 0) - { - armRadioControlStruct[3] = 0x01; - } - - retval = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armRadioControlStruct[0], sizeof(armRadioControlStruct)); - if (retval != MYKONOS_ERR_OK) - { - return retval; - } - - retval = MYKONOS_sendArmCommand(device, MYKONOS_ARM_WRITECFG_OPCODE, &extData[0], sizeof(extData)); - if (retval != MYKONOS_ERR_OK) - { - return retval; - } - - timeoutMs = 1000; - retval = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_WRITECFG_OPCODE, timeoutMs, &cmdStatusByte); - if (retval != MYKONOS_ERR_OK) - { - return retval; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR)); - return MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Sets the measure count which is the number of samples taken before DC offset correction is applied for the given RF channel. - * This value should be changed after ARM initialization. - * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). - * - * Channel | Channel description - * ------------------------|-------------------------------- - * MYK_DC_OFFSET_RX_CHN | Selects Rx channel - * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel - * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel - * - * The total duration 'tCount' is calculated as, - * [tCount = (measureCount * 1024) / IQ data rate of the channel]. - * There is a minimum limit for the value of measureCount, the value passed should satisfy the condition 'tCount > 800us'. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param channel Receive channel to be selected. - * \param measureCount Value to be configured for the selected channel which is the number of samples taken before DC offset correction is applied. - * - * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. - * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT measurement count value passed is invalid - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT The measureCount value passed is less than the minimum limit allowed. - */ -mykonosErr_t MYKONOS_setRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t measureCount) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */ - uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */ - uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */ - - const uint8_t MEASURE_CNT_H = (measureCount & 0xFF00) >> 8; /* Higher byte of the measure count */ - const uint8_t MEASURE_CNT_L = measureCount & 0x00FF; /* Lower byte of the measure count */ - - /* Calculation of Total Duration [ tCount = (measureCount * 0x400) / IQ data rate cycles ] */ - const uint8_t FACTOR = 10; - uint32_t tCount = (measureCount << FACTOR); /* precalculations for Total duration in us */ - uint32_t IQ_RATE = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfDcOffsetCnt()\n"); -#endif - - /* check for channel and update the appropriate register address */ - switch (channel) - { - case MYK_DC_OFFSET_RX_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1; - IQ_RATE = device->rx->rxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ - break; - case MYK_DC_OFFSET_ORX_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1; - IQ_RATE = device->obsRx->orxProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ - break; - case MYK_DC_OFFSET_SNF_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1; - /* measureCount for Sniffer should be 10 bit */ - MEASURE_CNT_RANGE= 0x03FF; - IQ_RATE = device->obsRx->snifferProfile->iqRate_kHz / 1000; /* IQ Rate to calculate total duration */ - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, - getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); - return MYKONOS_ERR_DC_OFFSET_INV_CHAN; - } - - tCount = (tCount / IQ_RATE); /* Calculating total duration in us */ - if (tCount < 800) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT, - getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT)); - return MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT ; - } - - if ((measureCount < 0x11) || (measureCount & ~MEASURE_CNT_RANGE)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT, - getMykonosErrorMessage(MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT)); - return MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT ; - } - - CMB_SPIWriteField(device->spiSettings, REG_ADDRESS_H, MEASURE_CNT_H, ((MEASURE_CNT_RANGE >>8) & 0xFF),0); - CMB_SPIWriteByte(device->spiSettings, REG_ADDRESS_L, MEASURE_CNT_L); - - return retVal; -} - -/** - * \brief retrieves the measure count which is the number of samples taken before DC offset correction is applied for the given Rf channel. - * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). - * - * Channel | Channel description - * ------------------------|-------------------------------- - * MYK_DC_OFFSET_RX_CHN | Selects Rx channel - * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel - * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param channel receive channel to be selected. - * \param measureCount pointer to the variable to store the read value. - * - * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. - * \retval MYKONOS_ERR_SET_RF_DC_OFFSET_NULL_MEASURECNT passed pointer of measureCount is NULL - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t *measureCount) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS_H = 0; /* Address for Higher byte */ - uint16_t REG_ADDRESS_L = 0; /* Address for Lower byte */ - uint16_t MEASURE_CNT_RANGE = 0xFFFF; /* Mask for measure count range checking */ - uint16_t mCount = 0; /* Temporary variable to store readback from register. */ - uint8_t readbackData = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfDcOffsetCnt()\n"); -#endif - - switch (channel) - { - case MYK_DC_OFFSET_RX_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_MEASURE_COUNT_1; - break; - case MYK_DC_OFFSET_ORX_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1; - break; - case MYK_DC_OFFSET_SNF_CHN: - REG_ADDRESS_H = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2; - REG_ADDRESS_L = MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1; - /* measureCount for Sniffer should be 10 bit */ - MEASURE_CNT_RANGE= 0x03FF; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, - getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); - return MYKONOS_ERR_DC_OFFSET_INV_CHAN; - } - - if (measureCount == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT, - getMykonosErrorMessage(MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT)); - return MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT; - } - - /* Store Higher byte of measureCount */ - CMB_SPIReadField(device->spiSettings, REG_ADDRESS_H, &readbackData, ((MEASURE_CNT_RANGE >>8) & 0xFF),0); - mCount = readbackData; - mCount = mCount << 8; - - /* Store Lower byte of measureCount */ - readbackData = 0; - CMB_SPIReadByte(device->spiSettings, REG_ADDRESS_L, &readbackData); - mCount = mCount | readbackData; - - *measureCount = mCount; - - return retVal; -} - -/** - * \brief Sets M-Shift value which is the Corner frequency of Rx notch filter for the given channel. - * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). - * - * Channel | Channel description - * ------------------------|-------------------------------- - * MYK_DC_OFFSET_RX_CHN | Selects Rx channel - * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel - * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param channel receive channel to be selected. - * \param mShift value to be configured for the given channel - * - * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. - * \retval MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT mShift value passed is invalid. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t mShift) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS = 0; - - const uint8_t MSHIFT_MIN_RANGE= 0x08; - const uint8_t MSHIFT_MAX_RANGE= 0x14; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetMShift()\n"); -#endif - - if ((mShift < MSHIFT_MIN_RANGE) || (mShift > MSHIFT_MAX_RANGE)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT, - getMykonosErrorMessage(MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT)); - return MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT; - } - - /* check channel and set the address */ - switch (channel) - { - case MYK_DC_OFFSET_RX_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT; - break; - case MYK_DC_OFFSET_ORX_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT; - break; - case MYK_DC_OFFSET_SNF_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, - getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); - return MYKONOS_ERR_DC_OFFSET_INV_CHAN; - } - - CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, mShift, 0x1F, 0); - - return retVal; -} - -/** - * \brief retrieves the M-Shift value which is the Corner frequency of Rx notch filter for the given channel. - * channel can be one of the following ( ::mykonosDcOffsetChannels_t ). - * - * Channel | Channel description - * ------------------------|-------------------------------- - * MYK_DC_OFFSET_RX_CHN | Selects Rx channel - * MYK_DC_OFFSET_ORX_CHN | Selects ORx channel - * MYK_DC_OFFSET_SNF_CHN | Selects Sniffer channel - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param channel receive channel to be selected. - * \param mShift Pointer to the variable to store mshift value of the given channel - * - * \retval MYKONOS_ERR_DC_OFFSET_INV_CHAN channel passed to the function is invalid, refer mykonosDcOffsetChannels_t enum for valid channels. - * \retval MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT mShift pointer is NULL - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t *mShift) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS = 0x0; - uint8_t readbackData = 0x0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetMShift()\n"); -#endif - - if (mShift == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT, - getMykonosErrorMessage(MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT)); - return MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT; - } - - /* check for the channel and set the address */ - switch (channel) - { - case MYK_DC_OFFSET_RX_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT; - break; - case MYK_DC_OFFSET_ORX_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT; - break; - case MYK_DC_OFFSET_SNF_CHN: - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DC_OFFSET_INV_CHAN, - getMykonosErrorMessage(MYKONOS_ERR_DC_OFFSET_INV_CHAN)); - return MYKONOS_ERR_DC_OFFSET_INV_CHAN; - } - - CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x1F,0); - - *mShift = readbackData; - - return retVal; -} - -/** - * \brief Sets the RF PLL loop filter bandwith. - * - * \pre Command should be called in Radio Off state. ARM must be initialized. - * - * \post Loop filter should lock successfully - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - * \param device is structure pointer to the MYKONOS data structure containing settings - * \param pllName Name of the PLL to configure.RX_PLL and TX_PLL can be configured.SNIFFER_PLL can not be configured. - * \param loopBandwidth_kHz Desired RF pll bandwith to be set. The valid values range of loopBandwidth_kHz for Rx and Tx is 50 to 750.For SRX valid values lies from 500 to 750. - * \param stability PLL Loop stability to be set.The valid values range of stability is from 3 to 15. - * - * \return MYKONOS_ERR_OK Function completed successfully - * \return MYKONOS_ERR_SETRFPLL_LF_ARMERROR ARM Command to set RF PLL loop filter bandwidth failed - * \return MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH Invalid Tx/Rx value bandwith - * \return MYKONOS_ERR_SETRFPLL_LF_PLLNAME Invalid pllName requested - * \return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY Invalid stability range, valid range is 3-15 - */ -mykonosErr_t MYKONOS_setRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t loopBandwidth_kHz, uint8_t stability) -{ - const uint8_t SETCMD_OPCODE = 0x0A; - const uint8_t SET_PLL_BANDWIDTH = 0x6D; - const uint16_t LOOP_BW_HIGH = 750; - - uint16_t LOOP_BW_LOW = 50; - uint8_t extData[4] = {0}; - uint8_t cmdStatusByte = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - mykonosErr_t errLoopBw = MYKONOS_ERR_OK; - uint32_t timeoutMs = 1000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setRfPllLoopFilter()\n"); -#endif - - switch (pllName) - { - case RX_PLL: - extData[1] = 0x00; - LOOP_BW_LOW = 50; - errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH; - break; - case TX_PLL: - extData[1] = 0x10; - LOOP_BW_LOW = 50; - errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH; - break; - case SNIFFER_PLL: -#if 0 /* Set for Sniffer PLL loop bandwidth is not supported */ - extData[1] = 0x20; - LOOP_BW_LOW = 500; - errLoopBw = MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH; - break; -#endif - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_PLLNAME, - getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_PLLNAME)); - return MYKONOS_ERR_SETRFPLL_LF_PLLNAME; - } - } - - /* Range check for loopBandwidth - Should be between 50kHz and 750kHz for TX/RX and between 500kHz and 750 for SRX*/ - if ((loopBandwidth_kHz< LOOP_BW_LOW) || (loopBandwidth_kHz >LOOP_BW_HIGH)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, errLoopBw, - getMykonosErrorMessage(errLoopBw)); - return errLoopBw; - } - - /* Range check for stability - Should be between 3 and 15 */ - if ((stability < 3) || (stability > 15)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY, - getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY)); - return MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY; - } - - /* Generate payload for SET command */ - extData[0] = SET_PLL_BANDWIDTH; - /*left shift and truncate left side*/ - extData[1] |= stability; - extData[2] = (uint8_t)(loopBandwidth_kHz & 0xFF); //full first byte - extData[3] = (uint8_t)(loopBandwidth_kHz >> 8); //two extra bits - - /* executing the SET command */ - retVal = MYKONOS_sendArmCommand(device, SETCMD_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* waiting for command to complete */ - retVal = MYKONOS_waitArmCmdStatus(device, SETCMD_OPCODE, timeoutMs, &cmdStatusByte); - - /* performing command status check */ - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETRFPLL_LF_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_SETRFPLL_LF_ARMERROR)); - return MYKONOS_ERR_SETRFPLL_LF_ARMERROR; - } - - return retVal; - } - - return retVal; -} - -/** - * \brief Gets the RF PLL loop filter bandwidth and stability. - * - * This function is used to get the RF PLL loop bandwidth. It can get the RX PLL, TX PLL - * Sniffer PLL. - * - * \pre Command can be called in Radio Off state or On state. ARM must be initialized. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->spiSettings - * - device->clocks->deviceClock_kHz - * - * \param device is structure pointer to the MYKONOS data structure containing settings - * \param pllName Name of the PLL for which to read the frequency - * \param loopBandwidth_kHz RF PLL loop bandwidth for the PLL specified - * \param stability RF PLL loop stability - * - * \retval MYKONOS_ERR_OK Function completed successfully - * \retval MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME Invalid PLL name, can not get PLL frequency. Use PLL name ENUM. - * \retval MYKONOS_ERR_GETRFPLL_LF_ARMERROR ARM Command to get RF PLL frequency failed - * \retval MYKONOS_ERR_GETRFPLL_LF_NULLPARAM input parameter is NULL - */ -mykonosErr_t MYKONOS_getRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t *loopBandwidth_kHz, uint8_t *stability) -{ - const uint8_t GET_PLL_BANDWIDTH = 0x6D; - - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armData[8] = {0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t extData[2] = {GET_PLL_BANDWIDTH, 0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getRfPllLoopFilter()\n"); -#endif - - /* Check for NULL */ - if ((loopBandwidth_kHz == NULL)|| (stability == NULL)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_NULLPARAM)); - return MYKONOS_ERR_GETRFPLL_LF_NULLPARAM; - } - - switch(pllName) - { - case RX_PLL: extData[1] = 0x00; break; - case TX_PLL: extData[1] = 0x10; break; - case SNIFFER_PLL: extData[1] = 0x20; break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME)); - return MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME; - } - } - /* executing the GET command */ - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - - /* waiting for command to complete */ - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - - /* performing command status check */ - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRFPLL_LF_ARMERROR, - getMykonosErrorMessage(MYKONOS_ERR_GETRFPLL_LF_ARMERROR)); - return MYKONOS_ERR_GETRFPLL_LF_ARMERROR; - } - - return retVal; - } - - /* Read from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], 8, 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - /* Assign to variables */ - *stability = armData[3]; - *loopBandwidth_kHz = (((uint16_t)armData[1]) << 8) | ((uint16_t)armData[0]); - - return MYKONOS_ERR_OK; -} - -/** - * \brief Enable/ Disable Digital DC Offset channels using the channel mask. - * The mask can be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ). - * - * Channel | Value | Channel description - * -------------------------|---------|-------------------------- - * MYK_DC_OFFSET_ALL_OFF | 0x00 | Disable all the channels - * MYK_DC_OFFSET_RX1 | 0x01 | Enables Rx1 - * MYK_DC_OFFSET_RX2 | 0x02 | Enables Rx1 - * MYK_DC_OFFSET_SNF | 0x04 | Enables Sniffer - * MYK_DC_OFFSET_ORX | 0x08 | Enables ORx - * MYK_DC_OFFSET_AVAILABLE | 0x0F | Enables all the channels - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param enableMask with bits of channels to be enabled. - * - * \retval MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK enable mask passed to the function is invalid, refer mykonosRxDcOffsettEn_t enum. - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setDigDcOffsetEn(mykonosDevice_t *device, uint8_t enableMask) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS = 0x00; - uint8_t dataToWrite = 0x00; - - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDigDcOffsetEn()\n"); -#endif - - if (enableMask & ~((uint8_t)MYK_DC_OFFSET_AVAILABLE)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK, - getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK)); - return MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK; - } - - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* Address for Rx Digital tracking Enable bits register */ - if (enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 | (uint8_t)MYK_DC_OFFSET_RX2)) /* Enable / Disable Rx1 and/or Rx2 */ - { - dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_RX1 |(uint8_t) MYK_DC_OFFSET_RX2)) << 1 ); - } - CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x06,0); /* Write RX enable bits to the register */ - - dataToWrite = 0x0; /* Reset dataToWrite */ - REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* Address for ORx and Sniffer Digital trackingEnable bits register */ - if (enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX)) /* Check for channel ORx and/or Sniffer */ - { - dataToWrite |= ((enableMask & ((uint8_t)MYK_DC_OFFSET_SNF | (uint8_t)MYK_DC_OFFSET_ORX))>>2); - } - CMB_SPIWriteField(device->spiSettings, REG_ADDRESS, dataToWrite, 0x03,0); /* Write Loopback, ORx and Sniffer enable bits to the register */ - - return retVal; -} - -/** - * \brief reads Enable/ Disable channels Digital DC Offset and returns a mask of it. - * The mask returned will be a combination of the following channel values ( ::mykonosRxDcOffsettEn_t ). - * - * Channel | Value | Channel description - * -------------------------|---------|-------------------------- - * MYK_DC_OFFSET_ALL_OFF | 0x00 | All channels are disabled - * MYK_DC_OFFSET_RX1 | 0x01 | Rx1 is enabled - * MYK_DC_OFFSET_RX2 | 0x02 | Rx2 is enabled - * MYK_DC_OFFSET_SNF | 0x04 | Sniffer is enabled - * MYK_DC_OFFSET_ORX | 0x08 | ORx is enabled - * MYK_DC_OFFSET_AVAILABLE | 0x0F | All channels are enabled - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param enableMask pointer to the variable to store Enable mask of channels - * - * \retval MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK enableMask is NULL - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDigDcOffsetEn(mykonosDevice_t *device,uint8_t *enableMask) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint16_t REG_ADDRESS = 0; - uint8_t readbackData = 0; - uint8_t enableMaskData = 0; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDigDcOffsetEn()\n"); -#endif - - if (enableMask == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK, - getMykonosErrorMessage(MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK)); - return MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK; - } - - REG_ADDRESS = MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG; /* register address of Rx1 and Rx2 enable bits*/ - CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x06,0); - enableMaskData |= (readbackData>>1); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */ - - readbackData = 0x00; - REG_ADDRESS = MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING; /* register address of Orx and sniffer enable bits*/ - CMB_SPIReadField(device->spiSettings, REG_ADDRESS, &readbackData, 0x03,0); - enableMaskData |= (uint8_t)(readbackData<<2); /* adjust bits to match channel :refer enum mykonosRfDcOffsettEn_t. */ - - *enableMask = enableMaskData; - - return retVal; -} - -/** - * \brief This function will configure the path delay settings for all the features: - * DPD, VSWR and CLGC. - * - * A DPD device is required. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to be programmed - * - * \retval MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM pathDelay is null - * \retval MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE path delay valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setPathDelay(mykonosDevice_t *device, mykonosPathdelay_t *pathDelay) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[16] = {0}; - uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL, (uint8_t)SET_PATH_DELAY, 0}; - uint8_t writeSize = 0; - uint8_t fifoDel[4] = {0}; - uint8_t interpIndex[4] = {0}; - uint32_t *delPointer = &pathDelay->forwardPathDelayCh1; - uint8_t i = 0; - - const uint32_t RANGE_PATH_DELAY = 4095; - const uint8_t PATH_DELAY_SIZE = 4; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setPathDelay()\n"); -#endif - - if (pathDelay == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM)); - return MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM; - } - - /* Loop to set the ARM memory data */ - for (i = 0; i < PATH_DELAY_SIZE ; i++) - { - /* Verify all the data in the structure is in range */ - if (*delPointer > RANGE_PATH_DELAY) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE)); - return MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE; - } - - fifoDel[i] = (uint8_t)(*delPointer >> 4); - interpIndex[i] = (uint8_t)(*delPointer - (fifoDel[i] * 16)); - - delPointer++; - } - - if ((device->tx->vswrConfig == NULL) || ((pathDelay->reversePathDelayCh1 == 0) && (pathDelay->reversePathDelayCh2 == 0))) - { - armFieldValue[0] = interpIndex[0]; - armFieldValue[1] = 0; - armFieldValue[2] = fifoDel[0]; - armFieldValue[3] = 0; - armFieldValue[4] = interpIndex[2]; - armFieldValue[5] = 0; - armFieldValue[6] = fifoDel[2]; - armFieldValue[7] = 0; - extData[2] = 0; - writeSize = 8; - } - else - { - armFieldValue[0] = interpIndex[0]; - armFieldValue[1] = 0; - armFieldValue[2] = fifoDel[0]; - armFieldValue[3] = 0; - armFieldValue[4] = interpIndex[2]; - armFieldValue[5] = 0; - armFieldValue[6] = fifoDel[2]; - armFieldValue[7] = 0; - armFieldValue[8] = interpIndex[1]; - armFieldValue[9] = 0; - armFieldValue[10] = fifoDel[1]; - armFieldValue[11] = 0; - armFieldValue[12] = interpIndex[3]; - armFieldValue[13] = 0; - armFieldValue[14] = fifoDel[3]; - armFieldValue[15] = 0; - extData[2] = 1; - writeSize = 16; - } - - retVal = MYKONOS_writeArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armFieldValue[0], writeSize); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &extData[0], sizeof(extData)); - - return retVal; -} - -/** - * \brief This function will read the current path delay settings for the selected calibration. - * - * A DPD-enabled transceiver is required - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param select path delay status selection from ::mykonosPathDelaySel_t - * \param pathDelay pointer to structure of type ::mykonosPathdelay_t to store the read back path delay - * - * \retval MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM pathDelay is null - * \retval MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION invalid selection for getting the path delay, valid selections are given by mykonosPathDelaySel_t - * \retval MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG Arm error while reading path delay for the selected calibration status - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getPathDelay(mykonosDevice_t *device, mykonosPathDelaySel_t select, mykonosPathdelay_t *pathDelay) -{ - uint8_t extData[3] = {(uint8_t)MYKONOS_ARM_OBJECTID_CAL_STATUS, (uint8_t)MYKONOS_ARM_OBJECTID_VSWRCONFIG, 0}; - uint8_t armData[80] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint32_t *delPointer = &pathDelay->forwardPathDelayCh1; - uint8_t channel = 0; - uint8_t addr[4] = {0}; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getPathDelay()\n"); -#endif - - if (pathDelay == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM, - getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM)); - return MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM; - } - - switch (select) - { - case MYK_DPD_PATH_DELAY: - extData[1] = MYKONOS_ARM_OBJECTID_DPDCONFIG; - addr[0] = 24; - addr[1] = 26; - addr[2] = 0; - addr[3] = 0; - break; - case MYK_CLGC_PATH_DELAY: - extData[1] = MYKONOS_ARM_OBJECTID_CLGCCONFIG; - addr[0] = 60; - addr[1] = 62; - addr[2] = 0; - addr[3] = 0; - break; - case MYK_VSWR_PATH_DELAY: - extData[1] = MYKONOS_ARM_OBJECTID_VSWRCONFIG; - addr[0] = 72; - addr[1] = 74; - addr[2] = 76; - addr[3] = 78; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION, - getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION)); - return MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION; - } - - /* reading 2 channels, channel being the channel selector */ - for (channel = 0; channel < 2; channel++) - { - if (channel) - { - delPointer++; - } - - extData[2] = channel; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - /* throw more specific error message instead of returning error code from waitArmCmdStatus */ - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG)); - return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG)); - return MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG; - } - - /* read status from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - *delPointer = ((uint32_t)(armData[addr[1]]) * 16) + (uint32_t)(armData[addr[0]]); - delPointer++; - if ((addr[2] != 0) && (addr[3] != 0)) - { - /* reverse path delay only applies to VSWR */ - *delPointer = ((uint32_t)(armData[addr[3]]) * 16) + (uint32_t)(armData[addr[2]]); - } - else - { - /* the rest of path delays will not have a reverse delay value */ - *delPointer = 0; - } - } - - return retVal; -} - -/** - * \brief This function reads the current error counters for all the DPD error codes from ::mykonosDpdErrors_t. - * - * A DPD-enabled transceiver is required - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param txChannel Tx channel selection from ::mykonosTxChannels_t - * \param dpdErrCnt pointer to structure of type ::mykonosDpdErrorCounters_t to store the read back error counters - * - * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM dpdErrCnt is null - * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH invalid selection for getting the error counters tx channel, only valid values are Tx1 and Tx2 - * \retval MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG Arm error while reading the error counters for the DPD status - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDpdErrorCounters(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdErrorCounters_t *dpdErrCnt) -{ - uint8_t extData[3] = {MYKONOS_ARM_OBJECTID_CAL_STATUS, MYKONOS_ARM_OBJECTID_DPDCONFIG, 0}; - uint8_t armData[200] = {0}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint8_t loop = 0; - uint8_t index = 0; - uint8_t channelSelect = 0; - mykonosErr_t retVal = MYKONOS_ERR_OK; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdErrorCounters()\n"); -#endif - - if (dpdErrCnt == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM, - getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM)); - return MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM; - } - - switch (txChannel) - { - case TX1: - channelSelect = 0; - break; - case TX2: - channelSelect = 1; - break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH, - getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH)); - return MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH; - } - } - - extData[2] = channelSelect; - - retVal = MYKONOS_sendArmCommand(device, MYKONOS_ARM_GET_OPCODE, &extData[0], sizeof(extData)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - timeoutMs = 1000; - retVal = MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_GET_OPCODE, timeoutMs, &cmdStatusByte); - if (retVal != MYKONOS_ERR_OK) - { - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG)); - return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG; - } - - return retVal; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, - getMykonosErrorMessage(MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG)); - return MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG; - } - - /* read status from ARM memory */ - retVal = MYKONOS_readArmMem(device, MYKONOS_ADDR_ARM_START_DATA_ADDR, &armData[0], sizeof(armData), 1); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - dpdErrCnt->dpdErrorCount = ((uint32_t)(armData[67]) << 24) | ((uint32_t)(armData[66]) << 16) | ((uint32_t)(armData[65]) << 8) | (uint32_t)(armData[64]); - index = 68; - for (loop = 1; loop < (uint8_t)MYK_DPD_ERROR_END; loop++) - { - dpdErrCnt->errorCounter[loop] = ((uint32_t)(armData[index + 3]) << 24) | ((uint32_t)(armData[index + 2]) << 16) | ((uint32_t)(armData[index + 1]) << 8) | (uint32_t)(armData[index]); - index +=4; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief DPD feature to set the bypassing actuator when Tx signal power is below a programmable threshold given in - * ::mykonosDpdBypassConfig_t lowPowerActuatorBypassLevel. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param actConfig Pointer to actuator structure of type ::mykonosDpdBypassConfig_t which contains the settings to be programmed - * - * \retval MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT passed structure is null - * \retval MYKONOS_ERR_SETDPDACT_INV_ACTMODE invalid mode in actConfig->lowPowerActuatorBypassMode for valid modes ::mykonosDpdResetMode_t - * \retval MYKONOS_ERR_SETDPDACT_INV_LEVEL actConfig->lowPowerActuatorBypassLevel outside the range, valid range is 0 to 6000 (0 to 60dB) - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[4] = {0}; - uint8_t byteOffset = 62; - - const uint16_t LEVEL_RANGE_CHECK = 6000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdBypassConfig()\n"); -#endif - - if (actConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT)); - return MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT; - } - - if (actConfig->bypassActuatorMode >= MYK_DPD_RESET_END) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_ACTMODE, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_ACTMODE)); - return MYKONOS_ERR_SETDPDACT_INV_ACTMODE; - } - - if (actConfig->bypassActuatorLevel > LEVEL_RANGE_CHECK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACT_INV_LEVEL, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACT_INV_LEVEL)); - return MYKONOS_ERR_SETDPDACT_INV_LEVEL; - } - - armFieldValue[0] = (actConfig->bypassActuatorEn > 0) ? 1 : 0; - armFieldValue[1] = (uint8_t)(actConfig->bypassActuatorMode); - armFieldValue[2] = (uint8_t)(actConfig->bypassActuatorLevel & 0xFF); - armFieldValue[3] = (uint8_t)((actConfig->bypassActuatorLevel >> 8) & 0xFF); - - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - -/** - * \brief Get configuration for bypassing DPD actuator - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param actConfig actuator structure of type ::mykonosDpdBypassConfig_t - * - * \retval MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT passed structure is null - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[4] = {0}; - uint8_t byteOffset = 62; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdBypassConfig()\n"); -#endif - - if (actConfig == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT)); - return MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT; - } - - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - actConfig->bypassActuatorEn = armFieldValue[0]; - actConfig->bypassActuatorMode = (mykonosDpdResetMode_t)armFieldValue[1]; - actConfig->bypassActuatorLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); - - return MYKONOS_ERR_OK; -} - -/** - * \brief DPD feature to set the actuator gain difference check. - * If the gain before and after the actuator exceeds the value actCheck->actuatorGainCheckLevel an error will be issued - * and the actuator will reset depending on the actCheck->actuatorGainCheckMode. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which contains the settings to be programmed - * - * \retval MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null - * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE invalid mode in actCheck->actuatorGainCheckMode for valid modes ::mykonosDpdResetMode_t - * \retval MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL actCheck->actuatorGainCheckLevel outside the range, valid range is from 0 to 3000 (0 to 30dB) - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[4] = {0}; - uint8_t byteOffset = 58; - - const uint16_t LEVEL_RANGE_CHECK = 3000; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setDpdActuatorCheck()\n"); -#endif - - if (actCheck == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT)); - return MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT; - } - - if (actCheck->actuatorGainCheckMode >= MYK_DPD_RESET_END) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE)); - return MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE; - } - - if (actCheck->actuatorGainCheckLevel > LEVEL_RANGE_CHECK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL, - getMykonosErrorMessage(MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL)); - return MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL; - } - - armFieldValue[0] = (actCheck->actuatorGainCheckEn > 0) ? 1 : 0; - armFieldValue[1] = (uint8_t)(actCheck->actuatorGainCheckMode); - armFieldValue[2] = (uint8_t)(actCheck->actuatorGainCheckLevel & 0xFF); - armFieldValue[3] = (uint8_t)((actCheck->actuatorGainCheckLevel >> 8) & 0xFF); - - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - - -/** - * \brief Get configuration for DPD actuator check - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param actCheck Pointer to structure of type mykonosDpdActuatorCheck_t which will contain the programmed settings - * - * \retval MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT passed structure is null - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[4] = {0}; - uint8_t byteOffset = 58; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getDpdActuatorCheck()\n"); -#endif - - if (actCheck == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT)); - return MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT; - } - - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_DPDCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - actCheck->actuatorGainCheckEn = armFieldValue[0]; - actCheck->actuatorGainCheckMode = (mykonosDpdResetMode_t)armFieldValue[1]; - actCheck->actuatorGainCheckLevel = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); - - return MYKONOS_ERR_OK; -} - - -/** - * \brief CLGC feature to set the TX attenuation tuning range to a relative range around a nominal value - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which contains the settings to be programmed - * - * \retval MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV Tx and ObsRx profiles must be valid to use the CLGC feature - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT Passed structure is null - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE Invalid mode in attRangeCfg member, for valid modes ::mykonosClgcAttenTuningMode_t - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET Invalid AttenTuningPreset in attRangeCfg member, valid range is from 0 to 839 (0 to 41.95dB) - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE Invalid AttenTuningRange in attRangeCfg member, valid range is from 0 to 420 (0 to 21dB) - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS Invalid Tx1 AttenTuningRange and AttenTuningPreset combination - * \retval MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS Invalid Tx2 AttenTuningRange and AttenTuningPreset combination - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[10] = {0}; - uint8_t byteOffset = 0x2C; - - const uint16_t PRESET_CHECK = 840; - const uint16_t RANGE_CHECK = 420; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_setClgcAttenTuningConfig()\n"); -#endif - - /* CLGC requires Tx and ORx enabled, throw error if both are not enabled */ - if ((device->profilesValid & (TX_PROFILE_VALID | ORX_PROFILE_VALID)) != (TX_PROFILE_VALID | ORX_PROFILE_VALID)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, - getMykonosErrorMessage(MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV)); - return MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV; - } - - if (attRangeCfg == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT)); - return MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT; - } - - /* Range checks */ - if ((attRangeCfg->tx1AttenTuningLimitMode >= MYK_CLGC_ATTEN_END) || (attRangeCfg->tx2AttenTuningLimitMode >= MYK_CLGC_ATTEN_END)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE)); - return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE; - } - - if ((attRangeCfg->tx1AttenTuningPreset >= PRESET_CHECK) || (attRangeCfg->tx2AttenTuningPreset >= PRESET_CHECK)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET)); - return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET; - } - - if ((attRangeCfg->tx1AttenTuningRange > RANGE_CHECK) || (attRangeCfg->tx2AttenTuningRange > RANGE_CHECK)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE)); - return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE; - } - - if (((attRangeCfg->tx1AttenTuningPreset - attRangeCfg->tx1AttenTuningRange) < 0) || - ((attRangeCfg->tx1AttenTuningPreset + attRangeCfg->tx1AttenTuningRange) > PRESET_CHECK)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS)); - return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS; - } - - if (((attRangeCfg->tx2AttenTuningPreset - attRangeCfg->tx2AttenTuningRange) < 0) || - ((attRangeCfg->tx2AttenTuningPreset + attRangeCfg->tx2AttenTuningRange) > PRESET_CHECK)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS)); - return MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS; - } - - armFieldValue[0] = (uint8_t)(attRangeCfg->tx1AttenTuningLimitMode & 0xFF); - armFieldValue[1] = (uint8_t)(attRangeCfg->tx2AttenTuningLimitMode & 0xFF); - armFieldValue[2] = (uint8_t)(attRangeCfg->tx1AttenTuningPreset & 0xFF); - armFieldValue[3] = (uint8_t)((attRangeCfg->tx1AttenTuningPreset >> 8) & 0xFF); - armFieldValue[4] = (uint8_t)(attRangeCfg->tx2AttenTuningPreset & 0xFF); - armFieldValue[5] = (uint8_t)((attRangeCfg->tx2AttenTuningPreset >> 8) & 0xFF); - armFieldValue[6] = (uint8_t)(attRangeCfg->tx1AttenTuningRange & 0xFF); - armFieldValue[7] = (uint8_t)((attRangeCfg->tx1AttenTuningRange >> 8) & 0xFF); - armFieldValue[8] = (uint8_t)(attRangeCfg->tx2AttenTuningRange & 0xFF); - armFieldValue[9] = (uint8_t)((attRangeCfg->tx2AttenTuningRange >> 8) & 0xFF); - - retVal = MYKONOS_writeArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - return MYKONOS_ERR_OK; -} - - -/** - * \brief Get configuration for CLGC Tx attenuation tuning range. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->profilesValid - * - * \param device Pointer to the Mykonos device data structure containing settings - * \param attRangeCfg Pointer to structure of type mykonosClgcAttenTuningConfig_t which will contain the programmed settings - * - * \retval MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT passed structure is null - * \retval MYKONOS_ERR_OK Function completed successfully - */ -mykonosErr_t MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg) -{ - mykonosErr_t retVal = MYKONOS_ERR_OK; - uint8_t armFieldValue[10] = {0}; - uint8_t byteOffset = 0x2C; - -#if (MYKONOS_VERBOSE == 1) - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OK, "MYKONOS_getClgcAttenTuningConfig()\n"); -#endif - - if (attRangeCfg == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT, - getMykonosErrorMessage(MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT)); - return MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT; - } - - retVal = MYKONOS_readArmConfig(device, MYKONOS_ARM_OBJECTID_CLGCCONFIG, byteOffset, &armFieldValue[0], sizeof(armFieldValue)); - if (retVal != MYKONOS_ERR_OK) - { - return retVal; - } - - attRangeCfg->tx1AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[0]; - attRangeCfg->tx2AttenTuningLimitMode = (mykonosClgcAttenTuningMode_t)armFieldValue[1]; - attRangeCfg->tx1AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[3]) << 8) | (uint16_t)(armFieldValue[2])); - attRangeCfg->tx2AttenTuningPreset = (uint16_t)(((uint16_t)(armFieldValue[5]) << 8) | (uint16_t)(armFieldValue[4])); - attRangeCfg->tx1AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[7]) << 8) | (uint16_t)(armFieldValue[6])); - attRangeCfg->tx2AttenTuningRange = (uint16_t)(((uint16_t)(armFieldValue[9]) << 8) | (uint16_t)(armFieldValue[8])); - - return MYKONOS_ERR_OK; -} diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos.h b/df_datalink_ge/src/hardware/mykonos/mykonos.h deleted file mode 100644 index b852b58..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos.h +++ /dev/null @@ -1,277 +0,0 @@ -/*! - * \file mykonos.h - * \brief Contains macro definitions and function prototypes for mykonos.c - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _MYKONOS_LIB_H_ -#define _MYKONOS_LIB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "t_mykonos.h" -#include "mykonos_version.h" - -#define TX_PROFILE_VALID 0x01 -#define RX_PROFILE_VALID 0x02 -#define ORX_PROFILE_VALID 0x04 -#define SNIFF_PROFILE_VALID 0x08 - -/* - **************************************************************************** - * General Initialization functions - **************************************************************************** - */ -mykonosErr_t MYKONOS_resetDevice(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getDeviceRev(mykonosDevice_t *device, uint8_t *revision); -mykonosErr_t MYKONOS_getProductId(mykonosDevice_t *device, uint8_t *productId); -mykonosErr_t MYKONOS_setSpiSettings(mykonosDevice_t *device); -mykonosErr_t MYKONOS_verifyDeviceDataStructure(mykonosDevice_t *device); -mykonosErr_t MYKONOS_verifyProfiles(mykonosDevice_t *device); -mykonosErr_t MYKONOS_initialize(mykonosDevice_t *device); -mykonosErr_t MYKONOS_waitForEvent(mykonosDevice_t *device, waitEvent_t waitEvent, uint32_t timeout_us); -mykonosErr_t MYKONOS_readEventStatus(mykonosDevice_t *device, waitEvent_t waitEvent, uint8_t *eventDone); -mykonosErr_t MYKONOS_getApiVersion (mykonosDevice_t *device, uint32_t *siVer, uint32_t *majorVer, uint32_t *minorVer, uint32_t *buildVer); - -/* - ***************************************************************************** - * PLL / Synthesizer functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_initDigitalClocks(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t rfPllLoFrequency_Hz); -mykonosErr_t MYKONOS_getRfPllFrequency(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint64_t *rfPllLoFrequency_Hz); -mykonosErr_t MYKONOS_checkPllsLockStatus(mykonosDevice_t *device, uint8_t *pllLockStatus); -mykonosErr_t MYKONOS_setRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t loopBandwidth_kHz, uint8_t stability); -mykonosErr_t MYKONOS_getRfPllLoopFilter(mykonosDevice_t *device, mykonosRfPllName_t pllName, uint16_t *loopBandwidth_kHz, uint8_t *stability); -/* - ***************************************************************************** - * ARM Processor Control Functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_initArm(mykonosDevice_t *device); -mykonosErr_t MYKONOS_loadArmFromBinary(mykonosDevice_t *device, uint8_t *binary, uint32_t count); -mykonosErr_t MYKONOS_loadArmConcurrent(mykonosDevice_t *device, uint8_t *binary, uint32_t count); -mykonosErr_t MYKONOS_verifyArmChecksum(mykonosDevice_t *device); -mykonosErr_t MYKONOS_checkArmState(mykonosDevice_t *device, mykonosArmState_t armStateCheck); -mykonosErr_t MYKONOS_getArmVersion(mykonosDevice_t *device, uint8_t *majorVer, uint8_t *minorVer, uint8_t *rcVer, mykonosBuild_t *buildType); - -mykonosErr_t MYKONOS_configDpd(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getDpdConfig(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getDpdStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdStatus_t *dpdStatus); -mykonosErr_t MYKONOS_restoreDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes); -mykonosErr_t MYKONOS_saveDpdModel(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t *modelDataBuffer, uint32_t modelNumberBytes); -mykonosErr_t MYKONOS_setDpdActState(mykonosDevice_t *device, mykonosTxChannels_t txChannel, uint8_t actState); -mykonosErr_t MYKONOS_resetDpd(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdResetMode_t reset); -mykonosErr_t MYKONOS_setDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig); -mykonosErr_t MYKONOS_getDpdBypassConfig(mykonosDevice_t *device, mykonosDpdBypassConfig_t *actConfig); -mykonosErr_t MYKONOS_setDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck); -mykonosErr_t MYKONOS_getDpdActuatorCheck(mykonosDevice_t *device, mykonosDpdActuatorCheck_t *actCheck); - -mykonosErr_t MYKONOS_setClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg); -mykonosErr_t MYKONOS_getClgcAttenTuningConfig(mykonosDevice_t *device, mykonosClgcAttenTuningConfig_t *attRangeCfg); - -mykonosErr_t MYKONOS_configClgc(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getClgcConfig(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getClgcStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosClgcStatus_t *clgcStatus); -mykonosErr_t MYKONOS_setClgcGain(mykonosDevice_t *device, mykonosTxChannels_t txChannel, int16_t gain); - -mykonosErr_t MYKONOS_configVswr(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getVswrConfig(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getVswrStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosVswrStatus_t *vswrStatus); - -mykonosErr_t MYKONOS_runInitCals(mykonosDevice_t *device, uint32_t calMask); -mykonosErr_t MYKONOS_waitInitCals(mykonosDevice_t *device, uint32_t timeoutMs, uint8_t *errorFlag, uint8_t *errorCode); -mykonosErr_t MYKONOS_abortInitCals(mykonosDevice_t *device, uint32_t *calsCompleted); -mykonosErr_t MYKONOS_getInitCalStatus(mykonosDevice_t *device, mykonosInitCalStatus_t *initCalStatus); - -mykonosErr_t MYKONOS_resetExtTxLolChannel(mykonosDevice_t *device, mykonosTxChannels_t channelSel); - -mykonosErr_t MYKONOS_radioOn(mykonosDevice_t *device); -mykonosErr_t MYKONOS_radioOff(mykonosDevice_t *device); -mykonosErr_t MYKONOS_getRadioState(mykonosDevice_t *device, uint32_t *radioStatus); -mykonosErr_t MYKONOS_enableTrackingCals(mykonosDevice_t *device, uint32_t enableMask); -mykonosErr_t MYKONOS_rescheduleTrackingCal(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal); -mykonosErr_t MYKONOS_setAllTrackCalState(mykonosDevice_t *device, uint32_t trackingCalMask); -mykonosErr_t MYKONOS_getAllTrackCalState(mykonosDevice_t *device, uint32_t *trackCals); -mykonosErr_t MYKONOS_setTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t trackCalState); -mykonosErr_t MYKONOS_getTrackingCalState(mykonosDevice_t *device, mykonosTrackingCalibrations_t trackingCal, uint8_t *trackCalState); -mykonosErr_t MYKONOS_getEnabledTrackingCals(mykonosDevice_t *device, uint32_t *enableMask); -mykonosErr_t MYKONOS_getPendingTrackingCals(mykonosDevice_t *device, uint32_t *pendingCalMask); -mykonosErr_t MYKONOS_getTxLolStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxLolStatus_t *txLolStatus); -mykonosErr_t MYKONOS_getTxQecStatus(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosTxQecStatus_t *txQecStatus); - -mykonosErr_t MYKONOS_getRxQecStatus(mykonosDevice_t *device, mykonosRxChannels_t rxChannel, mykonosRxQecStatus_t *rxQecStatus); -mykonosErr_t MYKONOS_getOrxQecStatus(mykonosDevice_t *device, mykonosObsRxChannels_t orxChannel, mykonosOrxQecStatus_t *orxQecStatus); - -mykonosErr_t MYKONOS_setSnifferChannel(mykonosDevice_t *device, mykonosSnifferChannel_t snifferChannel); -mykonosErr_t MYKONOS_setRadioControlPinMode(mykonosDevice_t *device); - -mykonosErr_t MYKONOS_setPathDelay(mykonosDevice_t *device, mykonosPathdelay_t *pathDelay); -mykonosErr_t MYKONOS_getPathDelay(mykonosDevice_t *device, mykonosPathDelaySel_t select, mykonosPathdelay_t *pathDelay); - -mykonosErr_t MYKONOS_getDpdErrorCounters(mykonosDevice_t *device, mykonosTxChannels_t txChannel, mykonosDpdErrorCounters_t *dpdErrCnt); - -/* Low level ARM functions */ -mykonosErr_t MYKONOS_readArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *returnData, uint32_t bytesToRead, uint8_t autoIncrement); -mykonosErr_t MYKONOS_writeArmMem(mykonosDevice_t *device, uint32_t address, uint8_t *data, uint32_t byteCount); -mykonosErr_t MYKONOS_writeArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount); -mykonosErr_t MYKONOS_readArmConfig(mykonosDevice_t *device, uint8_t objectId, uint16_t offset, uint8_t *data, uint8_t byteCount); -mykonosErr_t MYKONOS_sendArmCommand(mykonosDevice_t *device, uint8_t opCode, uint8_t *extendedData, uint8_t extendedDataNumBytes); -mykonosErr_t MYKONOS_readArmCmdStatus(mykonosDevice_t *device, uint16_t *errorWord, uint16_t *statusWord); -mykonosErr_t MYKONOS_readArmCmdStatusByte(mykonosDevice_t *device, uint8_t opCode, uint8_t *cmdStatByte); -mykonosErr_t MYKONOS_waitArmCmdStatus(mykonosDevice_t *device, uint8_t opCode, uint32_t timeoutMs, uint8_t *cmdStatByte); -mykonosErr_t MYKONOS_writeArmProfile(mykonosDevice_t *device); -mykonosErr_t MYKONOS_loadAdcProfiles(mykonosDevice_t *device); - - -/* - ***************************************************************************** - * JESD204B Datapath Functions - ***************************************************************************** - */ -/* Functions to setup the JESD204B IP */ -mykonosErr_t MYKONOS_resetDeframer(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setupSerializers(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setupDeserializers(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setupJesd204bFramer(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setupJesd204bObsRxFramer(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setupJesd204bDeframer(mykonosDevice_t *device); -mykonosErr_t MYKONOS_enableRxFramerLink(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_enableObsRxFramerLink(mykonosDevice_t *device, uint8_t enable); - -/* Functions to initialize the JESD204B link */ -mykonosErr_t MYKONOS_enableMultichipSync(mykonosDevice_t *device, uint8_t enableMcs, uint8_t *mcsStatus); -mykonosErr_t MYKONOS_enableSysrefToRxFramer(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_enableSysrefToObsRxFramer(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_enableSysrefToDeframer(mykonosDevice_t *device, uint8_t enable); - -/* Functions to help debug the JESD204B link */ -mykonosErr_t MYKONOS_readRxFramerStatus(mykonosDevice_t *device, uint8_t *framerStatus); -mykonosErr_t MYKONOS_readOrxFramerStatus(mykonosDevice_t *device, uint8_t *obsFramerStatus); -mykonosErr_t MYKONOS_readDeframerStatus(mykonosDevice_t *device, uint8_t *deframerStatus); -mykonosErr_t MYKONOS_getDeframerFifoDepth(mykonosDevice_t *device, uint8_t *fifoDepth, uint8_t *readEnLmfcCount); - -/* PRBS debug functions */ -mykonosErr_t MYKONOS_enableRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable); -mykonosErr_t MYKONOS_enableObsRxFramerPrbs(mykonosDevice_t *device, mykonosPrbsOrder_t polyOrder, uint8_t enable); -mykonosErr_t MYKONOS_rxInjectPrbsError(mykonosDevice_t *device); -mykonosErr_t MYKONOS_obsRxInjectPrbsError(mykonosDevice_t *device); -mykonosErr_t MYKONOS_enableDeframerPrbsChecker(mykonosDevice_t *device, uint8_t lanes, mykonosPrbsOrder_t polyOrder, uint8_t enable); -mykonosErr_t MYKONOS_clearDeframerPrbsCounters(mykonosDevice_t *device); -mykonosErr_t MYKONOS_readDeframerPrbsCounters(mykonosDevice_t *device, uint8_t counterSelect, uint32_t *prbsErrorCount); - -/* Miscellaneous debug functions */ -mykonosErr_t MYKONOS_jesd204bIlasCheck(mykonosDevice_t *device, uint16_t *mismatch); -mykonosErr_t MYKONOS_setRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource); -mykonosErr_t MYKONOS_setObsRxFramerDataSource(mykonosDevice_t *device, uint8_t dataSource); - -/* - ***************************************************************************** - * Shared Data path functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_programFir(mykonosDevice_t *device, mykonosfirName_t filterToProgram, mykonosFir_t *firFilter); -mykonosErr_t MYKONOS_readFir(mykonosDevice_t *device, mykonosfirName_t filterToRead, mykonosFir_t *firFilter); - -/* - ***************************************************************************** - * Rx Data path functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_programRxGainTable(mykonosDevice_t *device, uint8_t *gainTablePtr, uint8_t numGainIndexesInTable, mykonosGainTable_t rxChannel); -mykonosErr_t MYKONOS_setRx1ManualGain(mykonosDevice_t *device, uint8_t gainIndex); -mykonosErr_t MYKONOS_setRx2ManualGain(mykonosDevice_t *device, uint8_t gainIndex); -mykonosErr_t MYKONOS_getRx1Gain(mykonosDevice_t *device, uint8_t *rx1GainIndex); -mykonosErr_t MYKONOS_getRx2Gain(mykonosDevice_t *device, uint8_t *rx2GainIndex); -mykonosErr_t MYKONOS_setupRxAgc(mykonosDevice_t *device); -mykonosErr_t MYKONOS_resetRxAgc(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosRxChannels_t rxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex); -mykonosErr_t MYKONOS_setObsRxAgcMinMaxGainIndex(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxChannelSelect, uint8_t maxGainIndex, uint8_t minGainIndex); -mykonosErr_t MYKONOS_setRx1TempGainComp(mykonosDevice_t *device, int16_t rx1TempCompGain_mdB); -mykonosErr_t MYKONOS_getRx1TempGainComp(mykonosDevice_t *device, int16_t *rx1TempCompGain_mdB); -mykonosErr_t MYKONOS_setRx2TempGainComp(mykonosDevice_t *device, int16_t rx2TempCompGain_mdB); -mykonosErr_t MYKONOS_getRx2TempGainComp(mykonosDevice_t *device, int16_t *rx2TempCompGain_mdB); -mykonosErr_t MYKONOS_setObsRxTempGainComp(mykonosDevice_t *device, int16_t obsRxTempCompGain_mdB); -mykonosErr_t MYKONOS_getObsRxTempGainComp(mykonosDevice_t *device, int16_t *obsRxTempCompGain_mdB); -mykonosErr_t MYKONOS_enableRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_setRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode); -mykonosErr_t MYKONOS_getRx1DecPower(mykonosDevice_t *device, uint16_t *rx1DecPower_mdBFS); -mykonosErr_t MYKONOS_getRx2DecPower(mykonosDevice_t *device, uint16_t *rx2DecPower_mdBFS); - -/* - ***************************************************************************** - * Observation Rx Data path functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_setDefaultObsRxPath(mykonosDevice_t *device, mykonosObsRxChannels_t defaultObsRxCh); -mykonosErr_t MYKONOS_setObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh); -mykonosErr_t MYKONOS_getObsRxPathSource(mykonosDevice_t *device, mykonosObsRxChannels_t *obsRxCh); -mykonosErr_t MYKONOS_setObsRxManualGain(mykonosDevice_t *device, mykonosObsRxChannels_t obsRxCh, uint8_t gainIndex); -mykonosErr_t MYKONOS_getObsRxGain(mykonosDevice_t *device, uint8_t *gainIndex); -mykonosErr_t MYKONOS_setupObsRxAgc(mykonosDevice_t *device); -mykonosErr_t MYKONOS_enableObsRxGainCtrSyncPulse(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_setObsRxGainControlMode(mykonosDevice_t *device, mykonosGainMode_t mode); -mykonosErr_t MYKONOS_getObsRxDecPower(mykonosDevice_t *device, uint16_t *obsRxDecPower_mdBFS); - -/* - ***************************************************************************** - * Tx Data path functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_setTx1Attenuation(mykonosDevice_t *device, uint16_t tx1Attenuation_mdB); -mykonosErr_t MYKONOS_setTx2Attenuation(mykonosDevice_t *device, uint16_t tx2Attenuation_mdB); -mykonosErr_t MYKONOS_getTx1Attenuation(mykonosDevice_t *device, uint16_t *tx1Attenuation_mdB); -mykonosErr_t MYKONOS_getTx2Attenuation(mykonosDevice_t *device, uint16_t *tx2Attenuation_mdB); -mykonosErr_t MYKONOS_getTxFilterOverRangeStatus(mykonosDevice_t *device, uint8_t *txFilterStatus); -mykonosErr_t MYKONOS_enableTxNco(mykonosDevice_t *device, uint8_t enable, int32_t tx1ToneFreq_kHz, int32_t tx2ToneFreq_kHz); - -/* - ***************************************************************************** - * PA Protection Functions - ***************************************************************************** - */ -mykonosErr_t MYKONOS_setupPaProtection(mykonosDevice_t *device, uint16_t powerThreshold, uint8_t attenStepSize, uint8_t avgDuration, uint8_t stickyFlagEnable, uint8_t txAttenControlEnable); -mykonosErr_t MYKONOS_enablePaProtection(mykonosDevice_t *device, uint8_t enable); -mykonosErr_t MYKONOS_getDacPower(mykonosDevice_t *device, mykonosTxChannels_t channel, uint16_t *channelPower); -mykonosErr_t MYKONOS_getPaProtectErrorFlagStatus(mykonosDevice_t *device, uint8_t *errorFlagStatus); -mykonosErr_t MYKONOS_clearPaErrorFlag(mykonosDevice_t *device); - -/* - ***************************************************************************** - * Low level functions and helper functions. BBP should not need to call - ***************************************************************************** - */ -const char* getMykonosErrorMessage(mykonosErr_t errorCode); - -mykonosErr_t MYKONOS_initSubRegisterTables(mykonosDevice_t *device); -mykonosErr_t MYKONOS_setTxPfirSyncClk(mykonosDevice_t *device); /* Helper function */ -mykonosErr_t MYKONOS_setRxPfirSyncClk(mykonosDevice_t *device); /* Helper function */ - -/* - ***************************************************************************** - * Functions to configure DC offsets - ***************************************************************************** - */ -mykonosErr_t MYKONOS_setRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t measureCount); -mykonosErr_t MYKONOS_getRfDcOffsetCnt(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint16_t *measureCount); -mykonosErr_t MYKONOS_setDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t mShift); -mykonosErr_t MYKONOS_getDigDcOffsetMShift(mykonosDevice_t *device, mykonosDcOffsetChannels_t channel, uint8_t *mShift); -mykonosErr_t MYKONOS_setDigDcOffsetEn(mykonosDevice_t *device, uint8_t enableMask); -mykonosErr_t MYKONOS_getDigDcOffsetEn(mykonosDevice_t *device, uint8_t *enableMask); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/mykonosMmap.c b/df_datalink_ge/src/hardware/mykonos/mykonosMmap.c deleted file mode 100644 index 076be0c..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonosMmap.c +++ /dev/null @@ -1,136 +0,0 @@ -/** - * \file mykonosMmap.c - * \brief Contains the Mykonos memory mapping - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -uint8_t mykonosMmap [] = {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,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x13,0x03,0x03,0x13,0x13,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,0x01, - 0x00,0xE4,0xE4,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xA5,0xA5,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x01,0x00,0xE4,0xE4,0x00,0x00,0x00,0x1F,0x00,0x14,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,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x9F,0xE0,0x20,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0xF5,0x8F,0x0F,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,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,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,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,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,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,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,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,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,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,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,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, - 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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, - 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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,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,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; -/*!< Mykonos memory map */ diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.c b/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.c deleted file mode 100644 index caf1e04..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.c +++ /dev/null @@ -1,5357 +0,0 @@ -/** - *\file mykonos_gpio.c - * - *\brief Contains Mykonos APIs for transceiver GPIO configuration and control. - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -#include -#include "../common.h" -#include "mykonos.h" -#include "mykonos_gpio.h" -#include "mykonos_macros.h" -#include "mykonos_user.h" - - -/** - * \brief Helper function for return of character string based on 32-bit mykonosGpioErr_t enum value - * - * To save codespace, these error strings are ifdef'd out unless the user - * adds a define MYKONOS_VERBOSE to their workspace. This function can be - * useful for debug. Each function also returns unique error codes to - * make it easier to determine where the code broke. - * - * \param errorCode is enumerated error code value - * - * \return Returns character string based on enumerated value - */ -const char* getGpioMykonosErrorMessage(mykonosGpioErr_t errorCode) -{ -#if MYKONOS_VERBOSE == 0 - return ""; - - #else - - switch (errorCode) - { - case MYKONOS_ERR_GPIO_OK: - return ""; - - case MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED: - return "MYKONOS_setGpioMonitorOut() Mykonos monitor output not enable, please run GPIO setup with the correct setup for enabling the monitor output functionality\n"; - - case MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE: - return "MYKONOS_setGpioMonitorOut()The index specified is incorrect, index available are from 0x01 to 0x42\n"; - - case MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM: - return "MYKONOS_getGpioMonitorOut() if the monitorIndex is null.\n"; - - case MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM: - return "MYKONOS_getGpioMonitorOut() if the monitorMask is null.\n"; - - case MYKONOS_ERR_MGCRX1_STEP_INV_PARAM: - return "MYKONOS_setRx1GainCtrlPin() An invalid step size has been passed, valid step sizes for increment/decrement is 0-7\n"; - - case MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM: - return "MYKONOS_setRx1GainCtrlPin() An invalid decrement pin has been passed \n"; - - case MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM: - return "MYKONOS_setRx1GainCtrlPin() An invalid increment pin has been passed, \n"; - - case MYKONOS_ERR_MGCRX2_STEP_INV_PARAM: - return "MYKONOS_setRx2GainCtrlPin() An invalid step size has been passed, valid step sizes for increment/decrement is 0-7\n"; - - case MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM: - return "MYKONOS_setRx2GainCtrlPin() An invalid decrement pin has been passed\n"; - - case MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM: - return "MYKONOS_setRx2GainCtrlPin() An invalid increment pin has been passed\n"; - - case MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM: - return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to incStep.\n"; - - case MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM: - return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to decStep.\n"; - - case MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM: - return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to rx1GainIncPin.\n"; - - case MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM: - return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to rx1GainDecPin.\n"; - - case MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM: - return "MYKONOS_getRx1GainCtrlPin() if a null value has been passed to enable.\n"; - - case MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM: - return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to incStep.\n"; - - case MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM: - return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to decStep.\n"; - - case MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM: - return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to rx1GainIncPin.\n"; - - case MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM: - return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to rx1GainDecPin.\n"; - - case MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM: - return "MYKONOS_getRx2GainCtrlPin() if a null value has been passed to enable.\n"; - - case MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM: - return "MYKONOS_setTx1AttenCtrlPin() An invalid step size has been passed, valid step sizes for att are 0x00-0x1F\n"; - - case MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM: - return "MYKONOS_setTx1AttenCtrlPin() An invalid decrement pin has been passed\n"; - - case MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM: - return "MYKONOS_setTx1AttenCtrlPin() An invalid decrement pin has been passed\n"; - - case MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM: - return "MYKONOS_setTx2AttenCtrlPin() An invalid step size has been passed, valid step sizes for att are 0x00-0x1F\n"; - - case MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM: - return "MYKONOS_setTx2AttenCtrlPin() An invalid decrement pin has been passed\n"; - - case MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM: - return "MYKONOS_setTx2AttenCtrlPin() An invalid decrement pin has been passed\n"; - - case MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM: - return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to stepSize.\n"; - - case MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM: - return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to tx2AttenIncPin.\n"; - - case MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM: - return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to tx2AttenDecPin.\n"; - - case MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM: - return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to enable.\n"; - - case MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM: - return "MYKONOS_getTx2AttenCtrlPin() if a null value has been passed to useTx1ForTx2.\n"; - - case MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM: - return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to stepSize.\n"; - - case MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM: - return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to tx1AttenIncPin.\n"; - - case MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM: - return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to tx1AttenDecPin.\n"; - - case MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM: - return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to enable.\n"; - - case MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM: - return "MYKONOS_getTx1AttenCtrlPin() if a null value has been passed to useTx1ForTx2.\n"; - - case MYKONOS_ERR_GPIO_SRC_PARAM_INV: - return "MYKONOS_setGpioSourceCtrl() An invalid source control parameter has been passed\n"; - - case MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM: - return "MYKONOS_getGpioSetLevel() gpioPinSetLevel pointer is NULL in function parameter\n"; - - case MYKONOS_ERR_READGPIOSPI_NULL_PARM: - return "MYKONOS_readGpioPinLevel() has a null *gpioPinLevel parameter\n"; - - case MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM: - return "MYKONOS_getGpio3v3PinLevel() has a null *gpio3v3PinLevel parameter\n"; - - case MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM: - return "MYKONOS_setupAuxDac() has a null device->auxIo pointer\n"; - - case MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM: - return "MYKONOS_getGpio3v3Oe() has NULL pointer for function parameter gpio3v3OutEn\n;"; - - case MYKONOS_ERR_INV_GP_INT_MASK_PARM: - return "General Purpose Interrupt source mask parameter is invalid\n"; - - case MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM: - return "MYKONOS_readGpInterruptStatus() has NULL status parameter\n"; - - case MYKONOS_ERR_SET_GPIO_3V3_INV_MODE: - return "Invalid GPIO3v3 source control mode\n"; - - case MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL: - return "gpio3v3 members have invalid value for the GPIO3v3 source control mode.\n"; - - case MYKONOS_ERR_SET_GPIO_1V8_INV_MODE: - return "The GPIO mode enum is not a valid value in MYKONOS_setupGpio\n"; - - case MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM: - return "MYKONOS_getGpio3v3SetLevel() has NULL pointer for function parameter gpio3v3SetLevel\n"; - - case MYKONOS_ERR_GPIO_OE_INV_PARAM: - return "MYKONOS_setGpioOe() had invalid parameter gpioOutEn (valid range 0 - 0x07FFFF)\n"; - - case MYKONOS_ERR_GETGPIO_OE_NULL_PARM: - return "MYKONOS_getGpioOe() has NULL function parameter\n"; - - case MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO: - return "device->auxIo structure has NULL pointer in MYKONOS_writeAuxDac()\n"; - - case MYKONOS_ERR_READAUXADC_NULL_PARAM: - return "MYKONOS_readAuxAdc() has NULL function parameter\n"; - - case MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER: - return "Invalid pointer detected in MYKONOS_setupGpio3v3()\n"; - - case MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER: - return "Invalid pointer detected in MYKONOS_setupGpio()\n"; - - case MYKONOS_ERR_SET_ARMGPIO_INV_POINTER: - return "Invalid pointer detected at device->auxIo->armGpio in MYKONOS_setArmGpioPins() \n"; - - case MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR: - return "ARM Command Error in MYKONOS_setArmGpioPins()\n"; - - case MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID: - return "Invalid Signal ID detected in device->auxIo->armGpio \n"; - - case MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN: - return "Out of range GPIO pin detected \n"; - - case MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE: - return "device->auxIo->auxDacValue, AUXDAC value out of range in MYKONOS_setupAuxDacs()\n"; - - case MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE: - return "auxDacCode value out of range in MYKONOS_writeAuxDac()\n"; - - case MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX: - return "auxDacIndex value out of range in MYKONOS_writeAuxDac()\n"; - - case MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM: - return "auxAdcChannel value out of range in MYKONOS_setAuxAdcChannel()\n"; - - case MYKONOS_ERR_SETUPAUXADC_INV_VCODIV: - return "device->clocks->clkPllVcoDiv value not supported in MYKONOS_setupAuxAdcs()\n"; - - case MYKONOS_ERR_INV_AUX_ADC_DEC_PARM: - return "adcDecimation value out of range in MYKONOS_setupAuxAdcs()\n"; - - case MYKONOS_ERR_SLICER_INV_RX1_SEL: - return "invalid RX1 GPIO pin selection for Slicer control in MYKONOS_setRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_INV_RX2_SEL: - return "invalid RX2 GPIO pin selection for Slicer control in MYKONOS_setRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE: - return "slicer step is out of range for the SLicer control in MYKONOS_setRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_EN_INV: - return "invalid enable in MYKONOS_setRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM: - return "rx1Pins is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM: - return "rx1Pins is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_STEP_NULL_PARM: - return "slicerStep is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; - - case MYKONOS_ERR_SLICER_EN_NULL_PARM: - return "enable is null pointer for the passed parameter in MYKONOS_getRxSlicerCtrl()\n"; - - case MYKONOS_ERR_GAINCOMP_NULL_STRUCT: - return "gain compensation structure gainComp is not initialised in MYKONOS_getRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_EN_NULL_PARM: - return "enable is null pointer for the passed parameter in MYKONOS_getRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT: - return "gain compensation structure gainComp is not initialised in MYKONOS_setRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET: - return "gain compensation structure gainComp->rx1Offset is invalid in MYKONOS_setRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET: - return "gain compensation structure gainComp->rx2Offset is invalid in MYKONOS_setRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_INV_STEP: - return "gain compensation structure gainComp->compStep is invalid in MYKONOS_setRxGainCompensation()\n"; - - case MYKONOS_ERR_GAINCOMP_INV_EN: - return "enable is not valid in MYKONOS_setRxGainCompensation()\n"; - - case MYKONOS_ERR_FLOATFRMT_NULL_STRUCT: - return "floating point formatter structure floatFrmt not initialised in MYKONOS_getFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT: - return "floating point formatter structure floatFrmt not initialised in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE: - return "floating point formatter structure floatFrmt.roundMode not valid parameter in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT: - return "floating point formatter structure floatFrmt.dataFormat not valid parameter in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN: - return "floating point formatter structure floatFrmt.encNan not valid parameter in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS: - return "floating point formatter structure floatFrmt.expBits not valid parameter in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_LEADING: - return "floating point formatter structure floatFrmt.leading not valid parameter in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_RX1ATT: - return "not valid rx1 attenuation parameter passed in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_INV_RX2ATT: - return "not valid rx2 attenuation parameter passed in MYKONOS_setFloatPointFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT: - return "not valid rx2 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT: - return "not valid rx1 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_SET_INV_EN: - return "not valid enable parameter passed in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT: - return "null pointer passed for rx1 attenuation in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT: - return "null pointer passed for rx2 attenuation in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_FLOATFRMT_NULL_ENABLE: - return "null pointer passed for enable in MYKONOS_setRxEnFloatPntFrmt()\n"; - - case MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM: - return "MYKONOS_setupTempSensor() has NULL function parameter\n"; - - case MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION: - return "tempDecimation value out of range in MYKONOS_setupTempSensor()\n"; - - case MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW: - return "tempWindow value out of range in MYKONOS_setupTempSensor()\n"; - - case MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET: - return "offset value out of range in MYKONOS_setupTempSensor()\n"; - - case MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM: - return "MYKONOS_getTempSensorConfig() has NULL function parameter\n"; - - case MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM: - return "MYKONOS_readTempSensor() has NULL function parameter\n"; - - case MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED: - return "MYKONOS_readTempSensor() temperature sensor reading is not locked\n"; - - case MYKONOS_ERR_GPIO_HYBRID_RX1_PIN: - return "MYKONOS_setRxHybridGainChangePin() not valid pin has been passed for RX1 hybrid gain control.\n"; - - case MYKONOS_ERR_GPIO_HYBRID_RX2_PIN: - return "MYKONOS_setRxHybridGainChangePin() not valid pin has been passed for RX2 hybrid gain control.\n"; - - case MYKONOS_ERR_GPIO_HYBRID_ORX_PIN: - return "MYKONOS_setObsRxHybridGainChangePin() if invalid pin has been passed for ORX hybrid gain control.\n"; - - case MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID: - return "MYKONOS_setObsRxHybridGainChangePin() if the observation gain mode is not set to Hybrid.\n"; - - case MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM: - return "MYKONOS_getRxHybridGainChangePin() null value has been passed to rx1GainChangePin.\n"; - - case MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM: - return "MYKONOS_getRxHybridGainChangePin() null value has been passed to rx1GainChangePin.\n"; - - case MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID: - return "MYKONOS_setRxHybridGainChangePin() if gain control is not hybrid.\n"; - - case MYKONOS_ERR_GAIN_CONTROL_NOT_AGC : - return "MYKONOS_setRxAgcEnSyncPin() or MYKONOS_getObsRxAgcEnSyncPin() if the observation gain control mode is not set to AGC.\n"; - - case MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC: - return "MYKONOS_getObsRxAgcEnSyncPin() if the observation gain control mode is not set to AGC.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN: - return "MYKONOS_setRxAgcEnSyncPin() if invalid pin has been passed for RX1 AGC sync gain control.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN: - return "MYKONOS_setRxAgcEnSyncPin() if invalid pin has been passed for RX2 AGC sync gain control.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM: - return "MYKONOS_getRxAgcEnSyncPin() if a null value has been passed to rx1AgcSyncPin.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM: - return "MYKONOS_getRxAgcEnSyncPin() if a null value has been passed to rx2AgcSyncPin.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN: - return "MYKONOS_setObsRxAgcEnSyncPin() if invalid pin has been passed for ORX AGC sync gain control.\n"; - - case MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM: - return "MYKONOS_getObsRxAgcEnSyncPin() if a null value has been passed to obsRxAgcSyncPin.\n"; - - case MYKONOS_ERR_SLICER_INV_OBS_RX_SEL: - return "Invalid observation channel GPIO pin selection for Slicer control passed to MYKONOS_setObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE: - return "Slicer step is out of range passed to MYKONOS_setObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_SLICER_OBS_RX_EN_INV: - return "Invalid enable passed to MYKONOS_setObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM: - return "ObsRxPins is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM: - return "SlicerStep is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM: - return "Enable is null pointer for the passed parameter passed to MYKONOS_getObsRxSlicerCtrl().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT: - return "Gain compensation structure gainComp is not initialised in MYKONOS_setObsRxGainCompensation().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET: - return "Gain compensation structure gainComp->obsRxOffset is invalid in MYKONOS_setObsRxGainCompensation().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP: - return "Gain compensation structure gainComp->compStep is invalid in MYKONOS_setObsRxGainCompensation().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN: - return "Enable is not valid in MYKONOS_setObsRxGainCompensation().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT: - return "Observation channel gain compensation structure gainComp is not initialised in MYKONOS_getObsRxGainCompensation().\n"; - - case MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM: - return "enabled is null pointer for the parameter passed to MYKONOS_getObsRxGainCompensation().\n"; - - case MYKONOS_ERR_GETGPIODRV_NULL_PARAM: - return "Null parameter passed to the function MYKONOS_getGpioDrv().\n"; - - case MYKONOS_ERR_GPIO_DRV_INV_PARAM: - return "GPIO out of range passed to function MYKONOS_setGpioDrv(), valid GPIOs are in the range 0x00000 to 0x7FFFF.\n"; - - case MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM: - return "GPIO out of range -valid GPIOs are in the range 0x00000 to 0x7FFFF.\n"; - - case MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM: - return "Null parameter passed to the function MYKONOS_getGpioSlewRate().\n"; - - case MYKONOS_ERR_CMOS_DRV_NULL_PARAM: - return "Null parameter passed to the function.\n"; - - case MYKONOS_ERR_CMOS_DRV_INV_PARAM: - return "Incorrect drive strength, valid settings are given by mykonosCmosPadDrvStr_t.\n"; - - case MYKONOS_ERR_SPI2_INV_GPIO: - return "if an invalid GPIO pin configuration is passed to MYKONOS_spi2GpioSetup().\n"; - - case MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM: - return "Null parameter passed to the function MYKONOS_getGpioSourceCtrl().\n"; - - default: - return "Unknown error was encountered.\n"; - } - - #endif -} - -/** - * \brief This API function configures the monitor output function for the GPIOs - * - * The monitor outputs are grouped in set of nibbles, the user can set - * individual nibbles for having the monitor output function across the available GPIO. - * In order to enable the GPIO monitor function the function setupGpio has to be run and the - * structure should have the proper setup: - * - device->auxIo->gpio->gpioOe = 0xXXXFF the first D7:D0 GPIOs will have the output enable - * - device->auxIo->gpio->gpioSrcCtrl3_0 = GPIO_MONITOR_MODE - * - device->auxIo->gpio->gpioSrcCtrl4_7 = GPIO_MONITOR_MODE - - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio->gpioOe - * - device->auxIo->gpio->gpioSrcCtrl3_0 - * - device->auxIo->gpio->gpioSrcCtrl4_7 - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \param monitorIndex which will be the index at which the outputs are going to be set. see table in documentation - * - * \param monitorMask which GPIO outputs are going to active, the available GPIO - * bit 0 will represent MYKGPIO0 and bit 7 will represent MYKGPIO7. - * - * \retval MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE if GPIO Monitor output index is not in table - * \retval MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED if GPIO source control not set for Monitor output - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioMonitorOut(mykonosDevice_t *device, uint8_t monitorIndex, uint8_t monitorMask) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - const uint8_t INDEX_MASK = 0x42; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioMonitorOut()\n"); -#endif - - /* Error checking for correct index. */ - if (monitorIndex > INDEX_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE, - getGpioMykonosErrorMessage(MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE)); - return MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE; - } - - /* Set the GPIO monitor index and the required pin configuration. */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_INDEX, monitorIndex); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_ENABLE, monitorMask); - - return error; -} - -/** - * \brief This API function reads the GPIO monitor index from Mykonos - * - * The monitor outputs are grouped in two set of nibbles, the user can set - * individual nibbles for having the monitor output function, this nibbles - * will output the monitor output as per the index set. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - GPIO output enable - * - GPIO source control - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param monitorIndex which will be the index at which the outputs are set to. - * \param monitorMask which will be enable the monitor function. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM if the monitorIndex is null. - * \retval MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM if the monitorMask is null. - */ -mykonosGpioErr_t MYKONOS_getGpioMonitorOut(mykonosDevice_t *device, uint8_t *monitorIndex, uint8_t *monitorMask) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - uint8_t indexRd = 0; - uint8_t monMaskRd = 0; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioMonitorOut()\n"); -#endif - - /* Checking for null passed parameters */ - if (monitorIndex == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM)); - return MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM; - } - - if (monitorMask == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM)); - return MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM; - } - - /* Get GPIO monitor out enable. */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_ENABLE, &monMaskRd); - - /* Get the GPIO monitor index and the required pin configuration. */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_MONITOR_INDEX, &indexRd); - - /* assigning return values to the pointers passed */ - *monitorMask = monMaskRd; - *monitorIndex = indexRd; - - return error; -} - - - - -/** - * \brief This API function configures the GPIO inputs for controlling RX gain - * - * This API function configures the GPIO input pin and step size to allow the BBP to control gain changes in Rx1 signal chain. - * A high pulse on the 'rx1GainIncPin' in pin control mode will increment the gain by the value set in incStep'. - * A high pulse on the 'rx1GainDecPin' in pin control mode will decrement the gain by the value set in 'decStep'. - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \param incStep This sets the change (increase) in gain index that is applied when the - * increment gain pin (in MGC pin control mode) is pulsed. - * - * \param decStep This configures the decrement in gain index that should be applied - * when the decrement gain pin (in MGC pin control mode) is pulsed. - * - * \param rx1GainIncPin mykonosGpioSelect_t These bits select the GPIO used as the enable for - * the Rx1 Manual Increment gain input according to the following: - * MYKGPIO0 or MYKGPIO10 - * - * \param rx1GainDecPin mykonosGpioSelect_t These bits select the GPIO used as the enable for - * the Rx1 Manual Decrement gain input according to the following: - * MYKGPIO1 or MYKGPIO11 - * - * \param enable 0 = Disable the gain pin control for Rx1 - * 1 = enable the gain pin control for Rx1 - * - * \retval MYKONOS_ERR_MGCRX1_STEP_INV_PARAM if an invalid step size has been passed - * \retval MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM if invalid increment pin has been passed - * \retval MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM if invalid decrement pin has been passed - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setRx1GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx1GainIncPin, mykonosGpioSelect_t rx1GainDecPin, uint8_t enable) -{ - uint8_t wrtPin = 0x00; - uint8_t wrtStep = 0x00; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - const uint8_t SHIFT_CH1 = 0x00; - const uint8_t SHIFT_INC = 0x05; - const uint8_t SHIFT_DEC = 0x02; - const uint8_t MAX_STEP = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRx1GainCtrlPin()\n"); -#endif - - /* If enable then check for the next otherwise go directly to disable */ - if (enable > 0) - { - /* Error checking for correct step. */ - if ((uint8_t)(incStep > MAX_STEP) || (uint8_t)(decStep > MAX_STEP)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MGCRX1_STEP_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_MGCRX1_STEP_INV_PARAM)); - return MYKONOS_ERR_MGCRX1_STEP_INV_PARAM; - } - - /* Pin configuration assignment*/ - switch (rx1GainIncPin) - { - case MYKGPIO0: - wrtPin |= 0x00; - break; - case MYKGPIO10: - wrtPin |= 0x04; - break; - - default: - return MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM; - } - - switch (rx1GainDecPin) - { - case MYKGPIO1: - wrtPin |= 0x00; - break; - case MYKGPIO11: - wrtPin |= 0x01; - break; - - default: - return MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM; - } - } - - /* Setting increment step. */ - wrtStep = (uint8_t)(incStep<spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, wrtStep, 0xFD, 0); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, wrtPin, 0x0F, 0); - - return error; -} - -/** - * \brief This API function returns the configuration RX1 gain Pin control - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param incStep will contain the step that is used for increment. - * \param decStep will contain the step that is used for decrement. - * \param rx1GainIncPin this will have the pin used for increment. - * \param rx1GainDecPin this will have the pin used for decrement. - * \param enable will contain the enable status for this channel if it is set to 1 then this - * function is enable for this channel, if it is 0 it is not enable - * - * \retval MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM if a null value has been passed to incStep - * \retval MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM if a null value has been passed to decStep - * \retval MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM if a null value has been passed to rx1GainIncPin - * \retval MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM if a null value has been passed to rx1GainDecPin - * \retval MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM if a null value has been passed to enable - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getRx1GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx1GainIncPin, mykonosGpioSelect_t *rx1GainDecPin, uint8_t *enable) -{ - uint8_t readVal = 0x00; - - const uint8_t MASK_GPIO_CH1 = 0x0F; - const uint8_t MASK_EN_CH1 = 0x01; - const uint8_t MASK_STEP_INC = 0xE0; - const uint8_t MASK_STEP_DEC = 0x1C; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRx1GainCtrlPin()\n"); -#endif - - /* Checking for null passed parameters */ - if (incStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM)); - return MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM; - } - - if (decStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM)); - return MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM; - } - - if (rx1GainIncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM)); - return MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM; - } - - if (rx1GainDecPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM)); - return MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM; - } - - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM)); - return MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, &readVal); - readVal = readVal & MASK_GPIO_CH1; - - if (readVal & 0x04) - { - *rx1GainIncPin = MYKGPIO10; - } - else - { - *rx1GainIncPin = MYKGPIO0; - } - - if (readVal & 0x01) - { - *rx1GainDecPin = MYKGPIO11; - } - else - { - *rx1GainDecPin = MYKGPIO1; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, &readVal); - - *enable = readVal & MASK_EN_CH1; - - *incStep = (readVal & MASK_STEP_INC) >> 5; - - *decStep = (readVal & MASK_STEP_DEC) >> 2; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function configures the GPIO inputs for controlling RX gain - * - * This API function configures the GPIO input pin and step size to allow the BBP to control gain changes in Rx2 signal chain. - * A high pulse on the 'rx2GainIncPin' in pin control mode will increment the gain by the value set in incStep'. - * A high pulse on the 'rx2GainDecPin' in pin control mode will decrement the gain by the value set in 'decStep'. - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \param incStep This sets the change (increase) in gain index that is applied when the - * increment gain pin (in MGC pin control mode) is pulsed. - * - * \param decStep This configures the decrement in gain index that should be applied - * when the decrement gain pin (in MGC pin control mode) is pulsed. - * - * \param rx2GainIncPin mykonosGpioSelect_t These bits select the GPIO used as the enable for - * the Rx2 Manual Increment gain input according to the following: - * MYKGPIO3 or MYKGPIO13 - * - * \param rx2GainDecPin mykonosGpioSelect_t These bits select the GPIO used as the enable for - * the Rx2 Manual Decrement gain input according to the following: - * MYKGPIO4 or MYKGPIO14 - * - * \param enable 0 = Disable the gain pin control for Rx2 - * 1 = enable the gain pin control for Rx2 - * - * - * \retval MYKONOS_ERR_MGCRX2_STEP_INV_PARAM if an invalid step size is passed - * \retval MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM if invalid increment pin has been passed - * \retval MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM if invalid decrement pin has been passed - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setRx2GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx2GainIncPin, mykonosGpioSelect_t rx2GainDecPin, uint8_t enable) -{ - uint8_t wrtPin = 0x00; - uint8_t wrtStep = 0x00; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - const uint8_t SHIFT_CH2 = 0x01; - const uint8_t SHIFT_INC = 0x5; - const uint8_t SHIFT_DEC = 0x2; - const uint8_t MAX_STEP = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRx2GainCtrlPin()\n"); -#endif - - /* If enable then check for the next otherwise go directly to disable */ - if (enable > 0) - { - /* Error checking for correct step. */ - if ((uint8_t)(incStep > MAX_STEP) || (uint8_t)(decStep > MAX_STEP)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_MGCRX2_STEP_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_MGCRX2_STEP_INV_PARAM)); - return MYKONOS_ERR_MGCRX2_STEP_INV_PARAM; - } - - /* Pin configuration assignment*/ - switch (rx2GainIncPin) - { - case MYKGPIO3: - wrtPin |= 0x00; - break; - case MYKGPIO13: - wrtPin |= 0x40; - break; - - default: - return MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM; - } - - switch (rx2GainDecPin) - { - case MYKGPIO4: - wrtPin |= 0x00; - break; - case MYKGPIO14: - wrtPin |= 0x10; - break; - - default: - return MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM; - } - } - - /* Setting increment step. */ - wrtStep = (uint8_t)(incStep<spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, wrtStep, 0xFE, 0); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, wrtPin, 0xF0, 0); - - return error; -} - -/** - * \brief This API function returns the configuration RX2 gain Pin control - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param incStep will contain the step that is used for increment. - * \param decStep will contain the step that is used for decrement. - * \param rx2GainIncPin this will have the pin used for increment. - * \param rx2GainDecPin this will have the pin used for decrement. - * \param enable will contain the enable status for this channel if it is set to 1 then this - * function is enable for this channel, if it is 0 it is not enable - * - * \retval MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM if a null value has been passed to incStep - * \retval MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM if a null value has been passed to decStep - * \retval MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM if a null value has been passed to rx1GainIncPin - * \retval MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM if a null value has been passed to rx1GainDecPin - * \retval MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM if a null value has been passed to enable - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getRx2GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx2GainIncPin, mykonosGpioSelect_t *rx2GainDecPin, uint8_t *enable) -{ - uint8_t readVal = 0x00; - - const uint8_t MASK_GPIO_CH2 = 0xF0; - const uint8_t MASK_EN_CH2 = 0x02; - const uint8_t MASK_STEP_INC = 0xE0; - const uint8_t MASK_STEP_DEC = 0x1C; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRx2GainCtrlPin()\n"); -#endif - - /* Checking for null passed parameters */ - if (incStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM)); - return MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM; - } - - if (decStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM)); - return MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM; - } - - if (rx2GainIncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM)); - return MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM; - } - - if (rx2GainDecPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM)); - return MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM; - } - - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM)); - return MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL, &readVal); - readVal = readVal & MASK_GPIO_CH2; - - if (readVal & 0x40) - { - *rx2GainIncPin = MYKGPIO13; - } - else - { - *rx2GainIncPin = MYKGPIO3; - } - - if (readVal & 0x10) - { - *rx2GainDecPin = MYKGPIO14; - } - else - { - *rx2GainDecPin = MYKGPIO4; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG, &readVal); - - *enable = (readVal & MASK_EN_CH2) >> 1; - - *incStep = (readVal & MASK_STEP_INC) >> 5; - - *decStep = (readVal & MASK_STEP_DEC) >> 2; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function set the pins for hybrid gain control - * - * In order to call this function the gain mode should be set to Hybrid. - * The AGC gain change will be controlled with the selected GPIO pin: - * A pulse on the 'rx1GainChangePin' in hybrid pin control will enable the AGC gain change for RX1 - * A pulse on the 'rx2GainChangePin' in hybrid pin control will enable the AGC gain change for RX2 - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param rx1GainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for RX1 channel - * hybrid control are: - * MYKGPIO1 - * MYKGPIO10 - * MYKGPIO11 - * MYKGPIONAN for no GPIO selected - * - * \param rx2GainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for RX2 channel - * hybrid control are: - * MYKGPIO4 - * MYKGPIO10 - * MYKGPIO13 - * MYKGPIONAN for no GPIO selected - * - * \retval MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID if gain control is not hybrid - * \retval MYKONOS_ERR_GPIO_HYBRID_RX1_PIN if invalid pin has been passed for RX1 hybrid gain control. - * \retval MYKONOS_ERR_GPIO_HYBRID_RX2_PIN if invalid pin has been passed for RX2 hybrid gain control. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t rx1GainChangePin, mykonosGpioSelect_t rx2GainChangePin) -{ - uint8_t hybridPinWrite = 0x00; - uint8_t pinRx1 = 0x00; - uint8_t pinRx2 = 0x00; - - const uint8_t HYBRID_RX_PIN_MASK = 0x0F; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxHybridGainChangePin()\n"); -#endif - - /* Check if in Hybrid Mode */ - if (device->rx->rxGainCtrl->gainMode != HYBRID) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID)); - return MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID; - } - - /* Pin configuration assignment for RX1 and RX2 */ - switch (rx1GainChangePin) - { - case MYKGPIO1: - pinRx1 |= 0x00; - break; - case MYKGPIO10: - pinRx1 |= 0x01; - break; - case MYKGPIO11: - pinRx1 |= 0x02; - break; - case MYKGPIONAN: - pinRx1 |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX1_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX1_PIN)); - return MYKONOS_ERR_GPIO_HYBRID_RX1_PIN; - } - - switch (rx2GainChangePin) - { - case MYKGPIO4: - pinRx2 |= 0x00; - break; - case MYKGPIO10: - pinRx2 |= 0x04; - break; - case MYKGPIO13: - pinRx2 |= 0x08; - break; - case MYKGPIONAN: - pinRx2 |= 0x0C; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX2_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX2_PIN)); - return MYKONOS_ERR_GPIO_HYBRID_RX2_PIN; - } - - /* Setting GPIO control for RX1 and RX2 */ - hybridPinWrite = (pinRx1 | pinRx2); - - /* Writing GPIO pin configuration for hybrid mode. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, hybridPinWrite, HYBRID_RX_PIN_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - - - -/** - * \brief This API function gets the pin configuration for hybrid gain control of RX1 and RX2 - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param rx1GainChangePin Will return the GPIO pin used for Rx1 in hybrid gain control. - * \param rx2GainChangePin Will return the GPIO pin used for Rx2 in hybrid gain control. - * - * \retval MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM if a null value has been passed to rx1GainChangePin - * \retval MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM if a null value has been passed to rx2GainChangePin - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1GainChangePin, mykonosGpioSelect_t *rx2GainChangePin) -{ - uint8_t hybridPinRead = 0x00; - uint8_t pinRx1 = 0x00; - uint8_t pinRx2 = 0x00; - mykonosGpioSelect_t rx1Pin = MYKGPIONAN; - mykonosGpioSelect_t rx2Pin = MYKGPIONAN; - - const uint8_t MASK_RX1_PIN = 0x03; - const uint8_t MASK_RX2_PIN = 0x0C; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxHybridGainChangePin()\n"); -#endif - - /* Checking for null passed parameters */ - if (rx1GainChangePin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM; - } - - if (rx2GainChangePin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM; - } - - /* Getting Pin configuration assignment */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, &hybridPinRead); - pinRx1 = hybridPinRead & MASK_RX1_PIN; - pinRx2 = hybridPinRead & MASK_RX2_PIN; - - /* Pin configuration mapping assignment for RX1 and RX2 */ - switch (pinRx1) - { - case 0x00: - rx1Pin = MYKGPIO1; - break; - case 0x01: - rx1Pin = MYKGPIO10; - break; - case 0x02: - rx1Pin = MYKGPIO11; - break; - default: - rx1Pin = MYKGPIONAN; - break; - } - - switch (pinRx2) - { - case 0x00: - rx2Pin = MYKGPIO4; - break; - case 0x04: - rx2Pin = MYKGPIO10; - break; - case 0x08: - rx2Pin = MYKGPIO13; - break; - default: - rx2Pin = MYKGPIONAN; - break; - } - - /* Setting pins to passed pointers */ - *rx1GainChangePin = rx1Pin; - *rx2GainChangePin = rx2Pin; - - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief This API function set the pins for hybrid gain control - * - * In order to call this function the gain mode should be set to Hybrid. - * The AGC gain change will be controlled with the selected GPIO pin: - * A pulse on the 'obsRxGainChangePin' in hybrid pin control will enable the AGC gain change for observation channel - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxGainChangePin GPIO pin that will be used for hybrid gain change control, the available pins for observation channel - * hybrid control are: - * MYKGPIO6 - * MYKGPIO10 - * MYKGPIO17 - * MYKGPIONAN for none selected - * - * \retval MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID if the observation gain mode is not set to Hybrid - * \retval MYKONOS_ERR_GPIO_HYBRID_ORX_PIN if invalid pin has been passed for ORX hybrid gain control. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxGainChangePin) -{ - uint8_t hybridPinWrite = 0x00; - uint8_t pinOrx = 0x00; - - const uint8_t HYBRID_ORX_PIN_MASK = 0x30; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxHybridGainChangePin()\n"); -#endif - - /* Check if in Hybrid Mode */ - if (device->obsRx->orxGainCtrl->gainMode != HYBRID) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID, - getGpioMykonosErrorMessage(MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID)); - return MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID; - } - - /* Pin configuration assignment for RX1 and RX2 */ - switch (obsRxGainChangePin) - { - case MYKGPIO6: - pinOrx |= 0x00; - break; - case MYKGPIO10: - pinOrx |= 0x10; - break; - case MYKGPIO17: - pinOrx |= 0x20; - break; - case MYKGPIONAN: - pinOrx |= 0x30; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_ORX_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_ORX_PIN)); - return MYKONOS_ERR_GPIO_HYBRID_ORX_PIN; - } - - /* Setting GPIO control for observation channel */ - hybridPinWrite = pinOrx; - - /* Writing GPIO pin configuration for hybrid mode. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, hybridPinWrite, HYBRID_ORX_PIN_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function gets the pin configuration for hybrid gain control of observation channel - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxGainChangePin Will return the GPIO pin used for observation channel in hybrid gain control. - * - * \retval MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM if a null value has been passed to obsRxGainChangePin - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxGainChangePin) -{ - uint8_t hybridPinRead = 0x00; - uint8_t pinOrx = 0x00; - mykonosGpioSelect_t orxPin = MYKGPIONAN; - - const uint8_t MASK_ORX_PIN = 0x30; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxHybridGainChangePin()\n"); -#endif - - /* Checking for null passed parameters */ - if (obsRxGainChangePin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM; - } - - /* Getting Pin configuration assignment */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, &hybridPinRead); - pinOrx = hybridPinRead & MASK_ORX_PIN; - - /* Pin configuration mapping assignment for RX1 and RX2 */ - switch (pinOrx) - { - case 0x00: - orxPin = MYKGPIO6; - break; - case 0x10: - orxPin = MYKGPIO10; - break; - case 0x20: - orxPin = MYKGPIO17; - break; - default: - orxPin = MYKGPIONAN; - break; - } - - /* Setting pins to passed pointer */ - *obsRxGainChangePin = orxPin; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function set the pins for sync AGC gain control - * - * In order to call this function the RX gain control should be set to AGC mode. - * The AGC gain sync will be controlled with the selected GPIO pin: - * A pulse on the 'rx1AgcSyncPin' in hybrid pin control will enable the AGC gain sync for RX1 - * A pulse on the 'rx2AgcSyncPin' in hybrid pin control will enable the AGC gain sync for RX2 - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param rx1AgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for RX1 channel are: - * MYKGPIO1 - * MYKGPIO10 - * MYKGPIO11 - * MYKGPIONAN for no GPIO selected - * - * \param rx2AgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for RX2 channel are: - * MYKGPIO4 - * MYKGPIO10 - * MYKGPIO13 - * MYKGPIONAN for no GPIO selected - * - * \retval MYKONOS_ERR_GAIN_CONTROL_NOT_AGC if the RX gain control mode is not set to AGC. - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN if invalid pin has been passed for RX1 AGC sync gain control. - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN if invalid pin has been passed for RX2 AGC sync gain control. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t rx1AgcSyncPin, mykonosGpioSelect_t rx2AgcSyncPin) -{ - uint8_t agcSyncPinWrite = 0x00; - uint8_t pinRx1 = 0x00; - uint8_t pinRx2 = 0x00; - - const uint8_t SYNC_RX_PIN_MASK = 0x0F; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxAgcEnSyncPin()\n"); -#endif - - /* Check if in Hybrid Mode */ - if (device->rx->rxGainCtrl->gainMode != AGC) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAIN_CONTROL_NOT_AGC, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAIN_CONTROL_NOT_AGC)); - return MYKONOS_ERR_GAIN_CONTROL_NOT_AGC; - } - - /* Pin configuration assignment for RX1 and RX2 */ - switch (rx1AgcSyncPin) - { - case MYKGPIO1: - pinRx1 |= 0x00; - break; - case MYKGPIO10: - pinRx1 |= 0x01; - break; - case MYKGPIO11: - pinRx1 |= 0x02; - break; - case MYKGPIONAN: - pinRx1 |= 0x03; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN)); - return MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN; - } - - switch (rx2AgcSyncPin) - { - case MYKGPIO4: - pinRx2 |= 0x00; - break; - case MYKGPIO10: - pinRx2 |= 0x04; - break; - case MYKGPIO13: - pinRx2 |= 0x08; - break; - case MYKGPIONAN: - pinRx2 |= 0x0C; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN)); - return MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN; - } - - /* Setting GPIO control for RX1 and RX2 */ - agcSyncPinWrite = (pinRx1 | pinRx2); - - /* Writing GPIO pin configuration for Sync AGC. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, agcSyncPinWrite, SYNC_RX_PIN_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function gets the GPIO pin configuration for AGC gain sync control of RX1 and RX2 - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param rx1AgcSyncPin Will return the GPIO pin used for RX1 channel AGC gain sync control, - * - * \param rx2AgcSyncPin Will return the GPIO pin used for RX2 channel AGC gain sync control, - * - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM if a null value has been passed to rx1AgcSyncPin - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM if a null value has been passed to rx2AgcSyncPin - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1AgcSyncPin, mykonosGpioSelect_t *rx2AgcSyncPin) -{ - uint8_t agcSyncPinRead = 0x00; - uint8_t pinRx1 = 0x00; - uint8_t pinRx2 = 0x00; - mykonosGpioSelect_t rx1Pin = MYKGPIONAN; - mykonosGpioSelect_t rx2Pin = MYKGPIONAN; - - const uint8_t MASK_RX1_PIN = 0x03; - const uint8_t MASK_RX2_PIN = 0x0C; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxHybridGainChangePin()\n"); -#endif - - /* Checking for null passed parameters */ - if (rx1AgcSyncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM; - } - - if (rx2AgcSyncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM; - } - - /* Getting Pin configuration assignment */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL, &agcSyncPinRead); - pinRx1 = agcSyncPinRead & MASK_RX1_PIN; - pinRx2 = agcSyncPinRead & MASK_RX2_PIN; - - /* Pin configuration mapping assignment for RX1 and RX2 */ - switch (pinRx1) - { - case 0x00: - rx1Pin = MYKGPIO1; - break; - case 0x01: - rx1Pin = MYKGPIO10; - break; - case 0x02: - rx1Pin = MYKGPIO11; - break; - default: - rx1Pin = MYKGPIONAN; - break; - } - - switch (pinRx2) - { - case 0x00: - rx2Pin = MYKGPIO4; - break; - case 0x04: - rx2Pin = MYKGPIO10; - break; - case 0x08: - rx2Pin = MYKGPIO13; - break; - default: - rx2Pin = MYKGPIONAN; - break; - } - - /* Setting pins to passed pointers */ - *rx1AgcSyncPin = rx1Pin; - *rx2AgcSyncPin = rx2Pin; - - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief This API function set the pins for AGC gain Sync control - * - * In order to call this function the gain mode should be set to AGC mode. - * The AGC gain sync will be controlled with the selected GPIO pin: - * A pulse on the 'obsRxGainChangePin' in hybrid pin control will enable the AGC gain change for observation channel - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxAgcSyncPin GPIO pin that will be used for AGC sync gain control, the available pins for observation channel are: - * MYKGPIO6 - * MYKGPIO10 - * MYKGPIO17 - * MYKGPIONAN for none selected - * - * \retval MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC if the observation gain control mode is not set to AGC - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN if invalid pin has been passed for ORX AGC sync gain control. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxAgcSyncPin) -{ - uint8_t agcSyncPinWrite = 0x00; - uint8_t pinOrx = 0x00; - - const uint8_t SYNC_ORX_PIN_MASK = 0x30; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxAgcEnSyncPin()\n"); -#endif - - /* Check if in Hybrid Mode */ - if (device->obsRx->orxGainCtrl->gainMode != AGC) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC)); - return MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC; - } - - /* Pin configuration assignment for observation channel */ - switch (obsRxAgcSyncPin) - { - case MYKGPIO6: - pinOrx |= 0x00; - break; - case MYKGPIO10: - pinOrx |= 0x10; - break; - case MYKGPIO17: - pinOrx |= 0x20; - break; - case MYKGPIONAN: - pinOrx |= 0x30; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN)); - return MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN; - } - - /* Setting GPIO control for observation channel */ - agcSyncPinWrite = pinOrx; - - /* Writing GPIO pin configuration for Sync AGC mode. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, agcSyncPinWrite, SYNC_ORX_PIN_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function gets the pin configuration for AGC Sync gain control of observation channel - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param obsRxAgcSyncPin Will return the GPIO pin used for observation channel AGC gain sync control, - * - * \retval MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM if a null value has been passed to obsRxAgcSyncPin - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxAgcSyncPin) -{ - uint8_t agcSyncPinRead = 0x00; - uint8_t pinOrx = 0x00; - mykonosGpioSelect_t orxPin = MYKGPIONAN; - - const uint8_t MASK_ORX_PIN = 0x30; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxAgcEnSyncPin()\n"); -#endif - - /* Checking for null passed parameters */ - if (obsRxAgcSyncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM)); - return MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM; - } - - /* Getting Pin configuration assignment */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL, &agcSyncPinRead); - pinOrx = agcSyncPinRead & MASK_ORX_PIN; - - /* Pin configuration mapping assignment for observation channel */ - switch (pinOrx) - { - case 0x00: - orxPin = MYKGPIO6; - break; - case 0x10: - orxPin = MYKGPIO10; - break; - case 0x20: - orxPin = MYKGPIO17; - break; - default: - orxPin = MYKGPIONAN; - break; - } - - /* Setting pins to passed pointer */ - *obsRxAgcSyncPin = orxPin; - - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief This API function configures the GPIO inputs for controlling Tx attenuation settings - * - * This allows to control the TX attenuation using GPIO inputs. When a low to high transition is - * applied to the configure GPIO input the attenuation will change by the desire step. - * The stepSize parameter will set the attenuation change applied. - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \param stepSize the step that will increase or decrease the Tx1 channel attenuation. - * This parameter sets the change in Tx attenuation for each increment or decrement signal received in incr/decr mode. - * Step of 1 changes attenuation by 0.05dB. - * - * \param tx1AttenIncPin This parameter is the GPIO pin configuration that will be controlling the increment - * of Tx attenuation. Available pins are: - * Tx1 increment: MYKGPIO4 or MYKGPIO12 - * - * \param tx1AttenDecPin This parameter is the GPIO pin configuration that will be controlling the decrement - * of Tx attenuation. Available pins are: - * Tx1 decrement: MYKGPIO5 or MYKGPIO13 - * - * \param enable 0 = Disable the attenuation pin control for Tx1 - * 1 = enable the attenuation pin control for Tx1 - * - * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. - * - * \retval MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM if an invalid step size is passed - * \retval MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed - * \retval MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM if an invalid channel for TX is passed - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx1AttenIncPin, mykonosGpioSelect_t tx1AttenDecPin, uint8_t enable, uint8_t useTx1ForTx2) -{ - uint8_t wrtPin = 0; - uint8_t tpcMode = 0x0; - uint8_t tpcMaskTx2 = 0x00; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - const uint8_t TX_INCDEC_MASK = 0x1F; - const uint8_t TX_PIN_MASK = 0x0F; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setTx1AttenCtrlPin()\n"); -#endif - - /* If enable then check for the next otherwise go directly to disable */ - if (enable > 0) - { - /* Error checking for correct step. */ - if (stepSize > TX_INCDEC_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM)); - return MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM; - } - - /* Pin configuration assignment for Tx1 increments */ - switch (tx1AttenIncPin) - { - case MYKGPIO4: - wrtPin |= 0x00; - break; - case MYKGPIO12: - wrtPin |= 0x01; - break; - - default: - return MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM; - } - - /* Pin configuration assignment for Tx1 decrements */ - switch (tx1AttenDecPin) - { - case MYKGPIO5: - wrtPin |= 0x00; - break; - case MYKGPIO13: - wrtPin |= 0x04; - break; - - default: - return MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM; - } - - /* Setting TPC mode corresponding to the enable */ - tpcMode = 0x03; - - /* Setting TPC control for Tx2 using Tx1 */ - if (useTx1ForTx2 > 0) - { - tpcMode |= 0x1C; - tpcMaskTx2 = 0x1F; - } - else - { - tpcMaskTx2 = 0x13; - } - } - else - { - /* Setting TPC mode corresponding for no Pin control */ - tpcMode = 0x05; - tpcMaskTx2 = 0x1F; - } - - /* Setting increment step. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, stepSize, TX_INCDEC_MASK, 0); - - /* Set the TPC mode for GPIO control. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, tpcMode, tpcMaskTx2, 0); - - /* Set the GPIO input pin configuration and the step size. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, wrtPin, TX_PIN_MASK, 0); - - return error; -} - -/** - * \brief This API function returns the configuration TX1 attenuation Pin control - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param stepSize will contain the step that is used for increment and decrement. - * \param tx1AttenIncPin this will have the pin used for increment. - * \param tx1AttenDecPin this will have the pin used for decrement. - * \param enable will contain the enable status for this channel if it is set to 1 then this - * function is enable for this channel, if it is 0 it is not enable - * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. - * - * \retval MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM if a null value has been passed to stepSize - * \retval MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM if a null value has been passed to tx1AttenIncPin - * \retval MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM if a null value has been passed to tx1AttenDecPin - * \retval MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM if a null value has been passed to enable - * \retval MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM if a null value has been passed to useTx1ForTx2 - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx1AttenIncPin, mykonosGpioSelect_t *tx1AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2) -{ - uint8_t readVal = 0x00; - uint8_t en = 0x00; - - const uint8_t MASK_TPC_CH1 = 0x03; - const uint8_t MASK_TPC_CH1FCH2 = 0x10; - const uint8_t MASK_TPC_STEP = 0x1F; - const uint8_t MASK_TPC_GPIO_CH1 = 0x0F; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTx1AttenCtrlPin()\n"); -#endif - - /* Checking for null passed parameters */ - if (stepSize == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM)); - return MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM; - } - - if (tx1AttenIncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM)); - return MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM; - } - - if (tx1AttenDecPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM)); - return MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM; - } - - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM)); - return MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM; - } - - if (useTx1ForTx2 == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM)); - return MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, &readVal); - readVal = readVal & MASK_TPC_GPIO_CH1; - - if (readVal & 0x01) - { - *tx1AttenIncPin = MYKGPIO12; - } - else - { - *tx1AttenIncPin = MYKGPIO4; - } - - if (readVal & 0x04) - { - *tx1AttenDecPin = MYKGPIO13; - } - else - { - *tx1AttenDecPin = MYKGPIO5; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, &readVal); - - en = readVal & MASK_TPC_CH1; - - *enable = (en == MASK_TPC_CH1) ? 1 : 0; - - *useTx1ForTx2 = readVal & MASK_TPC_CH1FCH2; - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, &readVal); - - *stepSize = readVal & MASK_TPC_STEP; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This API function configures the GPIO inputs for controlling Tx attenuation settings - * - * This allows to control the TX attenuation using GPIO inputs. when a low to high transition is - * applied to the configure GPIO input the attenuation will change by the desire step. - * The stepSize parameter will set the attenuation change applied. - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - * - * \param device is structure pointer to the Mykonos data structure containing settings - * - * \param stepSize the step that will increase or decrease the Tx2 channel attenuation. - * This parameter sets the change in Tx attenuation for each increment or decrement signal received in incr/decr mode. - * Step of 1 changes attenuation by 0.05dB. - * - * \param tx2AttenIncPin This parameter is the GPIO pin configuration that will be controlling the increment - * of Tx attenuation. Available pins are: - * Tx2 increment: MYKGPIO6 or MYKGPIO14 - * - * \param tx2AttenDecPin This parameter is the GPIO pin configuration that will be controlling the decrement - * of Tx attenuation. Available pins are: - * Tx2 decrement: MYKGPIO7 or MYKGPIO15 - * - * \param enable 0 = Disable the attenuation pin control for Tx2 - * 1 = enable the attenuation pin control for Tx2 - * - * \retval MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM if an invalid step size is passed - * \retval MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed - * \retval MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM if an invalid channel for TX is passed - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx2AttenIncPin, mykonosGpioSelect_t tx2AttenDecPin, uint8_t enable) -{ - uint8_t wrtPin = 0; - uint8_t tpcMode = 0x0; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - - const uint8_t TX_INCDEC_MASK = 0x1F; - const uint8_t TX2_TPC_MASK = 0x1C; - const uint8_t TX2_WRTPIN = 0xf0; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setTx2AttenCtrlPin()\n"); -#endif - - /* If enable then check for the next otherwise go directly to disable */ - if (enable > 0) - { - /* Error checking for correct step. */ - if (stepSize > TX_INCDEC_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM)); - return MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM; - } - - /* Pin configuration assignment for Tx2 increments */ - switch (tx2AttenIncPin) - { - case MYKGPIO6: - wrtPin |= 0x00; - break; - case MYKGPIO14: - wrtPin |= 0x10; - break; - - default: - return MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM; - } - - /* Pin configuration assignment for Tx2 decrements */ - switch (tx2AttenDecPin) - { - case MYKGPIO7: - wrtPin |= 0x00; - break; - case MYKGPIO15: - wrtPin |= 0x40; - break; - - default: - return MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM; - } - - /* Setting TPC mode corresponding to the enable */ - tpcMode = 0x0C; - } - else - { - /* Setting TPC mode corresponding for no Pin control */ - tpcMode = 0x05; - } - - /* Setting increment step. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, stepSize, TX_INCDEC_MASK, 0); - - /* Set the TPC mode for GPIO control. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, tpcMode, TX2_TPC_MASK, 0); - - /* Set the GPIO input pin configuration and the step size. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, wrtPin, TX2_WRTPIN, 0); - - return error; -} - -/** - * \brief This API function returns the configuration TX2 attenuation Pin control - * - * - * Dependencies - * - device->spiSettings - * - device->spiSettings->chipSelectIndex - - * - * \param device is structure pointer to the Mykonos data structure containing settings - * \param stepSize will contain the step that is used for increment and decrement. - * \param tx2AttenIncPin this will have the pin used for increment. - * \param tx2AttenDecPin this will have the pin used for decrement. - * \param enable will contain the enable status for this channel if it is set to 1 then this - * function is enable for this channel, if it is 0 it is not enable - * \param useTx1ForTx2 is used to return if TX1 settings are used for TX2 channel. - * - * \retval MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM if a null value has been passed to stepSize - * \retval MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM if a null value has been passed to tx1AttenIncPin - * \retval MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM if a null value has been passed to tx1AttenDecPin - * \retval MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM if a null value has been passed to enable - * \retval MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM if a null value has been passed to useTx1ForTx2 - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx2AttenIncPin, mykonosGpioSelect_t *tx2AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2) -{ - uint8_t readVal = 0x00; - uint8_t en = 0x00; - - const uint8_t MASK_TPC_CH2 = 0x0C; - const uint8_t MASK_TPC_CH1FCH2 = 0x10; - const uint8_t MASK_TPC_STEP = 0x1F; - const uint8_t MASK_TPC_GPIO_CH2 = 0xF0; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTx2AttenCtrlPin()\n"); -#endif - - /* Checking for null passed parameters */ - if (stepSize == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM)); - return MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM; - } - - if (tx2AttenIncPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM)); - return MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM; - } - - if (tx2AttenDecPin == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM)); - return MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM; - } - - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM)); - return MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM; - } - - if (useTx1ForTx2 == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM)); - return MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_GPIO_CFG, &readVal); - readVal = readVal & MASK_TPC_GPIO_CH2; - - if (readVal & 0x10) - { - *tx2AttenIncPin = MYKGPIO14; - } - else - { - *tx2AttenIncPin = MYKGPIO6; - } - - if (readVal & 0x40) - { - *tx2AttenDecPin = MYKGPIO15; - } - else - { - *tx2AttenDecPin = MYKGPIO7; - } - - /* Getting Pin configuration assignment*/ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_TPC_CONFIG, &readVal); - - en = readVal & MASK_TPC_CH2; - - *enable = (en == MASK_TPC_CH2) ? 1 : 0; - - *useTx1ForTx2 = readVal & MASK_TPC_CH1FCH2; - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TX_INCR_DECR_WORD, &readVal); - - *stepSize = readVal & MASK_TPC_STEP; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets the Mykonos low voltage GPIO output pins level - * - * This function will only affect the GPIO pins that have their OE direction set to output and - * that have the correct source control for the nibbles in GPIO_BITBANG_MODE - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioPinLevel bit per GPIO pin, level to output for each GPIO pin. 0 = low output, 1= high output - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioPinLevel(mykonosDevice_t *device, uint32_t gpioPinLevel) -{ - - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioPinLevel()\n"); -#endif - - /* writing GPIO configuration registers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_7_0, (gpioPinLevel & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_15_8, ((gpioPinLevel >> 8) & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_18_16, ((gpioPinLevel >> 16) & 0x07)); - - /* Return */ - return error; -} - -/** - * \brief Reads the Mykonos low voltage GPIO pin levels and returns their contents in a single 32-bit word - * - * The GPIO pins that are set to be inputs in BITBANG mode will read back and be returned - * in the gpioPinLevel parameter. The return value is a bit per pin. GPIO 0 returns on bit 0 of - * the gpioPinLevel parameter. A logic low level returns a 0, a logic high level returns a 1. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioPinLevel Input Gpio pin levels read back on the pins assigned as inputs (bit per pin) - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_READGPIOSPI_NULL_PARM The pointer passed for gpioPinLevel parameter is NULL - */ -mykonosGpioErr_t MYKONOS_getGpioPinLevel(mykonosDevice_t *device, uint32_t *gpioPinLevel) -{ - uint8_t readBytes[3] = {0, 0, 0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioPinLevel()\n"); -#endif - - if (gpioPinLevel == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READGPIOSPI_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_READGPIOSPI_NULL_PARM)); - return MYKONOS_ERR_READGPIOSPI_NULL_PARM; - } - - /* reading the registers into three-byte array */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_15_8, &readBytes[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_READ_18_16, &readBytes[2]); - - /* performing concatenation and assigning value to gpio1v8SpiRead */ - *gpioPinLevel = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos GPIO pin output levels for BITBANG mode - * - * This function allows reading the value that the GPIO output pins are - * set to drive out the pins. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioPinSetLevel is a unit32_t pointer which contains the level of each GPIO pin (bit per pin) - * - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM gpioPinSetLevel pointer is NULL in function parameter - * - */ -mykonosGpioErr_t MYKONOS_getGpioSetLevel(mykonosDevice_t *device, uint32_t *gpioPinSetLevel) -{ - uint8_t readBytes[3] = {0, 0, 0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSetLevel()\n"); -#endif - - if (gpioPinSetLevel == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM)); - return MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM; - } - - /* reading the registers into two-byte array */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_15_8, &readBytes[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_SPI_SRC_18_16, &readBytes[2]); - - /* performing concatenation and assigning value to gpioPinSetLevel */ - *gpioPinSetLevel = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); - - return MYKONOS_ERR_GPIO_OK; -} - - - -/** - * \brief Sets the General Purpose (GP) interrupt register bit mask to enable interrupt sources to assert the GP Interrupt pin - * - * Mykonos has a single output pin called General Purpose Interrupt that asserts to a logic high level - * when certain events occur. The events that cause the GP Interrupt pin to assert are user - * selectable by setting the gpMask parameter in this function. Device default is mask = x1FF = ignore - * all events. The ARM Error interrupt can not be ignored and can always assert the GP interrupt pin. - * - * gpMask | Bit description - * ------------|------------ - * [0] | TXPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore TXPLL LOCK - * [1] | RXPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore RXPLL LOCK - * [2] | SNIFFER PLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore SNIFFER PLL LOCK - * [3] | CALIBRATION PLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore CALIBRATION PLL LOCK - * [4] | CLKPLL LOCK - 0 = allow PLL unlocking to assert GP Interrupt pin, 1 = ignore CLKPLL LOCK - * [5] | 0 = Allow JESD204 deframer interrupt to assert GP Interrupt pin, 1 = ignore JESD204 deframer interrupt - * [6] | Tx1 PA protection - 0 = allow Tx1 PA protection event to assert GP Interrupt pin, 1 = ignore Tx1 PA protection - * [7] | Tx2 PA protection - 0 = allow Tx2 PA protection event to assert GP Interrupt pin, 1 = ignore Tx2 PA protection - * [8] | Mykonos ARM Watchdog - 0 = allow Mykonos ARM Watchdog timeout to assert GP Interrupt pin, 1 = ignore Watchdog timeout event - * [15-9] | Reserved for future use - * - * Dependencies - * - device->spiSettings - * - * \param device Pointer to the device settings structure - * \param gpMask Value is passed to enable one or more general purpose interrupt sources - * (1=ignore source, 0 = enable source interrupt to GP Interrupt pin) - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_INV_GP_INT_MASK_PARM if invalid interrupt mask is passed - */ -mykonosGpioErr_t MYKONOS_configGpInterrupt(mykonosDevice_t *device, uint16_t gpMask) -{ - const uint16_t GP_INT_VALID_MASK = 0x1FF; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_configGpInterrupt()\n"); -#endif - - /* checking for valid mask setting */ - if (gpMask & ~GP_INT_VALID_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_GP_INT_MASK_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_INV_GP_INT_MASK_PARM)); - return MYKONOS_ERR_INV_GP_INT_MASK_PARM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_MASK_1, (gpMask & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_MASK_0, ((gpMask >> 8) & 0x01)); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the General Purpose (GP) interrupt status to determine what caused the GP Interrupt pin to assert - * - * When the BBIC detects a rising edge on the General Purpose Interrupt pin, this function - * allows the BBIC to determine the source of the interrupt. The value returned in the status parameter - * will show one or more sources for the interrupt based on the following table. - * - * The PLL unlock bits are not sticky. They will follow the current status of the PLLs. If the PLL relocks, the - * status bit will clear as well. The GP Interrupt pin is the logical OR of all the sources. When all the status - * bits are low, the GP Interrupt pin will be low. The status word readback will show the current value - * for all interrupt sources, even if they are disabled by the masked. However, the GP Interrupt pin will only assert - * for the enabled sources. - * - * status | Bit description - * ------------|------------ - * [0] | 1 = TXPLL UNLOCK - * [1] | 1 = RXPLL UNLOCK - * [2] | 1 = SNIFFER PLL UNLOCK - * [3] | 1 = CALIBRATION PLL UNLOCK - * [4] | 1 = CLK PLL UNLOCK - * [5] | 1 = JESD204 deframer interrupt occurred - * [6] | 1 = Tx1 PA protection event - * [7] | 1 = Tx2 PA protection event - * [8] | 1 = Mykonos ARM Watchdog timeout - * [9] | 1 = ARM interrupt occurred - * [15-10] | Reserved for future use - * - * Dependencies - * - device->spiSettings - * - * \param device Pointer to the device settings structure - * \param status parameter to return the IRQ source(s) that caused the GP Interrpt pin to assert. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM if null *status pointer is passed - */ -mykonosGpioErr_t MYKONOS_readGpInterruptStatus(mykonosDevice_t *device, uint16_t *status) -{ - uint8_t readStatus1 = 0; - uint8_t readStatus0 = 0; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readGpInterruptStatus()\n"); -#endif - /* checking for null pointer */ - if (status == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM)); - return MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_READ_1, &readStatus1); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GP_INTERRUPT_READ_0, &readStatus0); - - /* PLL Lock status bits are high when locked, invert to match up with other bits */ - *status = ((((uint16_t)(readStatus1) & 0xE0U) | ((~(uint16_t)(readStatus1)) & 0x1F)) | (((uint16_t)(readStatus0) & 0x0003) << 8)) ; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets the input and output GPIO pin selections for ARM related signals. - * - * The BBP should not have to call this as it will automatically be setup during the - * MYKONOS_loadArmFromBinary() function call. If the BBP wishes to change the GPIO - * assignments this function can be called again to change the configuration while - * the ARM is in the radioOff state. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->armGpio : all members in structure - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SET_ARMGPIO_INV_POINTER device->auxIo->armGpio pointer is null - * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID Invalid ARM GPIO pin signal ID - * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN Invalid GPIO pin selected for ARM output (valid 0-15 + output enable in bit[4]) - * \retval MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR ARM returned error setting GPIO pins - */ -mykonosGpioErr_t MYKONOS_setArmGpioPins(mykonosDevice_t *device) -{ - uint8_t i = 0; - uint8_t gpioConfig[3] = {0}; - uint8_t signalId[12] = {ORX_TRIGGER_SIGNALID, ORX_MODE_0_SIGNALID, ORX_MODE_1_SIGNALID, ORX_MODE_2_SIGNALID, RX1_ENABLE_ACK_SIGNALID, - RX2_ENABLE_ACK_SIGNALID, TX1_ENABLE_ACK_SIGNALID, TX2_ENABLE_ACK_SIGNALID, ORX1_ENABLE_ACK_SIGNALID, ORX2_ENABLE_ACK_SIGNALID, - SRX_ENABLE_ACK_SIGNALID, TX_OBS_SELECT_SIGNALID}; - uint32_t timeoutMs = 0; - uint8_t cmdStatusByte = 0; - uint32_t gpioOe = 0; - uint32_t gpioUsedMask = 0; - mykonosGpioErr_t retval = MYKONOS_ERR_GPIO_OK; - - const uint8_t GPIO_CTRL_OBJECTID = 0x60; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setArmGpioPins()\n"); -#endif - - if (device->auxIo->armGpio == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_INV_POINTER, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_INV_POINTER)); - return MYKONOS_ERR_SET_ARMGPIO_INV_POINTER; - } - - /* Write ARM set command to setup which ARM signals are using which GPIO pins */ - /* Setup input pins for ORX_MODE[2:0] and ORX_MODE_Trigger if orx is in pin mode */ - for(i = 0; i < sizeof(signalId); i++) - { - gpioConfig[0] = GPIO_CTRL_OBJECTID; - gpioConfig[1] = signalId[i]; - - switch(signalId[i]) - { - case ORX_TRIGGER_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxTriggerPin; break; - case ORX_MODE_0_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode0Pin; break; - case ORX_MODE_1_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode1Pin; break; - case ORX_MODE_2_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orxMode2Pin; break; - case RX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->rx1EnableAck; break; - case RX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->rx2EnableAck; break; - case TX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->tx1EnableAck; break; - case TX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->tx2EnableAck; break; - case ORX1_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orx1EnableAck; break; - case ORX2_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->orx2EnableAck; break; - case SRX_ENABLE_ACK_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->srxEnableAck; break; - case TX_OBS_SELECT_SIGNALID: gpioConfig[2] = device->auxIo->armGpio->txObsSelect; break; - default: - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID)); - return MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID; - } - } - - if (gpioConfig[2] > 0x1F) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN)); - return MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN; - } - - /* if output signal */ - if ((signalId[i] >= RX1_ENABLE_ACK_SIGNALID) && (gpioConfig[2] != 0)) - { - gpioOe |= (uint32_t)(((gpioConfig[2] >> 4) & 0x01) << (gpioConfig[2] & 0x0F)); /* 1 = output */ - gpioUsedMask |= (uint32_t)(1 << (gpioConfig[2] & 0x0F)); - } - - /* if input signal and orx Pin mode enabled - currently only input pins are orx pin mode control */ - if ((signalId[i] < RX1_ENABLE_ACK_SIGNALID) && (device->auxIo->armGpio->orxPinMode > 0)) - { - gpioUsedMask |= (1 << (gpioConfig[2] & 0x1F)); - } - - retval = (mykonosGpioErr_t)MYKONOS_sendArmCommand(device, MYKONOS_ARM_SET_OPCODE, &gpioConfig[0], sizeof(gpioConfig)); - if (retval != MYKONOS_ERR_GPIO_OK) - { - return retval; - } - - timeoutMs = 1000; - - if (( retval = (mykonosGpioErr_t)MYKONOS_waitArmCmdStatus(device, MYKONOS_ARM_SET_OPCODE, timeoutMs, &cmdStatusByte)) != MYKONOS_ERR_GPIO_OK) - { - return retval; - } - - if (cmdStatusByte > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR)); - return MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR; - } - } - - /* Mykonos SPI regs to set GPIO OE direction only for pins used by ARM */ - if ((retval = MYKONOS_setGpioOe(device, gpioOe, gpioUsedMask)) != MYKONOS_ERR_GPIO_OK) - { - return retval; - } - - /* if any output pins enabled, write GPIO nibble source control. ARM outputs only allowed on GPIO[15:0]*/ - if (gpioOe & 0x000F) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, 0x09, 0x0F, 0); - } - - if (gpioOe & 0x00F0) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, 0x09, 0xF0, 4); - } - - if (gpioOe & 0x0F00) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, 0x09, 0x0F, 0); - } - - if (gpioOe & 0xF000) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, 0x09, 0xF0, 4); - } - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets up the auxiliary ADC - * - * This function configures the AuxADC with the requested decimation. The AuxADC clock is set as close - * as possible to 40MHz. The AuxADC conversion time = (1/40Mhz) * decimation, where the decimation ranges - * from 256 AuxADC clock cycles to 32768 AuxADc clock cycles. - * - * Note: The AuxADC is intended for relative measurements. Two back to back measurements can allow a delta - * measurement with 12bit resolution. If absolute measurements are required, an accurate - * reference should be first measured on AuxADC0 input and used to calibrate the offset/gain error of the AuxADC. - * The reference would need to be measured before each measurement to account for measurement variations caused - * by the transmitter/receiver transients as other circuits in the device are being powered up/down. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device Pointer to the device settings structure - * \param adcDecimation ADC decimation factor (0-7). Decimates by 256 * 2^(adcDecimation) ADC clock cycles. - * \param enable Stop/run ADC (0/1) - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SETUPAUXADC_INV_VCODIV CLKPLL VCO divider is invalid - Check CLKPLL setup - * \retval MYKONOS_ERR_INV_AUX_ADC_DEC_PARM AuxADC decimation out of range (valid 0-7) - */ -mykonosGpioErr_t MYKONOS_setupAuxAdcs(mykonosDevice_t *device, uint8_t adcDecimation, uint8_t enable) -{ - uint32_t hsDigClk_kHz = 0; - uint32_t auxAdcDiv = 0; - uint32_t auxAdcClk_kHz = 40000; - uint32_t vcoDiv = (uint32_t)device->clocks->clkPllVcoDiv; - uint8_t vcoDivTimes10 = 10; - - const uint8_t AUXADC_POWER_BIT_MASK = 0x80; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupAuxAdcs()\n"); -#endif - - if (enable == 0) - { - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0, 0xCF); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, 0x01); - - return MYKONOS_ERR_GPIO_OK; - } - else - { - switch(vcoDiv) - { - case VCODIV_1: - vcoDivTimes10 = 10; - break; - case VCODIV_1p5: - vcoDivTimes10 = 15; - break; - case VCODIV_2: - vcoDivTimes10 = 20; - break; - case VCODIV_3: - vcoDivTimes10 = 30; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXADC_INV_VCODIV, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXADC_INV_VCODIV)); - return MYKONOS_ERR_SETUPAUXADC_INV_VCODIV; - } - - hsDigClk_kHz = (device->clocks->clkPllVcoFreq_kHz / vcoDivTimes10 / device->clocks->clkPllHsDiv) * 10; - auxAdcDiv = ((hsDigClk_kHz / 2) / (auxAdcClk_kHz)) - 1; - - if (auxAdcDiv > 63) - { - auxAdcDiv = 63; - } - - if (adcDecimation > 0x07) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AUX_ADC_DEC_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_INV_AUX_ADC_DEC_PARM)); - return MYKONOS_ERR_INV_AUX_ADC_DEC_PARM; - } - - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE, (uint8_t)(auxAdcDiv)); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, (uint8_t)((adcDecimation << 1))); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, 0x00); /* Set AuxADC select to AuxADC0 */ - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0, 0, AUXADC_POWER_BIT_MASK, 7); - - /* Set Clock enable bit to latch divider */ - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE, (uint8_t)(auxAdcDiv | 0x80)); - } - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets the selected channel of the auxiliary ADC - * - * After setting the AuxADC channel, wait at least 1 AuxADC conversion time before - * reading back the AuxADC value. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param auxAdcChannel desired Aux ADC input(0-4 and 16 = temperature sensor) - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM Invalid AuxADC channel (valid 0-4 and 16) - */ -mykonosGpioErr_t MYKONOS_setAuxAdcChannel(mykonosDevice_t *device, mykonosAuxAdcChannels_t auxAdcChannel) -{ - uint8_t currentAuxAdcChan = 0x00; - - const uint8_t CHANNEL_MASK = 0x17; - const uint8_t POWER_UP_AUXADC = 0x00; - const uint8_t POWER_DOWN_AUXADC = 0x01; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setAuxAdcChannel()\n"); -#endif - - if (((uint8_t)auxAdcChannel & ~CHANNEL_MASK) > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM)); - return MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM; - } - - /* Read current selected channel, if different power down AUXADC and change AUXADC */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, ¤tAuxAdcChan); - if (currentAuxAdcChan != (uint8_t)auxAdcChannel) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, POWER_DOWN_AUXADC, 0x01, 0); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_SEL, ((auxAdcChannel & MYK_AUXADC_0_DIV2) ? 0: auxAdcChannel)); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, POWER_UP_AUXADC, 0x01, 0); - } - - /* Invalid AuxADC channel, the only valid channel for external ref is channel 0 */ - if (auxAdcChannel == MYK_AUXADC_0_DIV2) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1, 0x01, 0x04, 2); - } - else if (auxAdcChannel == MYK_AUXADC_0) - { - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1, 0x00, 0x04, 2); - } - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads from the selected channel of the auxiliary ADC - * - * Before using this function to read back the AuxADC value of the - * currently selected AuxADC, make sure that at least 1 conversion time - * of the ADC has passed since setting the AuxADC channel. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param adcCode is a pointer for return of the 12bit ADC read value - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_READAUXADC_NULL_PARAM Function parameter adcCode is a NULL pointer - */ -mykonosGpioErr_t MYKONOS_readAuxAdc(mykonosDevice_t *device, uint16_t *adcCode) -{ - uint8_t adcNibble = 0; - - const uint8_t AUXADC_LOCK_BIT_MASK = 0x80; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readAuxAdcs()\n"); -#endif - - if (adcCode == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READAUXADC_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_READAUXADC_NULL_PARAM)); - return MYKONOS_ERR_READAUXADC_NULL_PARAM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_AUX_ADC_CFG, 1, AUXADC_LOCK_BIT_MASK, 7); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_READ_MSB, &adcNibble); - *adcCode = adcNibble << 4; - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_AUX_ADC_READ_LSB, &adcNibble); - *adcCode |= (adcNibble & 0x0F); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets up the 10 AuxDACs on the Mykonos device. - * - * This function uses the configuration in the Mykonos device data structure AuxIO substructure to - * setup which of the ten AuxDACs are enabled, their slope, Vref(mid point) and their initial DAC code. - * - * This function can be called any time after MYKONOS_initialize() to reconfigure, enable, disable the - * different AuxDAC outputs. The AuxDACs are used in manual control mode. After calling this setup - * function, it is possible to change a particular AuxDAC code by calling the writeAuxDac() function. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->auxDacEnable: 1= enabled, 0 = disabled - * - device->auxIo->auxDacSlope[i]: 0 = 1.404mv/code, 1= 0.702mV/code - * - device->auxIo->auxDacVref: 0 = 1v midpoint, 1 = 1.5v midpoint, 2 = 2v midpoint, 3 = 2.5v midpoint - * - device->auxIo->auxDacValue[i]: 10bit DAC code (0-1023) - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM device->auxIo structure has a NULL pointer - * \retval MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE auxDAC code is out of range (valid 0-1023) - */ -mykonosGpioErr_t MYKONOS_setupAuxDacs(mykonosDevice_t *device) -{ - uint8_t i = 0; /* for loop index */ - uint8_t auxDacConfig = 0 ; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupAuxDacs()\n"); -#endif - - if (device->auxIo == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM)); - return MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_5_0, 0x3F); /* Enable Manual AuxDAC control for all AuxDACs[5:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_9_6, 0x0F); /* Enable Manual AuxDAC control for all AuxDACs[9:6] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0, 0x3F); /* Power down all AuxDACs[5:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6, 0x0F); /* Power down all AuxDACs[9:6] */ - - for (i = 0; i < 10; i++) - { - /* If auxDac enabled, setup AuxDAC configuration */ - if ((device->auxIo->auxDacEnable >> i) & 0x01) - { - if (device->auxIo->auxDacValue[i] > 1023) - { - device->auxIo->auxDacValue[i] = 1023; /* clip value to max */ - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE)); - error = MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE; /* Complete AuxDAC configuration before returning error code */ - } - - auxDacConfig = 0x00; /* initialize config variable */ - - if (device->auxIo->auxDacSlope[i] > 0) - { - auxDacConfig = 0x40; /* bit [6] sets the slope */ - } - - auxDacConfig |= ((device->auxIo->auxDacVref[i] & 0x03) << 4); - - /* Write AuxDAC config and DAC code */ - CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (i * 2)), (auxDacConfig | ((device->auxIo->auxDacValue[i] >> 8) & 0x0F))); - CMB_SPIWriteByte(device->spiSettings, (MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (i * 2 ) + 1), (device->auxIo->auxDacValue[i] & 0xFF)); - } - } - - /* Write enable bit to latch DAC codes into DACs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL, 0x01); - - /* Power up selected AuxDacs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0, (~device->auxIo->auxDacEnable & 0x3F)); /* Power up enabled AuxDACs[5:0] */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6, (((uint16_t)(~device->auxIo->auxDacEnable) >> 6) & 0x0F)); /* Power up enabled AuxDACs[9:6] */ - - return error; -} - -/** - * \brief Writes the current AuxDAC code for a particular AuxDAC - * - * This function updates the 10bit code that controls the AuxDAC output voltage. - * The auxDacCode is updated for the specified auxDAC. Also the auxDacCode is written - * to the device data structure for future reference. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->auxDacValue[i] - * - * \param device is a pointer to the device settings structure - * \param auxDacIndex AuxDAC to set the DAC code for (0-9) - * \param auxDacCode DAC code to update the AuxDAC to. Sets the output voltage of the DAC (valid 0-1023) - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE AuxDac code invalid (valid 0-1023) - * \retval MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX AuxDAC index out of range (valid 0-9) - * \retval MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO device->auxIo has NULL pointer - */ -mykonosGpioErr_t MYKONOS_writeAuxDac(mykonosDevice_t *device, uint8_t auxDacIndex, uint16_t auxDacCode) -{ - uint16_t auxDacAddr = 0; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_writeAuxDac()\n"); -#endif - - if (auxDacCode > 1023) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE, - getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE)); - return MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE; - } - - if (auxDacIndex > 9) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX, - getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX)); - return MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX; - } - - if (device->auxIo == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO, - getGpioMykonosErrorMessage(MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO)); - return MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO; - } - - device->auxIo->auxDacValue[auxDacIndex] = auxDacCode; - - auxDacAddr = MYKONOS_ADDR_AUXDAC_0_WORD_MSB + (auxDacIndex * 2); - - /* Write AuxDAC config and DAC code */ - CMB_SPIWriteField(device->spiSettings, auxDacAddr, (auxDacCode >> 8), 0x0F, 0); - CMB_SPIWriteByte(device->spiSettings, (auxDacAddr + 1), (auxDacCode & 0xFF)); - - /* Write enable bit to latch DAC codes into DACs */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL, 0x01); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Sets the Mykonos low voltage GPIO configuration registers - * - * Sets the low voltage GPIO pin direction for each low voltage GPIO pin and - * sets the source control mode (feature) for each group of 4 GPIO pins. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio - all members - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER device->auxIo->gpio pointer is NULL - * \retval MYKONOS_ERR_SET_GPIO_1V8_INV_MODE gpio structure members have invalid enum value for the GPIO source control mode. - */ -mykonosGpioErr_t MYKONOS_setupGpio(mykonosDevice_t *device) -{ - uint32_t srcWrite = 0x000000; - uint32_t oEnMask = 0x7FFFF; - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupGpio()\n"); -#endif - - if (device->auxIo->gpio == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER)); - return MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER; - } - - /* write GPIO pin direction registers */ - if ((error = MYKONOS_setGpioOe(device, device->auxIo->gpio->gpioOe, oEnMask)) != MYKONOS_ERR_GPIO_OK) - { - return error; - } - - /* write GPIO source control mode */ - if (((uint8_t)device->auxIo->gpio->gpioSrcCtrl3_0 > 15) || ((uint8_t)device->auxIo->gpio->gpioSrcCtrl7_4 > 15) || - ((uint8_t)device->auxIo->gpio->gpioSrcCtrl11_8 > 15) || ((uint8_t)device->auxIo->gpio->gpioSrcCtrl15_12 > 15) || - ((uint8_t)device->auxIo->gpio->gpioSrcCtrl18_16 > 15)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_1V8_INV_MODE, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_1V8_INV_MODE)); - return MYKONOS_ERR_SET_GPIO_1V8_INV_MODE; - } - - srcWrite = (uint32_t)device->auxIo->gpio->gpioSrcCtrl3_0 + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl7_4 << 4) + - ((uint32_t)device->auxIo->gpio->gpioSrcCtrl11_8 << 8) + ((uint32_t)device->auxIo->gpio->gpioSrcCtrl15_12 << 12) + - ((uint32_t)device->auxIo->gpio->gpioSrcCtrl18_16 << 16); - - error = MYKONOS_setGpioSourceCtrl(device, srcWrite); - - return error; -} - -/** - * \brief Sets the Mykonos low voltage GPIO output pins direction - * - * This function will set the GPIO direction given by the passed parameter, - * the direction can be either output or input. The gpioUsedMask parameter - * allows the function to only affect the GPIO pins of interest. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio->gpioOe - * - * \param device is a pointer to the device settings structure - * \param gpioOutEn (valid range 0 - 0x07FFFF), bit per GPIO pin, the direction is - * - * gpioOutEn[bit] | GPIO[bit] direction - * ----------------|------------------- - * 0 | input - * 1 | output - * - * \param gpioUsedMask Mask used to control which Oe bits are set/cleared. If - * mask bit =1, that bit will be modified by gpioOutEn bit - * - * \retval MYKONOS_ERR_GPIO_OE_INV_PARAM If the Output enable parameter is invalid - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioOe(mykonosDevice_t *device, uint32_t gpioOutEn, uint32_t gpioUsedMask) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - - const uint32_t GPIO_OE_MASK = 0x7FFFF; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioOe()\n"); -#endif - - /* Error checking for correct number of GPIOs available. */ - if (gpioOutEn > GPIO_OE_MASK ) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OE_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_OE_INV_PARAM)); - return MYKONOS_ERR_GPIO_OE_INV_PARAM; - } - - /* Mykonos SPI regs to set GPIO OE direction */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_7_0, (gpioOutEn & 0xFF), (gpioUsedMask & 0xFF), 0); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_15_8, ((gpioOutEn >> 8) & 0xFF), ((gpioUsedMask >> 8) & 0xFF), 0); - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_18_16, ((gpioOutEn >> 16) & 0xFF), ((gpioUsedMask >> 16) & 0xFF), 0); - - /* Updating gpioConfig->gpioSetup->gpioOe output enable */ - if ((error = MYKONOS_getGpioOe(device, &gpioOutEn)) != MYKONOS_ERR_GPIO_OK) - { - return error; - } - - device->auxIo->gpio->gpioOe = gpioOutEn; - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Gets the Mykonos low voltage GPIO output pins direction - * - * This function will get the GPIO direction currently set in the device, - * the direction can be either output or input. The return gpioOutEn function - * parameter returns a bit per GPIO pin. 1 = output from the Mykonos Device, - * 0 = input into the Mykonos device. - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param *gpioOutEn a pointer to the data to be returned with the output enable reading - * - * gpioOutEn[bit] | GPIO[bit] direction - * ----------------|------------------- - * 0 | input - * 1 | output - * - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETGPIO_OE_NULL_PARM gpioOutEn function parameter is NULL - */ -mykonosGpioErr_t MYKONOS_getGpioOe(mykonosDevice_t *device, uint32_t *gpioOutEn) -{ - uint8_t readBytes[3] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioOe()\n"); -#endif - - if (gpioOutEn == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO_OE_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO_OE_NULL_PARM)); - return MYKONOS_ERR_GETGPIO_OE_NULL_PARM; - } - - /* Reading GPIO output enable registers */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_15_8, &readBytes[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_DIR_CTL_18_16, &readBytes[2]); - - /* Updating gpioConfig->gpioSetup->gpioOe output enable */ - *gpioOutEn = ((uint32_t)(readBytes[2] & 0x07) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - - -/** - * \brief Sets the Mykonos GPIO source control for different GPIO functionality - * - * This function will only affect the GPIO pins that have their OE direction set to output. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioSrcCtrl nibble based source control, this is a 32 bit containing - * 5 nibbles that will be set the source control. - * - * \retval MYKONOS_ERR_GPIO_SRC_PARAM_INV If the source control parameter is invalid - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioSourceCtrl(mykonosDevice_t *device, uint32_t gpioSrcCtrl) -{ - const uint32_t GPIO_SRC_MASK = 0xFFFFF; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioSourceCtrl()\n"); -#endif - - /* writing GPIO configuration registers */ - if (gpioSrcCtrl > GPIO_SRC_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SRC_PARAM_INV, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SRC_PARAM_INV)); - return MYKONOS_ERR_GPIO_SRC_PARAM_INV; - } - - /* writing GPIO configuration registers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, (gpioSrcCtrl & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, ((gpioSrcCtrl >> 8) & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS, ((gpioSrcCtrl >> 16) & 0x0F)); - - /* Updating gpioConfig->gpioSetup source control */ - device->auxIo->gpio->gpioSrcCtrl3_0 = (mykonosGpioMode_t)(gpioSrcCtrl & 0x0F); - device->auxIo->gpio->gpioSrcCtrl7_4 = (mykonosGpioMode_t)((gpioSrcCtrl >> 4) & 0x0F); - device->auxIo->gpio->gpioSrcCtrl11_8 = (mykonosGpioMode_t)((gpioSrcCtrl >> 8) & 0x0F); - device->auxIo->gpio->gpioSrcCtrl15_12 = (mykonosGpioMode_t)((gpioSrcCtrl >> 12) & 0x0F); - device->auxIo->gpio->gpioSrcCtrl18_16 = (mykonosGpioMode_t)((gpioSrcCtrl >> 16) & 0x0F); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos GPIO source control for different GPIO functionality - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioSrcCtrl nibble based source control, this is a 32 bit containing - * 5 nibbles that will be set the source control. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getGpioSourceCtrl(mykonosDevice_t *device, uint32_t *gpioSrcCtrl) -{ - uint8_t readBytes[3] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSourceCtrl()\n"); -#endif - - if (gpioSrcCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM)); - return MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM; - } - - /* Reading GPIO output enable registers */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE, &readBytes[1]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS, &readBytes[2]); - - /* Updating gpioConfig->gpioSetup->gpioOe output enable */ - *gpioSrcCtrl = ((uint32_t)(readBytes[2] & 0x0F) << 16) | ((uint32_t)(readBytes[1]) << 8) | (uint32_t)(readBytes[0]); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - - -/** - * \brief Sets the Mykonos 3.3 VDC GPIO configuration registers - * - * This function sets the GPIO 3.3v pin direction (1=output, 0=input) and - * sets the mode of each nibble of GPIO 3.3v pins. See the mykonosGpio3v3Mode_t - * enum for possible modes. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio3v3 - all members - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER device->auxIo->gpio3v3 pointer is NULL - * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_MODE gpio3v3 members have invalid enum value for the GPIO3v3 source control mode. - */ -mykonosGpioErr_t MYKONOS_setupGpio3v3(mykonosDevice_t *device) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupGpio3v3()\n"); -#endif - - if (device->auxIo->gpio3v3 == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER)); - return MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER; - } - else - { - /* write GPIO pin direction registers */ - if ((error = MYKONOS_setGpio3v3Oe(device, device->auxIo->gpio3v3->gpio3v3Oe)) != MYKONOS_ERR_GPIO_OK) - - /* write GPIO3v3 mode */ - if (((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0 > 15) || - ((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 > 15) || - ((uint8_t)device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 > 15)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_MODE, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_MODE)); - return MYKONOS_ERR_SET_GPIO_3V3_INV_MODE; - } - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, ((device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 << 4) | device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, (device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 & 0x0F)); - - return error; - } -} - -/** - * \brief If the GPIO3v3 pins are setup for BITBANG mode, this function sets - * the output pin levels per pin - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio3v3 - all members - * - * \param device is a pointer to the device settings structure - * \param gpio3v3PinLevel Bit per pin to set the level of each GPIO3v3 output pin - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpio3v3PinLevel(mykonosDevice_t *device, uint16_t gpio3v3PinLevel) -{ - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpio3v3PinLevel()\n"); -#endif - - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0, (gpio3v3PinLevel & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8, ((gpio3v3PinLevel >> 8) & 0x0F)); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos 3.3 VDC GPIO pin output levels for BITBANG mode - * - * This function allows reading the value that the 3.3v GPIO output pins are - * set to drive out the pins. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpio3v3SetLevel is a unit16_t pointer which contains the level of each GPIO3V3 pin (bit per pin) - * - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM gpio3v3SetLevel pointer is NULL in function parameter - */ -mykonosGpioErr_t MYKONOS_getGpio3v3SetLevel(mykonosDevice_t *device, uint16_t *gpio3v3SetLevel) -{ - uint8_t readBytes[2] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3SetLevel()\n"); -#endif - - if (gpio3v3SetLevel == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM)); - return MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM; - } - - /* reading the registers into two-byte array */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8, &readBytes[1]); - - /* performing concatenation and assigning value to gpio3v3SpiRead */ - *gpio3v3SetLevel = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos 3.3 VDC GPIO pin levels for BITBANG mode - * - * Note: this function is only capable of reading back pin levels for the - * 3.3v pins set to be inputs. Any pins set to be a GPIO output will read - * back as zero. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpio3v3PinLevel is a unit16_t pointer which contains the level of each GPIO3V3 pin - * that is defined as an input - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM gpio3v3PinLevel pointer is NULL in function parameter - */ -mykonosGpioErr_t MYKONOS_getGpio3v3PinLevel(mykonosDevice_t *device, uint16_t *gpio3v3PinLevel) -{ - uint8_t readBytes[2] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3PinLevel()\n"); -#endif - - if (gpio3v3PinLevel == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM)); - return MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM; - } - - /* reading the registers for input pin levels */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_READ_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_SPI_READ_15_8, &readBytes[1]); - - *gpio3v3PinLevel = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This function sets the Pin direction control for the Mykonos 3.3 VDC GPIO. - * - * The bits in gpio3v3OutEn are used to configure each corresponding pin as an input or an output. - * If the bit is set, the pin is configured as an output, and if it is clear the pin is configured as an input. - * For example, setting gpio3v3OutEn = 0x02 will configure GPIO_3p3_2 as an output and the rest pins as inputs. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - device->auxIo->gpio3v3 - all members - * - * \param device is a pointer to the device settings structure - * \param gpio3v3OutEn Bit per pin to set the level of each GPIO3v3 output pin - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpio3v3Oe(mykonosDevice_t *device, uint16_t gpio3v3OutEn) -{ - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3Oe()\n"); -#endif - - /* write GPIO pin direction registers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0, (gpio3v3OutEn & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8, ((gpio3v3OutEn >> 8) & 0x0F)); - - /* update device->auxIo->gpio3v3 structure */ - device->auxIo->gpio3v3->gpio3v3Oe = gpio3v3OutEn; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos 3.3 VDC GPIO pin direction - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpio3v3OutEn is a unit16_t pointer which will contain the output enable parameter, - * this will be a bit field, if a bit is set then the corresponding GPIO pin is an output, - * if the bit is not set then the corresponding pin is an input - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM gpio3v3OutEn pointer is NULL in function parameter - */ -mykonosGpioErr_t MYKONOS_getGpio3v3Oe(mykonosDevice_t *device, uint16_t *gpio3v3OutEn) -{ - uint8_t readBytes[2] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3Oe()\n"); -#endif - - /* checking for null parameter */ - if (gpio3v3OutEn == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM)); - return MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM; - } - - /* reading the registers for input pin levels */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8, &readBytes[1]); - - *gpio3v3OutEn = ((uint16_t)(readBytes[1] & 0x0F) << 8) | (uint16_t)(readBytes[0]); - - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Sets the Mykonos GPIO 3.3 VDC source control for different GPIO fucntionality - * - * This function will only affect the GPIO pins that have their OE direction set to output. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpio3v3SrcCtrl nibble based source control, this is a 12 bit containing - * 3 nibbles that will be set the source control. - * - * \retval MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL gpio3v3 members have invalid value for the GPIO3v3 source control mode. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t gpio3v3SrcCtrl) -{ - const uint16_t GPIO_SRC_MASK = 0x0FFF; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpio3v3SourceCtrl()\n"); -#endif - - /* writing GPIO configuration registers */ - if (gpio3v3SrcCtrl > GPIO_SRC_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL, - getGpioMykonosErrorMessage(MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL)); - return MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL; - } - - /* writing GPIO configuration registers */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, (gpio3v3SrcCtrl & 0xFF)); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, ((gpio3v3SrcCtrl >> 8) & 0xFF)); - - /* Updating gpioConfig->gpioSetup source control */ - device->auxIo->gpio3v3->gpio3v3SrcCtrl3_0 = (mykonosGpio3v3Mode_t)(gpio3v3SrcCtrl & 0x0F); - device->auxIo->gpio3v3->gpio3v3SrcCtrl7_4 = (mykonosGpio3v3Mode_t)(gpio3v3SrcCtrl & 0xF0); - device->auxIo->gpio3v3->gpio3v3SrcCtrl11_8 = (mykonosGpio3v3Mode_t)((gpio3v3SrcCtrl >> 8) & 0x0F); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads the Mykonos 3v3 GPIO source control for different GPIO functionality - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpio3v3SrcCtrl nibble based source control, this is a 12 bit containing - * 3 nibbles that will be set the source control. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t *gpio3v3SrcCtrl) -{ - uint8_t readBytes[2] = {0}; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpio3v3SourceCtrl()\n"); -#endif - - /* checking for null parameter */ - if (gpio3v3SrcCtrl == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM)); - return MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM; - } - - /* Reading GPIO output enable registers */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL, &readBytes[0]); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL, &readBytes[1]); - - /* Updating gpioConfig->gpioSetup->gpioOe output enable */ - *gpio3v3SrcCtrl = ((uint16_t)(readBytes[1] & 0xFF) << 8) | ((uint16_t)(readBytes[0])); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Gain compensation enable and setup function. - * - * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the Rx channels. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gainComp which is a mykonosGainComp_t structure. - * \param enable this parameter enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT gain compensation structure gainComp is not initialised - * \retval MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET gain compensation structure gainComp->rx1Offset is invalid - * \retval MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET gain compensation structure gainComp->rx2Offset is invalid - * \retval MYKONOS_ERR_GAINCOMP_INV_STEP gain compensation structure gainComp->compStep is invalid - * \retval MYKONOS_ERR_GAINCOMP_INV_EN enable is not valid - */ -mykonosGpioErr_t MYKONOS_setRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t enable) -{ - uint8_t regWr2 = 0x00; - uint8_t regWr3 = 0x00; - uint8_t regWr4 = 0x00; - - /* Max parameter values for error checking */ - const uint8_t RXOFFSET_RANGE = 0x1F; - const uint8_t STEP_RANGE = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxGainCompensation()\n"); -#endif - - /* Check for gainComp initialised */ - if (gainComp == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT)); - return MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT; - } - - /* Check for enable */ - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_EN, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_EN)); - return MYKONOS_ERR_GAINCOMP_INV_EN; - } - else if (enable == 1) - { - /* Check for gain compensation Rx1 offset range */ - if (gainComp->rx1Offset > RXOFFSET_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET)); - return MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET; - } - - /* Check for gain compensation Rx2 offset range */ - if (gainComp->rx2Offset > RXOFFSET_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET)); - return MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET; - } - - /* Check for gain compensation step range */ - if (gainComp->compStep > STEP_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_INV_STEP, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_INV_STEP)); - return MYKONOS_ERR_GAINCOMP_INV_STEP; - } - - /* Enabling gain compensation block */ - regWr4 = 0x88 | gainComp->compStep; - regWr3 = gainComp->rx2Offset; - regWr2 = gainComp->rx1Offset; - } - - /* Write gain compensation setup to device */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET, regWr2); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET, regWr3); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_GAIN_COMP_CFG, regWr4); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Get gain compensation setup and enabled function. - * - * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the Rx channels. - * This function will get the current setup and the enable state of the block. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gainComp pointer to a mykonosGainComp_t structure, will held the current device gain compensation settings. - * \param enabled pointer this parameter will contain the enable state of the gain compensation block. - * enabled = 1 - * disabled = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GAINCOMP_NULL_STRUCT gain compensation structure gainComp is not initialised - * \retval MYKONOS_ERR_GAINCOMP_EN_NULL_PARM enable is null pointer for the passed parameter - */ -mykonosGpioErr_t MYKONOS_getRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t *enabled) -{ - uint8_t regWr2 = 0x00; - uint8_t regWr3 = 0x00; - uint8_t regWr4 = 0x00; - - /* Mask parameter values populating mykonosGainComp_t structure */ - const uint8_t ENABLED_MASK = 0x80; - const uint8_t STEP_MASK = 0x07; - - /* Shift values for writing gain values */ - const uint8_t ENABLED_SHIFT = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxGainCompensation()\n"); -#endif - - /* Check for gainComp for Null */ - if (gainComp == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_NULL_STRUCT)); - return MYKONOS_ERR_GAINCOMP_NULL_STRUCT; - } - - if (enabled == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GAINCOMP_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GAINCOMP_EN_NULL_PARM)); - return MYKONOS_ERR_GAINCOMP_EN_NULL_PARM; - } - - /* Read gain compensation setup from device */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET, ®Wr2); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET, ®Wr3); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX_GAIN_COMP_CFG, ®Wr4); - - - /* Parsing read data to passed by reference parameters */ - *enabled = (regWr4 & ENABLED_MASK) >> ENABLED_SHIFT; - gainComp->compStep = (regWr4 & STEP_MASK); - gainComp->rx2Offset = regWr3; - gainComp->rx1Offset = regWr2; - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Gain compensation enable and setup function for the observation channel. - * - * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the observation channels. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gainComp is a pointer to the mykonosObsRxGainComp_t structure. - * \param enable enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT gain compensation structure gainComp is not initialised - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET gain compensation structure gainComp->obsRxOffset is invalid - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP gain compensation structure gainComp->compStep is invalid - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN enable is not valid - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t enable) -{ - uint8_t regWr2 = 0x00; - uint8_t regWr3 = 0x00; - - /* Max parameter values for error checking */ - const uint8_t RXOFFSET_RANGE = 0x1F; - - /* Shift values for writing gain values */ - const uint8_t STEP_RANGE = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxGainCompensation()\n"); -#endif - - /* Check for gainComp initialised */ - if (gainComp == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT; - } - - /* Check for enable */ - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN; - } - else if (enable == 1) - { - /* Check for gain compensation offset range */ - if (gainComp->obsRxOffset > RXOFFSET_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET; - } - - /* Check for gain compensation step range */ - if (gainComp->compStep > STEP_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP; - } - - /* Enabling gain compensation block */ - regWr3 = 0x88 | gainComp->compStep; - regWr2 = ((gainComp->obsRxOffset & 0x1E) >> 1) | ((gainComp->obsRxOffset & 0x01) << 4); - } - - /* Write gain compensation setup to device */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET, regWr2); - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG, regWr3); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Get gain compensation setup and enabled function for the observation channel. - * - * The gain compensation block is a function that compensates for the attenuation in the internal attenuator for the observation - * channels. - * This function will get the current setup and the enable state of the block. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gainComp pointer to a mykonosObsRxGainComp_t structure, will held the current device gain compensation settings. - * \param enabled pointer this parameter will contain the enable state of the gain compensation block. - * enabled = 1 - * disabled = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT observation channel gain compensation structure gainComp is not initialised - * \retval MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM enabled is null pointer for the parameter passed - */ -mykonosGpioErr_t MYKONOS_getObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t *enabled) -{ - uint8_t regRd2 = 0x00; - uint8_t regRd3 = 0x00; - - /* Masks values for populating mykonosObsRxGainComp_t structure */ - const uint8_t ENABLED_MASK = 0x80; - const uint8_t STEP_MASK = 0x07; - - /* Shift values for populating mykonosObsRxGainComp_t structure */ - const uint8_t ENABLED_SHIFT = 0x07; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxGainCompensation()\n"); -#endif - - /* Check for gainComp for Null */ - if (gainComp == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT; - } - - if (enabled == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM)); - return MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM; - } - - /* Read gain compensation setup from device */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET, ®Rd2); - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG, ®Rd3); - - - /* Parsing read data to passed by reference parameters */ - *enabled = (regRd3 & ENABLED_MASK) >> ENABLED_SHIFT; - gainComp->compStep = (regRd3 & STEP_MASK); - gainComp->obsRxOffset = ((regRd2 & 0x0F) << 1) | ((regRd2 & 0x10) >> 4); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Slicer control over GPIO inputs. - * - * The user can control the slicer position via 3 GPIO inputs per channel. - * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosRxSlicer_t. - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - Gain compensation block has to be enabled in order to user the slicer control - * - * \param device is a pointer to the device settings structure - * \param slicerStep configures the step size of the slicer when external pin contol mode is enabled. - * Slicer gain in this mode is determined by multiplying the step size by the input bit code from the BBP. - * Step sizes are as follows: - * sllicerStep | step - * -------------|------------ - * 0 | 1 - * 1 | 2 - * 2 | 3 - * 3 | 4 - * - * \param rx1Pins Rx1 slicer inputs can take values from one of the following combinations that are specified in mykonosRxSlicer_t enum: - * -GPIO_2, GPIO_1, and GPIO_0 - * -GPIO_7, GPIO_6, and GPIO_5 - * -GPIO_10, GPIO_9, and GPIO_8 - * \param rx2Pins Rx2 slicer inputs can take values from one of the following combinations that are specified in mykonosRxSlicer_t enum: - * -GPIO_7, GPIO_6, and GPIO_5 - * -GPIO_13, GPIO_12, and GPIO_11 - * \param enable this parameter enables the external pin control mode so the BBP can control the slicer setting. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SLICER_INV_RX1_SEL invalid RX1 GPIO pin selection for Slicer control - * \retval MYKONOS_ERR_SLICER_INV_RX2_SEL invalid RX2 GPIO pin selection for Slicer control - * \retval MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE slicer step is out of range - * \retval MYKONOS_ERR_SLICER_EN_INV invalid enable - */ -mykonosGpioErr_t MYKONOS_setRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosRxSlicer_t rx1Pins, mykonosRxSlicer_t rx2Pins, uint8_t enable) -{ - uint8_t regWr = 0x00; - - const uint8_t STEP_MASK = 0x03; - const uint8_t STEP_SHIFT = 0x05; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxSlicerCtrl()\n"); -#endif - - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_EN_INV, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_EN_INV)); - return MYKONOS_ERR_SLICER_EN_INV; - } - else if (enable == 1) - { - /* Enabling Slicer input control */ - regWr = 0x80; - - /* Check for Rx1 Slicer input control */ - switch (rx1Pins) - { - case GPIO_0_1_2: - regWr |= 0x00; - break; - case GPIO_5_6_7: - regWr |= 0x01; - break; - case GPIO_8_9_10: - regWr |= 0x02; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_RX1_SEL, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_RX1_SEL)); - return MYKONOS_ERR_SLICER_INV_RX1_SEL; - } - - /* Check for Rx2 Slicer input control */ - switch (rx2Pins) - { - case GPIO_11_12_13: - regWr |= 0x00; - break; - case GPIO_5_6_7: - regWr |= 0x04; - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_RX2_SEL, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_RX2_SEL)); - return MYKONOS_ERR_SLICER_INV_RX2_SEL; - } - - /* Check for Slicer input step size control */ - if (slicerStep > STEP_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE)); - return MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE; - } - else - { - regWr |= (uint8_t)(slicerStep << STEP_SHIFT); - } - } - - /* Write to device the slicer configuration */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_RX_SLCR_PIN_CFG, regWr); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This function will get the programmed Slicer control for Rx1 and Rx2 channels. - * - * The user can control the slicer position via 3 GPIO inputs per channel. - * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosRxSlicer_t. - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param slicerStep will contain the configured step size - * \param rx1Pins will contain the configured GPIO combination for Rx1 - * \param rx2Pins will contain the configured GPIO combination for Rx2 - * \param enable will contain the programmed enable setting - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM rx1Pins is null pointer for the passed parameter - * \retval MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM rx1Pins is null pointer for the passed parameter - * \retval MYKONOS_ERR_SLICER_STEP_NULL_PARM slicerStep is null pointer for the passed parameter - * \retval MYKONOS_ERR_SLICER_EN_NULL_PARM enable is null pointer for the passed parameter - */ -mykonosGpioErr_t MYKONOS_getRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosRxSlicer_t *rx1Pins, mykonosRxSlicer_t *rx2Pins, uint8_t *enable) -{ - uint8_t regRd = 0x00; - - /* Mask parameter values populating parameters */ - const uint8_t EN_MASK = 0x80; - const uint8_t STEP_MASK = 0x60; - const uint8_t RX1_MASK = 0x03; - const uint8_t RX2_MASK = 0x0C; - - /* Shift values for populating passed parameters */ - const uint8_t EN_SHIFT = 0x07; - const uint8_t STEP_SHIFT = 0x05; - const uint8_t RX1_SHIFT = 0x00; - const uint8_t RX2_SHIFT = 0x02; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxSlicerCtrl()\n"); -#endif - - /* Check for Rx1 Slicer input control null parameter */ - if (rx1Pins == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM)); - return MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM; - } - - /* Check for Rx2 Slicer input control null parameter */ - if (rx2Pins == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM)); - return MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM; - } - - /* Check for Slicer step control null parameter */ - if (slicerStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_STEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_STEP_NULL_PARM)); - return MYKONOS_ERR_SLICER_STEP_NULL_PARM; - } - - /* Check for Slicer step control null parameter */ - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_EN_NULL_PARM)); - return MYKONOS_ERR_SLICER_EN_NULL_PARM; - } - - /* Reading SLicer control register */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_RX_SLCR_PIN_CFG, ®Rd); - - /* Parsing values */ - *enable = (regRd & EN_MASK) >> EN_SHIFT; - *slicerStep = (regRd & STEP_MASK) >> STEP_SHIFT; - - /* Map to enum */ - switch ((regRd & RX2_MASK) >> RX2_SHIFT) - { - case 0: - *rx2Pins = GPIO_11_12_13; - break; - case 1: - *rx2Pins = GPIO_5_6_7; - break; - - default: - *rx2Pins = GPIO_11_12_13; - break; - } - - *rx1Pins = (mykonosRxSlicer_t)((regRd & RX1_MASK) >> RX1_SHIFT); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Slicer control over GPIO inputs for the observation channel. - * - * The user can control the slicer position via 3 GPIO inputs for the observation channel. - * There are various configurations for the GPIO pins, this configurations are enumerated in the mykonosObsRxSlicer_t. - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - Gain compensation block has to be enabled in order to user the slicer control - * - * \param device is a pointer to the device settings structure - * \param slicerStep configures the step size of the slicer when external pin contol mode is enabled. - * Slicer gain in this mode is determined by multiplying the step size by the input bit code from the BBP. - * Step sizes are as follows: - * sllicerStep | step - * -------------|------------ - * 0 | 1 - * 1 | 2 - * 2 | 3 - * 3 | 4 - * - * \param obsRxPins observation slicer inputs can take values from one of the following combinations that are specified in mykonosObsRxSlicer_t enum: - * -GPIO_18, GPIO_17 and GPIO_16 - * -GPIO_16, GPIO_15 and GPIO_14 - * \param enable enables the external pin control mode so the BBP can control the slicer setting. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_SLICER_INV_OBS_RX_SEL invalid observation channel GPIO pin selection for Slicer control - * \retval MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE slicer step is out of range - * \retval MYKONOS_ERR_SLICER_OBS_RX_EN_INV invalid enable - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosObsRxSlicer_t obsRxPins, uint8_t enable) -{ - uint8_t regWr = 0x00; - - const uint8_t STEP_MASK = 0x03; - const uint8_t STEP_SHIFT = 0x05; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setObsRxSlicerCtrl()\n"); -#endif - - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_EN_INV, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_EN_INV)); - return MYKONOS_ERR_SLICER_OBS_RX_EN_INV; - } - else if (enable == 1) - { - /* Enabling Slicer input control */ - regWr = 0x80; - - /* Check for Rx1 Slicer input control */ - switch (obsRxPins) - { - case GPIO_18_17_16: - regWr |= 0x00; - break; - case GPIO_16_15_14: - regWr |= 0x01; - break; - - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_INV_OBS_RX_SEL, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_INV_OBS_RX_SEL)); - return MYKONOS_ERR_SLICER_INV_OBS_RX_SEL; - } - - /* Check for Slicer input step size control */ - if (slicerStep & ~STEP_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE)); - return MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE; - } - else - { - regWr |= (uint8_t)((slicerStep << STEP_SHIFT)); - } - } - - /* Write to device the slicer configuration */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG, regWr); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This function will get the programmed Slicer control for observation channel. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param slicerStep will contain the configured step size - * \param obsRxPins will contain the configured GPIO combination - * \param enable will contain the programmed enable setting - * - * \retval MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM obsRxPins is null pointer for the passed parameter - * \retval MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM slicerStep is null pointer for the passed parameter - * \retval MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, enable is null pointer for the passed parameter - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosObsRxSlicer_t *obsRxPins, uint8_t *enable) -{ - uint8_t regRd = 0x00; - - /* Mask parameter values populating slicer parameters */ - const uint8_t EN_MASK = 0x80; - const uint8_t STEP_MASK = 0x60; - const uint8_t OBS_RX_MASK = 0x03; - - /* Shift values for writing slicer parameters */ - const uint8_t EN_SHIFT = 0x07; - const uint8_t STEP_SHIFT = 0x05; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getObsRxSlicerCtrl()\n"); -#endif - - /* Check for Rx1 Slicer input control null parameter */ - if (obsRxPins == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM)); - return MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM; - } - - /* Check for Slicer step control null parameter */ - if (slicerStep == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM)); - return MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM; - } - - /* Check for Slicer step control null parameter */ - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM)); - return MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM; - } - - /* Reading Slicer control register */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG, ®Rd); - - /* Parsing values */ - *enable = (regRd & EN_MASK) >> EN_SHIFT; - *slicerStep = (regRd & STEP_MASK) >> STEP_SHIFT; - - /* Map to enum */ - switch (regRd & OBS_RX_MASK) - { - case 0: - *obsRxPins = GPIO_18_17_16; - break; - case 1: - *obsRxPins = GPIO_16_15_14; - break; - - default: - *obsRxPins = (mykonosObsRxSlicer_t)0; - break; - } - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Floating point formatter enable and setup function. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) - * which increases the bitwidth in the digital datapath. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - Gain compensation block has to be enabled in order to user floating point formatter - * - * \param device is a pointer to the device settings structure - * \param floatFrmt which is a mykonosFloatPntFrmt_t structure. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT floating point formatter structure floatFrmt not initialized - * \retval MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE floating point formatter structure floatFrmt.roundMode not valid parameter - * \retval MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT floating point formatter structure floatFrmt.dataFormat not valid parameter - * \retval MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN floating point formatter structure floatFrmt.encNan not valid parameter - * \retval MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS floating point formatter structure floatFrmt.expBits not valid parameter - * \retval MYKONOS_ERR_FLOATFRMT_INV_LEADING floating point formatter structure floatFrmt.leading not valid parameter - */ -mykonosGpioErr_t MYKONOS_setFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt) -{ - uint8_t regWr1 = 0x00; - - /* Max parameter values for error checking */ - const uint8_t ROUND_RANGE = 0x04; - const uint8_t DATA_FRMT_RANGE = 0x01; - const uint8_t ENCODE_RANGE = 0x01; - const uint8_t EXPBITS_RANGE = 0x03; - const uint8_t LEADING_RANGE = 0x01; - - /* Shift values for writing mykonosFloatPntFrmt_t values */ - const uint8_t ROUND_SHIFT = 0x05; - const uint8_t DATA_FRMT_SHIFT = 0x04; - const uint8_t ENCODE_SHIFT = 0x03; - const uint8_t EXPBITS_SHIFT = 0x01; - const uint8_t LEADING_SHIFT = 0x00; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setFloatPointFrmt()\n"); -#endif - - /* Check for gainComp initialised */ - if (floatFrmt == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT)); - return MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT; - } - - /* Check for floating point round mode */ - if (floatFrmt->roundMode > ROUND_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE)); - return MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE; - } - - /* Check for floating point data format */ - if (floatFrmt->dataFormat > DATA_FRMT_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT)); - return MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT; - } - - /* Check for floating point encode NaN */ - if (floatFrmt->encNan > ENCODE_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN)); - return MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN; - } - - /* Check for floating point exponent bits range */ - if (floatFrmt->expBits > EXPBITS_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS)); - return MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS; - } - - /* Check for floating point hide leading ones */ - if (floatFrmt->leading > LEADING_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_LEADING, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_LEADING)); - return MYKONOS_ERR_FLOATFRMT_INV_LEADING; - } - - regWr1 = (uint8_t)((floatFrmt->roundMode << ROUND_SHIFT) | (floatFrmt->dataFormat << DATA_FRMT_SHIFT) | - (floatFrmt->encNan << ENCODE_SHIFT) | (floatFrmt->expBits << EXPBITS_SHIFT) | - (floatFrmt->leading << LEADING_SHIFT)); - - - /* Write gain compensation setup to device */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_CFG, regWr1); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Floating point formatter setup function. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range - * which increases the bit-width in the digital data-path. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - Gain compensation block has to be enabled in order to user floating point formatter - * - * \param device is a pointer to the device settings structure - * \param floatFrmt which is a mykonosFloatPntFrmt_t structure. - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_NULL_STRUCT floating point formatter structure floatFrmt not initialized - * - */ -mykonosGpioErr_t MYKONOS_getFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt) -{ - uint8_t regRd1 = 0x00; - - /* Mask parameter values populating mykonosGainComp_t structure */ - const uint8_t ROUND_MASK = 0xE0; - const uint8_t DATA_FRMT_MASK = 0x10; - const uint8_t ENCODE_MASK = 0x08; - const uint8_t EXPBITS_MASK = 0x06; - const uint8_t LEADING_MASK = 0x01; - - /* Shift values for writing gain values */ - const uint8_t ROUND_SHIFT = 0x05; - const uint8_t DATA_FRMT_SHIFT = 0x04; - const uint8_t ENCODE_SHIFT = 0x03; - const uint8_t EXPBITS_SHIFT = 0x01; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getFloatPointFrmt()\n"); -#endif - - /* Check floatFrmt for Null */ - if (floatFrmt == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_STRUCT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_STRUCT)); - return MYKONOS_ERR_FLOATFRMT_NULL_STRUCT; - } - - /* Read gain compensation setup from device */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_CFG, ®Rd1); - - /* Parsing read data to passed by reference parameters */ - floatFrmt->roundMode = (regRd1 & ROUND_MASK) >> ROUND_SHIFT; - floatFrmt->dataFormat = (regRd1 & DATA_FRMT_MASK) >> DATA_FRMT_SHIFT; - floatFrmt->encNan = (regRd1 & ENCODE_MASK) >> ENCODE_SHIFT; - floatFrmt->expBits = (regRd1 & EXPBITS_MASK) >> EXPBITS_SHIFT; - floatFrmt->leading = regRd1 & LEADING_MASK; - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Floating point formatter enable/disable Rx1 and Rx2 function. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range - * which increases the bit-width in the digital data-path. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - Gain compensation block has to be enabled in order to user floating point formatter - * - * \param device is a pointer to the device settings structure - * \param rx1Att this parameter sets the integer data attenuation for the Rx1 channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * \param rx2Att this parameter sets the integer data attenuation for the Rx2 channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * \param enable this parameter enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT not valid rx1 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt() - * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT not valid rx2 attenuation parameter passed in MYKONOS_setRxEnFloatPntFrmt() - * \retval MYKONOS_ERR_FLOATFRMT_SET_INV_EN not valid enable parameter passed in MYKONOS_setRxEnFloatPntFrmt() - */ -mykonosGpioErr_t MYKONOS_setRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t rx1Att, uint8_t rx2Att, uint8_t enable) -{ - uint8_t regWr = 0x00; - - const uint8_t RXATT_RANGE = 0x07; - const uint8_t RX1ATT_SHIFT = 0x01; - const uint8_t RX2ATT_SHIFT = 0x05; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setRxEnFloatPntFrmt()\n"); -#endif - - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_EN, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_EN)); - return MYKONOS_ERR_FLOATFRMT_SET_INV_EN; - } - else if (enable == 1) - { - /* Check for rx1Att range */ - if (rx1Att > RXATT_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT)); - return MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT; - } - - /* Check for rx2Att range */ - if (rx2Att > RXATT_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT)); - return MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT; - } - - /* Enabling floating point formatter for Rx1 and Rx2 */ - regWr = 0x11; - regWr |= (uint8_t)((rx1Att << RX1ATT_SHIFT) | (rx2Att << RX2ATT_SHIFT)); - } - - /* Writing floating point formatter enables for Rx1 and Rx2 */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_RX_CTRL, regWr); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Floating point formatter setup function. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) - * which increases the bitwidth in the digital datapath. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param rx1Att this parameter sets the integer data attenuation for the Rx1 channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * \param rx2Att this parameter sets the integer data attenuation for the Rx2 channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * \param enable this parameter enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT null pointer passed for rx1 attenuation in MYKONOS_setRxEnFloatPntFrmt() - * \retval MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT null pointer passed for rx2 attenuation in MYKONOS_setRxEnFloatPntFrmt() - * \retval MYKONOS_ERR_FLOATFRMT_NULL_ENABLE null pointer passed for enable in MYKONOS_setRxEnFloatPntFrmt() - */ -mykonosGpioErr_t MYKONOS_getRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *rx1Att, uint8_t *rx2Att, uint8_t *enable) -{ - uint8_t regRd = 0x00; - - const uint8_t EN_MASK = 0x11; - const uint8_t RX1ATT_MASK = 0x0E; - const uint8_t RX1ATT_SHIFT = 0x01; - const uint8_t RX2ATT_MASK = 0xE0; - const uint8_t RX2ATT_SHIFT = 0x05; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getRxEnFloatPntFrmt()\n"); -#endif - - /* Check for rx1Att NULL parameter */ - if (rx1Att == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT)); - return MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT; - } - - /* Check for rx2Att NULL parameter */ - if (rx2Att == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT)); - return MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT; - } - - /* Check for enable NULL parameter */ - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ENABLE, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ENABLE)); - return MYKONOS_ERR_FLOATFRMT_NULL_ENABLE; - } - - /* Read Rx1 and Rx2 floating point enables */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_RX_CTRL, ®Rd); - - *rx1Att = (regRd & RX1ATT_MASK) >> RX1ATT_SHIFT; - *rx2Att = (regRd & RX2ATT_MASK) >> RX2ATT_SHIFT ; - *enable = (regRd & EN_MASK) ? 1 : 0; - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - - -/** - * \brief Floating point formatter enable function for ORx channel. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range - * which increases the bit-width in the digital data-path. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param orxAtt this parameter sets the integer data attenuation for the ORx channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * * \param enable this parameter enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_INV_ORXATT not valid Orx attenuation parameter passed in MYKONOS_setOrxEnFloatPntFrmt() - * \retval MYKONOS_ERR_FLOATFRMT_INV_ORXEN not valid enable parameter passed in MYKONOS_setOrxEnFloatPntFrmt() - */ -mykonosGpioErr_t MYKONOS_setOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t orxAtt, uint8_t enable) -{ - uint8_t regWr = 0x00; - - const uint8_t ORXATT_RANGE = 0x07; - const uint8_t ORXATT_SHIFT = 0x01; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setOrxEnFloatPntFrmt()\n"); -#endif - - /* Check for enable */ - if (enable > 1) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ORXEN, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ORXEN)); - return MYKONOS_ERR_FLOATFRMT_INV_ORXEN; - } - else if (enable == 1) - { - /* Check for rx1Att range */ - if (orxAtt > ORXATT_RANGE) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_INV_ORXATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_INV_ORXATT)); - return MYKONOS_ERR_FLOATFRMT_INV_ORXATT; - } - - /* Enabling floating point formatter for Rx1 and Rx2 */ - regWr = 0x01; - regWr |= (uint8_t)(orxAtt << ORXATT_SHIFT); - } - - /* Writing floating point formatter enable for ORX channel */ - CMB_SPIWriteByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL, regWr); - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Floating point formatter enable and setup function. - * - * The floating point formatter block is a function that works in conjunction with the gain - * compensating block, as the gain compensation requires increased dynamic range (total gain range on AD9371 is 42dB) - * which increases the bitwidth in the digital datapath. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param orxAtt this parameter sets the integer data attenuation for the ORx channel in 6dB steps - * to enable the entire data range to be represented in the selected floating point format. - * \param enable this parameter enables or disables the gain compensation block. - * enable = 1 - * disable = 0 - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_FLOATFRMT_NULL_ORXATT null pointer passed for orxAtt - * \retval MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE null pointer passed for enable - */ -mykonosGpioErr_t MYKONOS_getOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *orxAtt, uint8_t *enable) -{ - uint8_t regRd = 0x00; - - const uint8_t EN_MASK = 0x01; - const uint8_t ORXATT_MASK = 0x0E; - const uint8_t ORXATT_SHIFT = 0x01; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getOrxEnFloatPntFrmt()\n"); -#endif - - /* Check for orxAtt NULL parameter */ - if (orxAtt == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ORXATT, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ORXATT)); - return MYKONOS_ERR_FLOATFRMT_NULL_ORXATT; - } - - /* Check for enable NULL parameter */ - if (enable == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE, - getGpioMykonosErrorMessage(MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE)); - return MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE; - } - - /* Read Rx1 and Rx2 floating point enables */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL, ®Rd); - - *orxAtt = (regRd & ORXATT_MASK) >> ORXATT_SHIFT; - *enable = (regRd & EN_MASK) ? 1 : 0; - - /* Return */ - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief Sets up the Temperature Sensor - * - * Before using this function to set up the temp sensor, - * make sure that you call the MYKONOS_setupAuxADC() function - * to ensure that the AuxADC clock is setup and running correctly at 40 MHz, - * and that the structure mykonosTempSensorConfig_t tempSensor is populated. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param tempSensor is a pointer to the mykonosTempSensorConfig_t which holds - * the configuration settings for the temperature sensor - * - * \retval MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM Function parameter tempSensor is a NULL pointer - * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION tempDecimation value out of range (0-7) - * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET offset value out of range (0-255) - * \retval MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW tempWindow out of range (0-15) - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setupTempSensor(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor) -{ - uint8_t offsetFromDevice = 0; - - const uint8_t OFFSET_API = 0x43; -/* const uint8_t TEMP_OFFSET_MASK = 0xFF;*/ - const uint8_t TEMP_WINDOW_MASK = 0xF0; - const uint8_t TEMP_WINDOW_CHECK = 0x0F; - const uint8_t TEMP_DEC_MASK = 0x07; - const uint8_t OFFSET_OVERRIDE_MASK = 0x10; - -#ifdef MYKONOS_VERBOSE - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setupTempSensor()\n"); -#endif - - /* Check for structure initialisation mykonosTempSensorConfig_t */ - if (tempSensor == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM)); - return MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM; - } - - /* Check Temperature sensor decimation range */ - if ((tempSensor->tempDecimation & ~TEMP_DEC_MASK) > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION)); - return MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION; - } - - /* Override fused offset */ - if (tempSensor->overrideFusedOffset > 0) - { - /* Check Temperature sensor offset range */ -/* if (tempSensor->offset & ~TEMP_OFFSET_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET)); - return MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET; - }*/ - - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, 1, OFFSET_OVERRIDE_MASK, 4); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, tempSensor->offset); - } - else - { - /* If manual override was not requested, read back device offset value. - * If factory fused it is non-zero; else API adds a typical offset value */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, &(offsetFromDevice)); - if (offsetFromDevice == 0) - { - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, OFFSET_API); - } - } - - /* Check Temperature sensor window range */ - if ((tempSensor->tempWindow & ~TEMP_WINDOW_CHECK) > 0) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW, - getGpioMykonosErrorMessage(MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW)); - return MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW; - } - else - { - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, tempSensor->tempWindow, TEMP_WINDOW_MASK, 4); - } - - /* Single shot setup */ - CMB_SPIWriteByte (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_MSB, 0x00); - - /* Write decimation factor for the Temperature sensor */ - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, tempSensor->tempDecimation, TEMP_DEC_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads from the Temperature Sensor registers and populates device data structure - * - * After this function is executed, the tempSensor parameter holds updated values - * from the device registers. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param tempSensor is a pointer to the mykonosTempSensorConfig_t which holds - * the configuration settings for the tempSensor - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_GETTEMPSENSORCONFIG_NULL_PARAM Function parameter tempSensor is a NULL pointer - */ -mykonosGpioErr_t MYKONOS_getTempSensorConfig(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor) -{ - uint8_t tempConfig = 0; - - const uint8_t TEMP_WINDOW_MASK = 0xF0; - const uint8_t TEMP_FUSE_MASK = 0x10; - const uint8_t TEMP_DECIMATION_MASK = 0x07; - const uint8_t TEMP_FUSE_SHIFT = 0x04; - -#ifdef MYKONOS_VERBOSE - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getTempSensorConfig()\n"); -#endif - - /* Check tempSensor null parameter passed */ - if (tempSensor == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM)); - return MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM; - } - - /* Read back factory offset, if fused; else manual offset value */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_OFFSET, &(tempSensor->offset)); - - /* Read back Decimation and override Offset Temperature sensor parameters */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, &tempConfig); - tempSensor->overrideFusedOffset = (tempConfig & TEMP_FUSE_MASK) >> TEMP_FUSE_SHIFT; - tempSensor->tempDecimation = (tempConfig & TEMP_DECIMATION_MASK); - - /* Read back tempWindow */ - CMB_SPIReadField(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, &tempConfig, TEMP_WINDOW_MASK, 4); - tempSensor->tempWindow = tempConfig; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Initiates temperature measurement - * - * This function will initiate the Temperature sensor measurement. - * - * \pre - * MYKONOS_setupTempSensor() function to set the temperature sensor. - * MYKONOS_setAuxAdcChannel() function with the AuxADC setting for Temperature sensor channel MYK_TEMPSENSOR - * from the enum type mykonosAuxAdcChannels_t. - * - * \post - * Internal temperature sensor will perform measurement and updated register values, - * read back using MYKONOS_readTempSensor() function. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_startTempMeasurement(mykonosDevice_t *device) -{ - const uint8_t TEMP_LOCK_MASK = 0x80; - const uint8_t TEMP_LOCK_BIT = 0x01; - const uint8_t MEASUREMENT_MASK = 0x01; - -#ifdef MYKONOS_VERBOSE - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_startTempMeasurement()\n"); -#endif - - /* Write the lock bit to ensure that a valid measurement is achieved */ - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, TEMP_LOCK_BIT, TEMP_LOCK_MASK, 7); - - /* Initiate Temperature measurement */ - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, 1, MEASUREMENT_MASK, 0); - CMB_SPIWriteField (device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, 0, MEASUREMENT_MASK, 0); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief Reads temperature code and statuses from the Temperature Sensor registers - * - * This function reads the temperature sensor's statuses and temperature code. - * Allow at least one computation period to elapse. - * The temperature sensor computation period is as 6 times the AuxADC conversion time. - * AuxADC conversion time = (1/40Mhz) * (256 * 2^(tempDecimation)) - * - * Before using this function to read back the temperature, make sure that temperature sensor - * is setup using the MYKONOS_setupTempSensor() function. - * - * \pre Before using this function to read back the sensor value: - * MYKONOS_setupTempSensor() function is needed in order to set up the Temperature sensor. - * MYKONOS_setAuxAdcChannel() function has to be called in order to set the proper AuxADC - * channel. AuxADC channel MYK_TEMPSENSOR is used for the Temperature sensor. - * MYKONOS_startTempMeasurement() this function will start the Temperature sensor, this - * function is needed to be called for every reading that needs to be performed. - * - * \post "tempStatus" structure will contain the status information and the temperature - * code. - * If a valid measurement is achieved then tempStatus->tempValid will be set and - * tempStatus->tempCode will contain the actual reading. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param tempStatus is a pointer to the mykonosTempSensorStatus_t structure which will be updated - * with the temp sensor readings - * - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - * \retval MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM Function parameter tempSensor is a NULL pointer - * \retval MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED temperature sensor reading is not locked - */ -mykonosGpioErr_t MYKONOS_readTempSensor(mykonosDevice_t *device, mykonosTempSensorStatus_t *tempStatus) -{ - int16_t temperature = 0; - uint8_t statusWord = 0; - uint8_t rgRd = 0x00; - - const uint8_t CODE_TO_DEGREE_CELSIUS = 0x67; - const uint8_t TEMP_VALID_MASK = 0x02; - const uint8_t WINDOW_EXCEED_MASK = 0x08; - const uint8_t WINDOW_HI_LO_MASK = 0x04; - const uint8_t TEMP_LOCK = 0x80; - -#ifdef MYKONOS_VERBOSE - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_readTempSensor()\n"); -#endif - - if (tempStatus == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM)); - return MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM; - } - - /* Check for temperature sensor value lock */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONFIG, &rgRd); - if ((rgRd & TEMP_LOCK) == TEMP_LOCK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED, - getGpioMykonosErrorMessage(MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED)); - return MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED; - } - - /* Perform temperature status reading */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB, &statusWord); - tempStatus->windowExceeded = (statusWord & WINDOW_EXCEED_MASK) >> 3; - tempStatus->windowHiLo = (statusWord & WINDOW_HI_LO_MASK) >> 2; - tempStatus->tempValid = (0x01 & ~((statusWord & TEMP_VALID_MASK) >> 1)); - - /* Perform temperature reading */ - CMB_SPIReadByte(device->spiSettings, MYKONOS_ADDR_TEMP_SENSOR_READ, &rgRd); - temperature = rgRd - CODE_TO_DEGREE_CELSIUS; - tempStatus->tempCode = temperature; - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This function sets the drive strength for the required GPIOs. - * - * This function will set the required drive strength, the settings for GPIO drive strength are normal drive and double drive. - * - * GPIO pins that can be assigned independent drive strength are: - * -MYKGPIO0 to MYKGPIO7 and MYKGPIO18 - * - * The rest of GPIOs are paired as: - * -MYKGPIO17 and MYKGPIO16 - * -MYKGPIO8 and MYKGPIO15 - * -MYKGPIO14 and MYKGPIO13 - * -MYKGPIO10 and MYKGPIO9 - * -MYKGPIO12 and MYKGPIO11 - * - * This means that if it is required to double the drive strength for MYKGPIO17 then the drive strength will also be doubled for MYKGPIO16. - * - * If the particular bitfield for gpioDrv is set then the drive strength will be doubled. Note that multiple GPIOs can be set at a time. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioDrv GPIO drive strength setup, valid range is from 0x00000 to 0x7FFFF. - * - * \retval MYKONOS_ERR_GPIO_DRV_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioDrv(mykonosDevice_t *device, uint32_t gpioDrv) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - uint8_t reg0 = 0x00; - uint8_t reg1 = 0x00; - - const uint32_t GPIO_MASK = 0x7FFFF; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioDrv()\n"); -#endif - - /* Error checking for correct number of GPIOs. */ - if (gpioDrv > GPIO_MASK ) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_DRV_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_DRV_INV_PARAM)); - return MYKONOS_ERR_GPIO_DRV_INV_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, ®0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, ®1); - - reg1 = reg1 & 0xC0; - - if (gpioDrv & 0xFF) - { - reg0 = (uint8_t)(gpioDrv & 0xFF); - } - else - { - reg0 = 0x00; - } - - if (gpioDrv & (uint32_t)MYKGPIO18) - { - reg1 |= 0x01; - } - - if ((gpioDrv & (uint32_t)MYKGPIO17) || (gpioDrv & (uint32_t)MYKGPIO16)) - { - reg1 |= 0x02; - } - - if ((gpioDrv & (uint32_t)MYKGPIO15) || (gpioDrv & (uint32_t)MYKGPIO8)) - { - reg1 |= 0x04; - } - - if ((gpioDrv & (uint32_t)MYKGPIO14) || (gpioDrv & (uint32_t)MYKGPIO13)) - { - reg1 |= 0x08; - } - - if ((gpioDrv & (uint32_t)MYKGPIO10) || (gpioDrv & (uint32_t)MYKGPIO9)) - { - reg1 |= 0x10; - } - - if ((gpioDrv & (uint32_t)MYKGPIO12) || (gpioDrv & (uint32_t)MYKGPIO11)) - { - reg1 |= 0x20; - } - - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, reg0); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, reg1); - - return error; -} - - -/** - * \brief This function gets the GPIOs drive strength. - * - * This function will get the programmed drive strength for all the GPIOs - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure. - * \param gpioDrv will contain the current GPIOs drive strength setting. - * - * \retval MYKONOS_ERR_GETGPIODRV_NULL_PARAM null parameter passed to the function. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getGpioDrv(mykonosDevice_t *device, uint32_t *gpioDrv) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - uint8_t reg0 = 0x00; - uint8_t reg1 = 0x00; - uint32_t gpioDrvRd = 0x00; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioDrv()\n"); -#endif - - /* Error checking for correct number of GPIOs. */ - if (gpioDrv == NULL ) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GETGPIODRV_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GETGPIODRV_NULL_PARAM)); - return MYKONOS_ERR_GETGPIODRV_NULL_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_0, ®0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_DRV_CTL_1, ®1); - - gpioDrvRd = (uint32_t)reg0 & 0xFF; - - if (reg1 & 0x01) - { - gpioDrvRd |= (uint32_t)MYKGPIO18; - } - - if (reg1 & 0x02) - { - gpioDrvRd |= (uint32_t)MYKGPIO17 | (uint32_t)MYKGPIO16; - } - - if (reg1 & 0x04) - { - gpioDrvRd |= (uint32_t)MYKGPIO8 | (uint32_t)MYKGPIO15; - } - - if (reg1 & 0x08) - { - gpioDrvRd |= (uint32_t)MYKGPIO14 | (uint32_t)MYKGPIO13; - } - - if (reg1 & 0x10) - { - gpioDrvRd |= (uint32_t)MYKGPIO10 | (uint32_t)MYKGPIO9; - } - - if (reg1 & 0x20) - { - gpioDrvRd |= (uint32_t)MYKGPIO12 | (uint32_t)MYKGPIO11; - } - - *gpioDrv = (mykonosGpioSelect_t)gpioDrvRd; - - return error; -} - -/** - * \brief This function sets the slew rate for the required GPIOs. - * - * This function will set the required slew rate, the settings for GPIO slew rate are given by the enumeration type mykonosGpioSlewRate_t. - * - * GPIO pins that can be assigned independent slew rate are: - * -MYKGPIO0 to MYKGPIO7 and MYKGPIO18 - * - * The rest of GPIOs are paired as: - * -MYKGPIO17 and MYKGPIO16 - * -MYKGPIO8 and MYKGPIO15 - * -MYKGPIO14 and MYKGPIO13 - * -MYKGPIO10 and MYKGPIO9 - * -MYKGPIO12 and MYKGPIO11 - * - * This means that if it is required to set the slew rate for MYKGPIO17 then the same slew rate will be applied for MYKGPIO16. - * - * If the particular bitfield for gpioSelect is set then slewRate will be set for that GPIO. Note that multiple GPIOs can be set at a time. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param gpioSelect GPIO for which the slew rate will be changed, valid range 0x00000 to 0x7FFFF. - * \param slewRate slew rate setting, valid slew rate settings are given by the enumeration type mykonosGpioSlewRate_t - * - * \retval MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t slewRate) -{ - mykonosGpioErr_t error = MYKONOS_ERR_GPIO_OK; - uint8_t reg0 = 0x00; - uint8_t reg1 = 0x00; - uint8_t reg2 = 0x00; - uint8_t reg3 = 0x00; - - const uint32_t GPIO_MASK = 0x7FFFF; - const uint8_t SLEWRATE_MASK = 0x03; - const uint32_t SHIFT4NIBLE = 0x06; - const uint32_t SHIFT3NIBLE = 0x04; - const uint32_t SHIFT2NIBLE = 0x02; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setGpioSlewRate()\n"); -#endif - - /* Error checking for correct number of GPIOs. */ - if (((uint32_t)gpioSelect > GPIO_MASK) || ((uint8_t)slewRate > SLEWRATE_MASK)) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM)); - return MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, ®0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, ®1); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, ®2); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®3); - - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO18) - { - reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); - } - if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO17) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO16)) - { - reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); - } - if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO15) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO8)) - { - reg0 = (reg0 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); - } - if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO14) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO13)) - { - reg0 = (reg0 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; - } - if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO11) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO12)) - { - reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); - } - if (((uint32_t)gpioSelect & (uint32_t)MYKGPIO9) || ((uint32_t)gpioSelect & (uint32_t)MYKGPIO10)) - { - reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO7) - { - reg1 = (reg1 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO6) - { - reg1 = (reg1 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO5) - { - reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT4NIBLE)) | ((uint8_t)slewRate << SHIFT4NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO4) - { - reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT3NIBLE)) | ((uint8_t)slewRate << SHIFT3NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO3) - { - reg2 = (reg2 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO2) - { - reg2 = (reg2 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO1) - { - reg3 = (reg3 & ~(SLEWRATE_MASK << SHIFT2NIBLE)) | ((uint8_t)slewRate << SHIFT2NIBLE); - } - if ((uint32_t)gpioSelect & (uint32_t)MYKGPIO0) - { - reg3 = (reg3 & ~(SLEWRATE_MASK)) | (uint8_t)slewRate; - } - - /* Prepare registers */ - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, reg0); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, reg1); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, reg2); - CMB_SPIWriteByte (device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, reg3); - - return error; -} - - -/** - * \brief This function gets the GPIO slew rate setting. - * - * This function will get the programmed slew rate for the GPIO given by slewRateGpio. - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure. - * \param gpioSelect GPIO selection for getting the slew rate setting. - * \param slewRate will contain the GPIO slew rate setting. - * - * \retval MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM null parameter passed to the function. - * \retval MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM GPIO out of range- valid GPIOs are in the range 0x00000 to 0x7FFFF. - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t *slewRate) -{ - uint8_t reg0 = 0x00; - uint8_t reg1 = 0x00; - uint8_t reg2 = 0x00; - uint8_t reg3 = 0x00; - mykonosGpioSlewRate_t slewSetting = MYK_SLEWRATE_NONE; - - const uint32_t SLEWRATE_MASK = 0x03; - const uint32_t SHIFT4NIBLE = 0x06; - const uint32_t SHIFT3NIBLE = 0x04; - const uint32_t SHIFT2NIBLE = 0x02; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getGpioSlewRate()\n"); -#endif - - /* Error checking for NULL parameter. */ - if (slewRate == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM)); - return MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_0, ®0); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_1, ®1); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_2, ®2); - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®3); - - switch (gpioSelect) - { - case MYKGPIO18: - slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); - break; - case MYKGPIO17: - case MYKGPIO16: - slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); - break; - case MYKGPIO15: - case MYKGPIO8: - slewSetting = (mykonosGpioSlewRate_t)((reg0 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); - break; - case MYKGPIO14: - case MYKGPIO13: - slewSetting = (mykonosGpioSlewRate_t)(reg0 & (SLEWRATE_MASK)); - break; - case MYKGPIO11: - case MYKGPIO12: - slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); - break; - case MYKGPIO9: - case MYKGPIO10: - slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); - break; - case MYKGPIO7: - slewSetting = (mykonosGpioSlewRate_t)((reg1 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); - break; - case MYKGPIO6: - slewSetting = (mykonosGpioSlewRate_t)(reg1 & (SLEWRATE_MASK)); - break; - case MYKGPIO5: - slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT4NIBLE)) >> SHIFT4NIBLE); - break; - case MYKGPIO4: - slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT3NIBLE)) >> SHIFT3NIBLE); - break; - case MYKGPIO3: - slewSetting = (mykonosGpioSlewRate_t)((reg2 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); - break; - case MYKGPIO2: - slewSetting = (mykonosGpioSlewRate_t)(reg2 & (SLEWRATE_MASK)); - break; - case MYKGPIO1: - slewSetting = (mykonosGpioSlewRate_t)((reg3 & (SLEWRATE_MASK << SHIFT2NIBLE)) >> SHIFT2NIBLE); - break; - case MYKGPIO0: - slewSetting = (mykonosGpioSlewRate_t)(reg3 & (SLEWRATE_MASK)); - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM)); - return MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM; - } - - *slewRate = slewSetting; - - return MYKONOS_ERR_GPIO_OK; -} - - -/** - * \brief This function sets the CMOS output driver. - * - * This function sets the CMOS output driver to increase pad drive strength for the SPI_DIO and GP_INTERRUPT pads - * according to the following settings of the enumeration type mykonosCmosPadDrvStr_t - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param cmosDrv drive for the CMOS output driver - * - * \retval MYKONOS_ERR_CMOS_DRV_INV_PARAM invalid drive strength, valid settings are given by mykonosCmosPadDrvStr_t - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_setCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t cmosDrv) -{ - const uint8_t CMOS_DRV_MASK = 0x0F; - const uint8_t CMOS_DRV_SHIFT = 0x04; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_setCmosDrv()\n"); -#endif - - /* Error checking for correct drive */ - switch (cmosDrv) - { /* fall through since this is only checking */ - case MYK_CMOSPAD_DRV_1X: - case MYK_CMOSPAD_DRV_2X: - case MYK_CMOSPAD_DRV_3X: - case MYK_CMOSPAD_DRV_4X: - case MYK_CMOSPAD_DRV_5X: - break; - default: - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CMOS_DRV_INV_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_CMOS_DRV_INV_PARAM)); - return MYKONOS_ERR_CMOS_DRV_INV_PARAM; - } - - CMB_SPIWriteField(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, cmosDrv, (~CMOS_DRV_MASK), CMOS_DRV_SHIFT); - - return MYKONOS_ERR_GPIO_OK; -} - -/** - * \brief This function gets the programmed CMOS output driver - * - * - * Dependencies - * - device->spiSettings->chipSelectIndex - * - * \param device is a pointer to the device settings structure - * \param cmosDrv will be the programmed drive for the CMOS output driver - * - * \retval MYKONOS_ERR_CMOS_DRV_NULL_PARAM Null parameter passed to the function - * \retval MYKONOS_ERR_GPIO_OK Function completed successfully - */ -mykonosGpioErr_t MYKONOS_getCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t *cmosDrv) -{ - uint8_t regRd = 0x00; - - const uint8_t CMOS_DRV_MASK = 0xF0; - const uint8_t CMOS_DRV_SHIFT = 0x04; - -#if MYKONOS_VERBOSE == 1 - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_getCmosDrv()\n"); -#endif - - if (cmosDrv == NULL) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_CMOS_DRV_NULL_PARAM, - getGpioMykonosErrorMessage(MYKONOS_ERR_CMOS_DRV_NULL_PARAM)); - return MYKONOS_ERR_CMOS_DRV_NULL_PARAM; - } - - CMB_SPIReadByte(device->spiSettings, MYKONOS_GPIO_SLEW_CTL_3, ®Rd); - - *cmosDrv = (mykonosCmosPadDrvStr_t)((regRd & CMOS_DRV_MASK) >> CMOS_DRV_SHIFT); - - return MYKONOS_ERR_GPIO_OK; -} - -/** -* \brief This API function configures and enables the secondary SPI port. -* -* This port allows control compatibility with BBPs that employ dual SPI ports. -* The GPIO mapping for the SPI2 is fixed: -* SPI signal | GPIO -* -------------|------------------- -* CSB_2 | GPIO 3 -* SCLK_2 | GPIO 2 -* SDO_2 | GPIO 1 -* SDO_2/SDI2 | GPIO 0 -* -* The secondary SPI port only has a small subset of registers that affect the -* attenuation of the TX channels. It uses a fifth GPIO pin in order to decide -* which TxAttenuation word is active. The Tx Attenuation words in the 2nd SPI -* port are different than the first SPI port. On the 2nd SPI port, each -* transmitter has two Tx Attenuation words (an active word and an inactive -* word). The BBIC should write to the inactive TxAttenuation word. Then the -* fifth GPIO pin should be asserted to make the inactive TxAttenuation word -* active. This allows the BBIC to tightly control in real time when the -* TxAttenuation updates. -* -* Dependencies -* - device->spiSettings -* - device->spiSettings->chipSelectIndex -* -* \param device is a pointer to the device settings structure -* \param enable This is parameter will enable the secondary SPI port: 1 = enable, 0 = disable -* \param updateTxAttenPinSelect This parameter set the GPIO pin to be toggle for using the inactive attenuation words for both channels -* tx update | GPIO -* ------------|------------------- -* 0x00 | GPIO 4 -* 0x01 | GPIO 8 -* 0x02 | GPIO 14 -* 0x03 | none selected -* -* \retval MYKONOS_ERR_SPI2_INV_GPIO if an invalid GPIO pin configuration is passed -* \retval MYKONOS_ERR_HAL_LAYER if HAL function error is passed -* \retval MYKONOS_ERR_OK Function completed successfully -*/ -mykonosGpioErr_t MYKONOS_spi2GpioSetup(mykonosDevice_t *device, uint8_t enable, uint8_t updateTxAttenPinSelect) -{ - uint8_t regWrite = 0; - uint8_t enableBit = 0; - - const uint32_t SPI2_PIN_MASK = 0x03; - -#ifdef MYKONOS_VERBOSE - CMB_writeToLog(ADIHAL_LOG_MESSAGE, device->spiSettings->chipSelectIndex, MYKONOS_ERR_GPIO_OK, "MYKONOS_spi2GpioSetup()\n"); -#endif - - /* Error checking for correctness of GPIO to control attenuation word. */ - if (updateTxAttenPinSelect & ~SPI2_PIN_MASK) - { - CMB_writeToLog(ADIHAL_LOG_ERROR, device->spiSettings->chipSelectIndex, MYKONOS_ERR_SPI2_INV_GPIO, - getGpioMykonosErrorMessage(MYKONOS_ERR_SPI2_INV_GPIO)); - return MYKONOS_ERR_SPI2_INV_GPIO; - } - - /* masking the enable bit and the required pin */ - enableBit = (enable > 0) ? 1 : 0; - regWrite = (uint8_t)((updateTxAttenPinSelect << 4) | (enableBit << 3)); - - /* Set the SPI2 enable and the GPIO pin associated. */ - CMB_SPIWriteField(device->spiSettings, MYKONOS_ADDR_CONFIGURATION_CONTROL_1, regWrite, 0x38, 0); - - return MYKONOS_ERR_GPIO_OK; -} - diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.h b/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.h deleted file mode 100644 index f69ec74..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_gpio.h +++ /dev/null @@ -1,172 +0,0 @@ -/*! - * \file mykonos_gpio.h - * \brief Contains macro definitions and function prototypes for mykonos_gpio.c - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef MYKONOSGPIO_H_ -#define MYKONOSGPIO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "t_mykonos.h" -#include "t_mykonos_gpio.h" - -/* - ***************************************************************************** - * GPIO functions - ***************************************************************************** - */ - -/* GPIO CMOS and SPI setting Functions */ -mykonosGpioErr_t MYKONOS_setGpioDrv(mykonosDevice_t *device, uint32_t gpioDrv); -mykonosGpioErr_t MYKONOS_getGpioDrv(mykonosDevice_t *device, uint32_t *gpioDrv); - -mykonosGpioErr_t MYKONOS_setGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t slewRate); -mykonosGpioErr_t MYKONOS_getGpioSlewRate(mykonosDevice_t *device, mykonosGpioSelect_t gpioSelect, mykonosGpioSlewRate_t *slewRate); - -mykonosGpioErr_t MYKONOS_setCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t spiDrv); -mykonosGpioErr_t MYKONOS_getCmosDrv(mykonosDevice_t *device, mykonosCmosPadDrvStr_t *spiDrv); - - -/* Monitor output Functions */ -mykonosGpioErr_t MYKONOS_setGpioMonitorOut(mykonosDevice_t *device, uint8_t monitorIndex, uint8_t monitorMask); -mykonosGpioErr_t MYKONOS_getGpioMonitorOut(mykonosDevice_t *device, uint8_t *monitorIndex, uint8_t *monitorMask); - -/* RX GPIO Functions */ -mykonosGpioErr_t MYKONOS_setRx1GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx1GainIncPin, mykonosGpioSelect_t rx1GainDecPin, uint8_t enable); -mykonosGpioErr_t MYKONOS_setRx2GainCtrlPin(mykonosDevice_t *device, uint8_t incStep, uint8_t decStep, mykonosGpioSelect_t rx2GainIncPin, mykonosGpioSelect_t rx2GainDecPin, uint8_t enable); -mykonosGpioErr_t MYKONOS_getRx1GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx1GainIncPin, mykonosGpioSelect_t *rx1GainDecPin, uint8_t *enable); -mykonosGpioErr_t MYKONOS_getRx2GainCtrlPin(mykonosDevice_t *device, uint8_t *incStep, uint8_t *decStep, mykonosGpioSelect_t *rx2GainIncPin, mykonosGpioSelect_t *rx2GainDecPin, uint8_t *enable); - -mykonosGpioErr_t MYKONOS_setRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t rx1GainChangePin, mykonosGpioSelect_t rx2GainChangePin); -mykonosGpioErr_t MYKONOS_getRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1GainChangePin, mykonosGpioSelect_t *rx2GainChangePin); -mykonosGpioErr_t MYKONOS_setObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxGainChangePin); -mykonosGpioErr_t MYKONOS_getObsRxHybridGainChangePin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxGainChangePin); - -mykonosGpioErr_t MYKONOS_setRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t rx1AgcSyncPin, mykonosGpioSelect_t rx2AgcSyncPin); -mykonosGpioErr_t MYKONOS_getRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *rx1AgcSyncPin, mykonosGpioSelect_t *rx2AgcSyncPin); -mykonosGpioErr_t MYKONOS_setObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t obsRxAgcSyncPin); -mykonosGpioErr_t MYKONOS_getObsRxAgcEnSyncPin(mykonosDevice_t *device, mykonosGpioSelect_t *obsRxAgcSyncPin); - -/* TX GPIO Functions */ -mykonosGpioErr_t MYKONOS_setTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx1AttenIncPin, mykonosGpioSelect_t tx1AttenDecPin, uint8_t enable, uint8_t useTx1ForTx2); -mykonosGpioErr_t MYKONOS_setTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t stepSize, mykonosGpioSelect_t tx2AttenIncPin, mykonosGpioSelect_t tx2AttenDecPin, uint8_t enable); -mykonosGpioErr_t MYKONOS_getTx1AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx1AttenIncPin, mykonosGpioSelect_t *tx1AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2); -mykonosGpioErr_t MYKONOS_getTx2AttenCtrlPin(mykonosDevice_t *device, uint8_t *stepSize, mykonosGpioSelect_t *tx2AttenIncPin, mykonosGpioSelect_t *tx2AttenDecPin, uint8_t *enable, uint8_t *useTx1ForTx2); - -mykonosGpioErr_t MYKONOS_spi2GpioSetup(mykonosDevice_t *device, uint8_t enable, uint8_t updateTxAttenPinSelect); - -/* GPIO memory source Functions */ -mykonosGpioErr_t MYKONOS_setGpioPinLevel(mykonosDevice_t *device, uint32_t gpioPinLevel); -mykonosGpioErr_t MYKONOS_getGpioPinLevel(mykonosDevice_t *device, uint32_t *gpioPinLevel); -mykonosGpioErr_t MYKONOS_getGpioSetLevel(mykonosDevice_t *device, uint32_t *gpioPinSetLevel); - -/* Gain Compensation Functions */ -mykonosGpioErr_t MYKONOS_setRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t enable); -mykonosGpioErr_t MYKONOS_getRxGainCompensation (mykonosDevice_t *device, mykonosGainComp_t *gainComp, uint8_t *enabled); - -mykonosGpioErr_t MYKONOS_setObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t enable); -mykonosGpioErr_t MYKONOS_getObsRxGainCompensation (mykonosDevice_t *device, mykonosObsRxGainComp_t *gainComp, uint8_t *enabled); - -/* SLICER Functions */ -mykonosGpioErr_t MYKONOS_setRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosRxSlicer_t rx1Pins, mykonosRxSlicer_t rx2Pins, uint8_t enable); -mykonosGpioErr_t MYKONOS_getRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosRxSlicer_t *rx1Pins, mykonosRxSlicer_t *rx2Pins, uint8_t *enable); - -mykonosGpioErr_t MYKONOS_setObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t slicerStep, mykonosObsRxSlicer_t obsRxPins, uint8_t enable); -mykonosGpioErr_t MYKONOS_getObsRxSlicerCtrl(mykonosDevice_t *device, uint8_t *slicerStep, mykonosObsRxSlicer_t *obsRxPins, uint8_t *enable); - -/* Floating Point Formatter Functions */ -mykonosGpioErr_t MYKONOS_setFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt); -mykonosGpioErr_t MYKONOS_getFloatPointFrmt (mykonosDevice_t *device, mykonosFloatPntFrmt_t *floatFrmt); - -mykonosGpioErr_t MYKONOS_setRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t rx1Att, uint8_t rx2Att, uint8_t enable); -mykonosGpioErr_t MYKONOS_getRxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *rx1Att, uint8_t *rx2Att, uint8_t *enable); - -mykonosGpioErr_t MYKONOS_setOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t orxAtt, uint8_t enable); -mykonosGpioErr_t MYKONOS_getOrxEnFloatPntFrmt (mykonosDevice_t *device, uint8_t *orxAtt, uint8_t *enable); - -/* - ***************************************************************************** - * General Purpose Interrupt functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_configGpInterrupt(mykonosDevice_t *device, uint16_t gpMask); -mykonosGpioErr_t MYKONOS_readGpInterruptStatus(mykonosDevice_t *device, uint16_t *status); - -/* - ***************************************************************************** - * ARM GPIO usage functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_setArmGpioPins(mykonosDevice_t *device); - -/* - ***************************************************************************** - * AuxADC/AuxDAC functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_setupAuxAdcs(mykonosDevice_t *device, uint8_t adcDecimation, uint8_t enable); -mykonosGpioErr_t MYKONOS_setAuxAdcChannel(mykonosDevice_t *device, mykonosAuxAdcChannels_t auxAdcChannel); -mykonosGpioErr_t MYKONOS_readAuxAdc(mykonosDevice_t *device, uint16_t *adcCode); -mykonosGpioErr_t MYKONOS_setupAuxDacs(mykonosDevice_t *device); -mykonosGpioErr_t MYKONOS_writeAuxDac(mykonosDevice_t *device, uint8_t auxDacIndex, uint16_t auxDacCode); - -/* - ***************************************************************************** - * GPIO3v3 functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_setupGpio3v3(mykonosDevice_t *device); - -mykonosGpioErr_t MYKONOS_setGpio3v3PinLevel(mykonosDevice_t *device, uint16_t gpio3v3PinLevel); -mykonosGpioErr_t MYKONOS_getGpio3v3SetLevel(mykonosDevice_t *device, uint16_t *gpio3v3SetLevel); - -mykonosGpioErr_t MYKONOS_getGpio3v3PinLevel(mykonosDevice_t *device, uint16_t *gpio3v3PinLevel); - -mykonosGpioErr_t MYKONOS_setGpio3v3Oe(mykonosDevice_t *device, uint16_t gpio3v3OutEn); -mykonosGpioErr_t MYKONOS_getGpio3v3Oe(mykonosDevice_t *device, uint16_t *gpio3v3OutEn); - -mykonosGpioErr_t MYKONOS_setGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t gpio3v3SrcCtrl); -mykonosGpioErr_t MYKONOS_getGpio3v3SourceCtrl(mykonosDevice_t *device, uint16_t *gpio3v3SrcCtrl); - -/* - ***************************************************************************** - * GPIO helper functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_setupGpio(mykonosDevice_t *device); -mykonosGpioErr_t MYKONOS_setGpioOe(mykonosDevice_t *device, uint32_t gpioOutEn, uint32_t gpioUsedMask); -mykonosGpioErr_t MYKONOS_getGpioOe(mykonosDevice_t *device, uint32_t *gpioOutEn); - -mykonosGpioErr_t MYKONOS_setGpioSourceCtrl(mykonosDevice_t *device, uint32_t gpioSrcCtrl); -mykonosGpioErr_t MYKONOS_getGpioSourceCtrl(mykonosDevice_t *device, uint32_t *gpioSrcCtrl); - -/* - ***************************************************************************** - * Temperature Sensor functions - ***************************************************************************** - */ -mykonosGpioErr_t MYKONOS_setupTempSensor(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor); -mykonosGpioErr_t MYKONOS_getTempSensorConfig(mykonosDevice_t *device, mykonosTempSensorConfig_t *tempSensor); - -mykonosGpioErr_t MYKONOS_startTempMeasurement(mykonosDevice_t *device); -mykonosGpioErr_t MYKONOS_readTempSensor(mykonosDevice_t *device, mykonosTempSensorStatus_t *tempStatus); - -const char* getGpioMykonosErrorMessage(mykonosGpioErr_t errorCode); - -#ifdef __cplusplus -} -#endif - -#endif /* MYKONOSGPIO_H_ */ diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_macros.h b/df_datalink_ge/src/hardware/mykonos/mykonos_macros.h deleted file mode 100644 index 354f561..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_macros.h +++ /dev/null @@ -1,707 +0,0 @@ -/** - * \file mykonos_macros.h - * \brief Contains address and miscellaneous macro definitions for Mykonos API - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef CLEMENTE_TDD_MACROS_H -#define CLEMENTE_TDD_MACROS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define MYKONOS_ADDR_CONFIGURATION_CONTROL_0 0x000 -#define MYKONOS_ADDR_SPI_CONFIGURATION_CONTROL_1 0x001 -#define MYKONOS_ADDR_PRODUCT_ID 0x004 -#define MYKONOS_GPIO_DRV_CTL_0 0x020 -#define MYKONOS_GPIO_DRV_CTL_1 0x021 -#define MYKONOS_GPIO_SLEW_CTL_0 0x022 -#define MYKONOS_GPIO_SLEW_CTL_1 0x023 -#define MYKONOS_GPIO_SLEW_CTL_2 0x024 -#define MYKONOS_GPIO_SLEW_CTL_3 0x025 - -#define MYKONOS_ADDR_DIGITAL_IO_CONTROL 0x028 - -#define MYKONOS_ADDR_SYSREF_PAD_CONFIG 0x040 -#define MYKONOS_ADDR_TX1_SYNC_PAD_CONFIG 0x041 -#define MYKONOS_ADDR_TX2_SYNC_PAD_CONFIG 0x042 -#define MYKONOS_ADDR_RX1_SYNC_CONFIG 0x043 -#define MYKONOS_ADDR_RX2_SYNC_CONFIG 0x044 - -/* Mykonos Framer Registers */ -#define MYKONOS_ADDR_FRAMER_RESET 0x059 -#define MYKONOS_ADDR_FRAMER_CLK_EN 0x05A -#define MYKONOS_ADDR_FRAMER_ADDR 0x05B -#define MYKONOS_ADDR_FRAMER_DATA 0x05C -#define MYKONOS_ADDR_FRAMER_WRITE_EN 0x05D -#define MYKONOS_ADDR_FRAMER_SYSREF_FIFO_EN 0x05E -#define MYKONOS_ADDR_FRAMER_CONFIG_F 0x05F -#define MYKONOS_ADDR_FRAMER_LANE_CTL 0x060 -#define MYKONOS_ADDR_FRAMER_ADC_XBAR_SEL 0x061 -#define MYKONOS_ADDR_FRAMER_LANE_XBAR_SEL 0x062 -#define MYKONOS_ADDR_FRAMER_CONFIG_LOOPBACK_XBAR_REV 0x063 -#define MYKONOS_ADDR_FRAMER_SYNCN_FILT 0x064 -#define MYKONOS_ADDR_FRAMER_LMFC_F_OFFSET 0x065 -#define MYKONOS_ADDR_FRAMER_LMFC_K_OFFSET 0x066 -#define MYKONOS_ADDR_FRAMER_TEST_CNTR_CTL 0x067 -#define MYKONOS_ADDR_FRAMER_STATUS_STRB 0x068 -#define MYKONOS_ADDR_FRAMER_STATUS 0x069 -#define MYKONOS_ADDR_FRAMER_SYSREF_TO_LMFC_CNTR_STAT 0x06A -#define MYKONOS_ADDR_FRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0x06B -#define MYKONOS_ADDR_FRAMER_LANE_FIFO_STRB 0x06C -#define MYKONOS_ADDR_FRAMER_LANE0_FIFO_RDWR_ADDR 0x06D -#define MYKONOS_ADDR_FRAMER_LANE1_FIFO_RDWR_ADDR 0x06E -#define MYKONOS_ADDR_FRAMER_LANE2_FIFO_RDWR_ADDR 0x06F -#define MYKONOS_ADDR_FRAMER_LANE3_FIFO_RDWR_ADDR 0x070 -#define MYKONOS_ADDR_FRAMER_PRBS10_CTL 0x071 -#define MYKONOS_ADDR_FRAMER_PRBS20_CTL 0x072 -#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_EN 0x073 -#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_7_TO_0 0x074 -#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_15_TO_8 0x075 -#define MYKONOS_ADDR_FRAMER_PATTERN_GEN_19_TO_16 0x076 -#define MYKONOS_ADDR_FRAMER_CONFIG_JTX_GEN 0x077 -#define MYKONOS_ADDR_FRAMER_LANE_DATA_CTL 0x078 -#define MYKONOS_ADDR_FRAMER_DATA_SAMPLE_CTL 0x079 - -/* Mykonos Deframer Sub Address Map */ -#define MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_RECVD 0x00 -#define MYKONOS_SUBADDR_DEFRAMER_LANE0_ILAS_CFG 0x50 - -/* Mykonos Deframer Registers */ -#define MYKONOS_ADDR_DEFRAMER_RESET 0x07A -#define MYKONOS_ADDR_DEFRAMER_CLK_EN 0x07B -#define MYKONOS_ADDR_DEFRAMER_ADDR 0x07C -#define MYKONOS_ADDR_DEFRAMER_DATA 0x07D -#define MYKONOS_ADDR_DEFRAMER_WR_EN 0x07E -#define MYKONOS_ADDR_DEFRAMER_SYSREF_FIFO_EN 0x07F -#define MYKONOS_ADDR_DEFRAMER_CONFIG_F 0x080 -#define MYKONOS_ADDR_DEFRAMER_LANE_FIFO_CTL 0x081 -#define MYKONOS_ADDR_DEFRAMER_DAC_XBAR_SEL 0x082 -#define MYKONOS_ADDR_DEFRAMER_LANE_XBAR_SEL 0x083 -#define MYKONOS_ADDR_DEFRAMER_LMFC_F_OFFSET 0x084 -#define MYKONOS_ADDR_DEFRAMER_LMFC_K_OFFSET 0x085 -#define MYKONOS_ADDR_DEFRAMER_CONFIG_SYNC_USER_DATA_CTL 0x086 -#define MYKONOS_ADDR_DEFRAMER_SYNC_REQ_RETIME 0x087 -#define MYKONOS_ADDR_DEFRAMER_TEST 0x088 -#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_STRT_DAC_XBAR_REV 0x089 -#define MYKONOS_ADDR_DEFRAMER_STAT_STRB 0x08A -#define MYKONOS_ADDR_DEFRAMER_STAT 0x08B -#define MYKONOS_ADDR_DEFRAMER_TEST_ERR_CNT_STAT 0x08C -#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_RD_ADDR 0x08D -#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_WR_ADDR 0x08E -#define MYKONOS_ADDR_DEFRAMER_QBLMFC_VS_EXTLMFC_CNTR_STAT 0x08F -#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_STAT 0x090 -#define MYKONOS_ADDR_DEFRAMER_STRT_RD_DEL_STOP_WR 0x091 -#define MYKONOS_ADDR_DEFRAMER_FIFO_SAMPLE_SPI_ADDR_RD 0x092 -#define MYKONOS_ADDR_DEFRAMER_FIFO_BYTE_SPI_ADDR_RD 0x093 -#define MYKONOS_ADDR_DEFRAMER_FIFO_BYTE_SPI_DATA_RD 0x094 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE0_7_TO_0 0x095 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE0_15_TO_8 0x096 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE1_7_TO_0 0x097 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE1_15_TO_8 0x098 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE2_7_TO_0 0x099 -#define MYKONOS_ADDR_DEFRAMER_SAMPLE2_15_TO_8 0x09A -#define MYKONOS_ADDR_DEFRAMER_SAMPLE3_7_TO_0 0x09B -#define MYKONOS_ADDR_DEFRAMER_SAMPLE3_15_TO_8 0x09C -#define MYKONOS_ADDR_DEFRAMER_LANE_FIFO_STRB 0x09D -#define MYKONOS_ADDR_DEFRAMER_LANE0_FIFO_RDWR_ADDR 0x09E -#define MYKONOS_ADDR_DEFRAMER_LANE1_FIFO_RDWR_ADDR 0x09F -#define MYKONOS_ADDR_DEFRAMER_LANE2_FIFO_RDWR_ADDR 0x0A0 -#define MYKONOS_ADDR_DEFRAMER_LANE3_FIFO_RDWR_ADDR 0x0A1 -#define MYKONOS_ADDR_DEFRAMER_SYSREF_TO_LMFC_CNTR_STAT 0x0A2 -#define MYKONOS_ADDR_DEFRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0x0A3 -#define MYKONOS_ADDR_DEFRAMER_PRBS10_CTL 0x0A4 -#define MYKONOS_ADDR_DEFRAMER_PRBS20_CTL 0x0A5 -#define MYKONOS_ADDR_DEFRAMER_PRBS20_STRB_CHKSUM_TYPE 0x0A6 -#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_7_TO_0 0x0A7 -#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_15_TO_8 0x0A8 -#define MYKONOS_ADDR_DEFRAMER_PRBS20_ERR_CNTR_23_TO_16 0x0A9 -#define MYKONOS_ADDR_DEFRAMER_LANE_DATA_CTL 0x0AA -#define MYKONOS_ADDR_DEFRAMER_STATUS_2 0x0AB -#define MYKONOS_ADDR_DEFRAMER_DET_FIFO_PHASE 0x0AC - -/* Mykonos Serializer Registers */ -#define MYKONOS_ADDR_SERIALIZER_CTL_0 0x0B0 -#define MYKONOS_ADDR_SERIALIZER_CTL_1 0x0B1 -#define MYKONOS_ADDR_SERIALIZER_CTL_2 0x0B2 -#define MYKONOS_ADDR_SERIALIZER_CTL_3 0x0B3 -#define MYKONOS_ADDR_SERIALIZER_HS_DIV_TXSER_CLK_EN 0x0B4 -#define MYKONOS_ADDR_SERIALIZER_SPECIAL 0x0B5 - -/* Mykonos Deserializer Registers */ -#define MYKONOS_ADDR_DESERIALIZER_PDET_CTL 0x0BC -#define MYKONOS_ADDR_DESERIALIZER_CTL_0 0x0BD -#define MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_0 0x0BE -#define MYKONOS_ADDR_DESERIALIZER_SIN_SHAPE_1 0x0BF -#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_0 0x0C1 -#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1 0x0C2 -#define MYKONOS_ADDR_DESERIALIZER_MISC_CTL 0x0C3 -#define MYKONOS_ADDR_DESERIALIZER_EQ_HP_EN 0x0C4 -#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_1_TO_0 0x0C5 -#define MYKONOS_ADDR_DESERIALIZER_EQ_CTL_3_TO_2 0x0C6 -#define MYKONOS_ADDR_DESERIALIZER_HS_DIV_RXCDR_CLK_EN 0x0CD -#define MYKONOS_ADDR_DESERIALIZER_SPECIAL 0x0CE -#define MYKONOS_ADDR_DESERIALIZER_CDR_CAL_CTL 0x0D0 - -#define MYKONOS_ADDR_CONFIGURATION_CONTROL_1 0x100 -#define MYKONOS_ADDR_CONFIGURATION_CONTROL_2 0x101 -#define MYKONOS_ADDR_CONFIGURATION_CONTROL_4 0x102 -#define MYKONOS_ADDR_CONFIGURATION_CONTROL_5 0x103 -#define MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_1 0x104 -#define MYKONOS_ADDR_DPD_SNIFFER_CONFIGURATION_CONTROL_2 0x105 -#define MYKONOS_ADDR_DPD_SNIFFER_GPIO_SELECT 0x106 -#define MYKONOS_ADDR_SNIFFER_CONFIGURATION_CONTROL 0x107 -#define MYKONOS_ADDR_DPD_CONFIGURATION_CONTROL 0x108 -#define MYKONOS_ADDR_LOOPBACK_CONFIGURATION_CONTROL 0x109 - -#define MYKONOS_ADDR_CLOCK_CONTROL_0 0x117 -#define MYKONOS_ADDR_CLOCK_CONTROL_1 0x118 -#define MYKONOS_ADDR_CLOCK_CONTROL_2 0x119 -#define MYKONOS_ADDR_CLOCK_CONTROL_3 0x11A -#define MYKONOS_ADDR_CLOCK_CONTROL_4 0x11B -#define MYKONOS_ADDR_CLOCK_CONTROL_5 0x11C - -#define MYKONOS_ADDR_MCS_CONTROL 0x120 -#define MYKONOS_ADDR_MCS_STATUS 0x121 - -/* CLK PLL Registers */ -#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE0 0x141 -#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_INT_BYTE1 0x142 -#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE0 0x143 -#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE1 0x144 -#define MYKONOS_ADDR_CLK_SYNTH_DIVIDER_FRAC_BYTE2 0x145 -#define MYKONOS_ADDR_CLK_SYNTH_F_VCOTN_BYTE1 0x148 -#define MYKONOS_ADDR_CLK_SYNTH_BYTE1 0x149 -#define MYKONOS_ADDR_CLK_SYNTH_BYTE2 0x14A -#define MYKONOS_ADDR_CLK_SYNTH_BYTE3 0x14B -#define MYKONOS_ADDR_CLK_SYNTH_BYTE5 0x14D -#define MYKONOS_ADDR_CLK_SYNTH_BYTE6 0x14E -#define MYKONOS_ADDR_CLK_SYNTH_BYTE7 0x14F -#define MYKONOS_ADDR_CLK_SYNTH_LF_R3 0x150 -#define MYKONOS_ADDR_CLK_SYNTH_BYTE9 0x152 -#define MYKONOS_ADDR_CLK_SYNTH_CAL_STAT 0x154 -#define MYKONOS_ADDR_CLK_SYNTH_VCO_CAL_REF 0x155 -#define MYKONOS_ADDR_CLK_SYNTH_VCO_BAND_BYTE1 0x157 -#define MYKONOS_ADDR_CLK_SYNTH_CAL_CONTROL 0x159 -#define MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL1 0x15E -#define MYKONOS_ADDR_CLK_SYNTH_VCO_VAR_CTL2 0x15F - -/* DPD Registers */ -#define MYKONOS_ADDR_TX1_DPD_MODEL_INDIRECT_PTR 0x178 -#define MYKONOS_ADDR_TX2_DPD_MODEL_INDIRECT_PTR 0x17C -#define MYKONOS_ADDR_DPD_RMS_BUF_SIZE 0x180 -#define MYKONOS_ADDR_TX1_DPD_MODEL_WORKING_PTR 0x188 -#define MYKONOS_ADDR_TX2_DPD_MODEL_WORKING_PTR 0x18C - -/* Rx NCO Control registers */ -#define MYKONOS_ADDR_CALPLL_SDM_CONTROL 0x17F -#define MYKONOS_ADDR_RX_NCO_CONTROL 0x190 -#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_3 0x191 -#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_2 0x192 -#define MYKONOS_ADDR_RX_NCO_CH1_FTW_BYTE_1 0x193 -#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_3 0x194 -#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_2 0x195 -#define MYKONOS_ADDR_RX_NCO_CH2_FTW_BYTE_1 0x196 -#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_3 0x197 -#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_2 0x198 -#define MYKONOS_ADDR_RX_NCO_DPD_SNIFFER_FTW_BYTE_1 0x199 - -#define MYKONOS_ADDR_ENSM_CONFIG_7_0 0x1B0 -#define MYKONOS_ADDR_CALIBRATION_CONTROL 0x1B2 -#define MYKONOS_ADDR_ENSM_MANUAL_GAIN_LOCK_GPIO_SELECT 0x1B5 -#define MYKONOS_ADDR_REFERENCE_CLOCK_CYCLES 0x1C0 -#define MYKONOS_ADDR_TX_PD_OVERIDE_7_0 0x209 -#define MYKONOS_ADDR_RCAL_CONTROL 0x224 -#define MYKONOS_ADDR_REF_PAD_CONFIG1 0x230 -#define MYKONOS_ADDR_REF_PAD_CONFIG2 0x231 - -#define MYKONOS_ADDR_RXSYNTH_CP_CAL_STAT 0x254 -#define MYKONOS_ADDR_RXSYNTH_VCO_BAND_BYTE1 0x257 -#define MYKONOS_ADDR_TXSYNTH_CP_CAL_STAT 0x2C4 -#define MYKONOS_ADDR_TXSYNTH_VCO_BAND_BYTE1 0x2C7 -#define MYKONOS_ADDR_SNIFF_RXSYNTH_CP_CAL_STAT 0x354 -#define MYKONOS_ADDR_SNIFF_RXSYNTH_VCO_BAND_BYTE1 0x357 -#define MYKONOS_ADDR_SNIFF_RXLOGEN_BYTE1 0x380 - -#define MYKONOS_ADDR_RX_FILTER_CONFIGURATION 0x410 -#define MYKONOS_ADDR_RX_FILTER_GAIN 0x411 -#define MYKONOS_ADDR_DPD_SNIFFER_RX_FILTER_GAIN 0x412 - -/* Mykonos Temperature Gain Compensation Registers */ -#define MYKONOS_ADDR_RX1_TEMP_GAIN_COMP 0x420 -#define MYKONOS_ADDR_RX2_TEMP_GAIN_COMP 0x421 -#define MYKONOS_ADDR_OBS_TEMP_GAIN_COMP 0x422 - -/* Mykonos AGC General Registers */ -#define MYKONOS_ADDR_AGC_CFG_1 0x42E -#define MYKONOS_ADDR_AGC_CFG_2 0x42F -#define MYKONOS_ADDR_AGC_GAIN_CHANGE_GPIO_SEL 0x430 -#define MYKONOS_ADDR_AGC_RX1_MAX_GAIN_INDEX 0x431 -#define MYKONOS_ADDR_AGC_RX1_MIN_GAIN_INDEX 0x432 -#define MYKONOS_ADDR_AGC_MANUAL_GAIN_CFG 0x433 -#define MYKONOS_ADDR_AGC_MANUAL_GAIN_GPIO_SEL 0x434 -#define MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_1 0x435 -#define MYKONOS_ADDR_AGC_MANUAL_GAIN_INDEX_CH_2 0x436 -#define MYKONOS_ADDR_AGC_LOCK_LEVEL 0x437 -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_1 0x438 -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_2 0x439 -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_3 0x43A -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_4 0x43B -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_5 0x43C -#define MYKONOS_ADDR_AGC_OVRG_GAIN_STEP_6 0x43D -#define MYKONOS_ADDR_AGC_RX1_GAIN_LOCK_DELAY 0x43E -#define MYKONOS_ADDR_AGC_RX2_GAIN_LOCK_DELAY 0x43F -#define MYKONOS_ADDR_AGC_RX1_ATTACK_DELAY 0x440 -#define MYKONOS_ADDR_AGC_RX2_ATTACK_DELAY 0x441 -#define MYKONOS_ADDR_AGC_ULB_THRSH 0x442 -#define MYKONOS_ADDR_AGC_LLB_THRSH 0x443 -#define MYKONOS_ADDR_AGC_RX_BLOCK_DET_DECAY 0x444 -#define MYKONOS_ADDR_AGC_RESET_PD_HIGH_CNT 0x445 -#define MYKONOS_ADDR_AGC_RX2_MAX_GAIN_INDEX 0x446 -#define MYKONOS_ADDR_AGC_RX2_MIN_GAIN_INDEX 0x447 -#define MYKONOS_ADDR_AGC_ORX_SNRX_CFG_1 0x448 -#define MYKONOS_ADDR_AGC_ORX_SNRX_CFG_2 0x449 -#define MYKONOS_ADDR_AGC_ORX_SNRX_MAX_GAIN_INDEX 0x44A -#define MYKONOS_ADDR_AGC_ORX_SNRX_MIN_GAIN_INDEX 0x44B -#define MYKONOS_ADDR_AGC_ORX_SNRX_MANUAL_GAIN_CFG 0x44C -#define MYKONOS_ADDR_AGC_ORX_SNRX_GPIO_SEL 0x44D -#define MYKONOS_ADDR_AGC_ORX_SNRX_LOCK_LEVEL 0x44E -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_1 0x44F -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_2 0x450 -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_3 0x451 -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_4 0x452 -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_5 0x453 -#define MYKONOS_ADDR_AGC_ORX_SNRX_OVRG_GAIN_STEP_6 0x454 -#define MYKONOS_ADDR_AGC_ORX_SNRX_GAIN_LOCK_DELAY 0x455 -#define MYKONOS_ADDR_AGC_ORX_SNRX_ATTACK_DELAY 0x456 -#define MYKONOS_ADDR_AGC_ORX_SNRX_ULB_THRSH 0x457 -#define MYKONOS_ADDR_AGC_ORX_SNRX_LLB_THRSH 0x458 -#define MYKONOS_ADDR_AGC_ORX_SNRX_BLOCK_DET_DECAY 0x459 -#define MYKONOS_ADDR_AGC_ORX_SNRX_RESET_PD_HIGH_CNT 0x45A -#define MYKONOS_ADDR_AGC_ORX1_MANUAL_GAIN_INDEX 0x45B -#define MYKONOS_ADDR_AGC_ORX2_MANUAL_GAIN_INDEX 0x45C -#define MYKONOS_ADDR_AGC_SNRX_MANUAL_GAIN_INDEX 0x45D -#define MYKONOS_ADDR_AGC_LOOPBACK1_MANUAL_GAIN_INDEX 0x45E -#define MYKONOS_ADDR_AGC_LOOPBACK2_MANUAL_GAIN_INDEX 0x45F -#define MYKONOS_ADDR_AGC_ORX_SNRX_ACTIVE 0x460 - -/* Mykonos Fast Attack AGC Registers */ -#define MYKONOS_ADDR_AGC_FAST_CFG_1 0x468 -#define MYKONOS_ADDR_AGC_FAST_CFG_2 0x469 -#define MYKONOS_ADDR_AGC_FAST_ENRGY_LOST_THRSH 0x46A -#define MYKONOS_ADDR_AGC_FAST_STRONG_SIG_THRSH 0x46B -#define MYKONOS_ADDR_AGC_FAST_SETTING_DELAY 0x46C -#define MYKONOS_ADDR_AGC_FAST_OPT_MAX_GAIN 0x46D -#define MYKONOS_ADDR_AGC_FAST_ENRGY_DET_CNT 0x46E -#define MYKONOS_ADDR_AGC_FAST_AGCLL_UPPER_LIMIT 0x46F -#define MYKONOS_ADDR_AGC_FAST_GAIN_LOCK_EXIT_CNT 0x470 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_CFG_1 0x471 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_CFG_2 0x472 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_ENRGY_LOST_THRSH 0x473 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_STRONG_SIG_THRSH 0x474 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_SET_DELAY 0x475 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_OPT_MAX_GAIN 0x476 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_ENRGY_DET_CNT 0x477 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_AGCLL_UPPER_LIMIT 0x478 -#define MYKONOS_ADDR_AGC_FAST_ORX_SNRX_GAIN_LOCK_EXIT_CNT 0x479 - -/* Mykonos Slow Loop - Hybrid AGC Registers */ -#define MYKONOS_ADDR_AGC_SLOW_LOCK_LEV_THRSH 0x480 -#define MYKONOS_ADDR_AGC_SLOW_ULB_CNT_THRSH 0x481 -#define MYKONOS_ADDR_AGC_SLOW_LLB_CNT_THRSH 0x482 -#define MYKONOS_ADDR_AGC_SLOW_HIGH_OVRG_CNT_THRSH 0x483 -#define MYKONOS_ADDR_AGC_SLOW_LOW_OVRG_CNT_THRSH 0x484 -#define MYKONOS_ADDR_AGC_SLOW_VERYLOW_OVRG_CNT_THRSH 0x485 -#define MYKONOS_ADDR_AGC_SLOW_DIG_SAT_CNT_THRSH 0x486 -#define MYKONOS_ADDR_AGC_SLOW_UPPER0_THRSH_GAIN_STEP 0x487 -#define MYKONOS_ADDR_AGC_SLOW_LOWER0_THRSH_GAIN_STEP 0x488 -#define MYKONOS_ADDR_AGC_SLOW_UPPER1_THRSH_GAIN_STEP 0x489 -#define MYKONOS_ADDR_AGC_SLOW_LOWER1_THRSH_GAIN_STEP 0x48A -#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_1 0x48B -#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_2 0x48C -#define MYKONOS_ADDR_AGC_SLOW_GAIN_UPDATE_CNT_3 0x48D -#define MYKONOS_ADDR_AGC_SLOW_LOOP_CFG 0x48E -#define MYKONOS_ADDR_AGC_SLOW_POWER_THRSH 0x48F -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOCK_LEV_THRSH 0x490 - -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ULB_CNT_THRSH 0x491 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LLB_CNT_THRSH 0x492 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_HIGH_OVRG_CNT_THRSH 0x493 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_LOW_OVRG_CNT_THRSH 0x494 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_ADC_VERYLOW_OVRG_CNT_THRSH 0x495 - -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_DIG_SAT_CNT_THRSH 0x496 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER0_THRSH_GAIN_STEP 0x497 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER0_THRSH_GAIN_STEP 0x498 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UPPER1_THRSH_GAIN_STEP 0x499 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOWER1_THRSH_GAIN_STEP 0x49A -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_1 0x49B -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_2 0x49C -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_GAIN_UPDATE_CTR_3 0x49D -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_LOOP_CFG 0x49E -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_POWER_THRSH 0x49F -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DEL_1 0x4A0 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DEL_2 0x4A1 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DUR_1 0x4A2 -#define MYKONOS_ADDR_AGC_SLOW_ORX_SNRX_UL_SIG_POW_MEAS_DUR_2 0x4A3 - -/* Mykonos Gain Control Read Registers */ -#define MYKONOS_ADDR_GAIN_CTL_CHANNEL_1 0x4B0 -#define MYKONOS_ADDR_GAIN_CTL_FAST_ATTK_STATE 0x4B1 -#define MYKONOS_ADDR_GAIN_CTL_SLOW_LOOP_STATE 0x4B2 -#define MYKONOS_ADDR_GAIN_CTL_CHANNEL_2 0x4B3 -#define MYKONOS_ADDR_GAIN_CTL_OVRG_SIGS_CHANNEL_1 0x4B4 -#define MYKONOS_ADDR_GAIN_CTL_OVRG_SIGS_CHANNEL_2 0x4B5 -#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_GAIN 0x4B6 -#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_LOOP_STATE 0x4B7 -#define MYKONOS_ADDR_GAIN_CTL_ORX_SNRX_OVRG_SIGS 0x4B8 - -/* Mykonos Rx Data Path Overrange Registers */ -#define MYKONOS_ADDR_RX_OVRG_DATAPATH_OVRFLW 0x4B9 -#define MYKONOS_ADDR_RX_OVRG_ORX_SNRX_DATAPATH_OVRFLW 0x4BA - -/* Mykonos RSSI Measurement Registers and Dec Power Measurement Registers*/ -#define MYKONOS_ADDR_RSSI_MEAS_DURATION_0_1 0x4C0 -#define MYKONOS_ADDR_RSSI_MEAS_DURATION_2_3 0x4C1 -#define MYKONOS_ADDR_RSSI_CFG 0x4C6 -#define MYKONOS_DEC_POWER_CONFIG_1 0x4C7 -#define MYKONOS_DEC_POWER_CONFIG_2 0x4C8 -#define MYKONOS_ADDR_DPD_SNF_RSSI_CFG 0x4CF -#define MYKONOS_ADDR_DPD_RSSI_CFG 0x4D6 -#define MYKONOS_SNIFFER_DEC_POWER_CONFIG_1 0x4D7 -#define MYKONOS_SNIFFER_DEC_POWER_CONFIG_2 0x4D8 -#define MYKONOS_CH1_DECIMATED_PWR 0x4DE -#define MYKONOS_CH2_DECIMATED_PWR 0x4DF -#define MYKONOS_SNIFFER_DECIMATED_PWR 0x4E6 - -#define MYKONOS_ADDR_DIGITAL_GAIN_CONFIG 0x4F0 -#define MYKONOS_ADDR_DPD_SNIFFER_DIGITAL_GAIN_CONFIG 0x4F1 -#define MYKONOS_ADDR_GAIN_TABLE_ADDR 0x500 -#define MYKONOS_ADDR_GAIN_TABLE_RX1_FE_GAIN 0x501 -#define MYKONOS_ADDR_GAIN_TABLE_RX1_EXT_CTL 0x502 -#define MYKONOS_ADDR_GAIN_TABLE_RX1_DIG_GAIN 0x503 -#define MYKONOS_ADDR_GAIN_TABLE_RX2_FE_GAIN 0x504 -#define MYKONOS_ADDR_GAIN_TABLE_RX2_EXT_CTL 0x505 -#define MYKONOS_ADDR_GAIN_TABLE_RX2_DIG_GAIN 0x506 -#define MYKONOS_ADDR_GAIN_TABLE_RX3_FE_GAIN 0x507 -#define MYKONOS_ADDR_GAIN_TABLE_RX3_LNA_ENAB 0x508 -#define MYKONOS_ADDR_GAIN_TABLE_RX3_DIG_GAIN 0x509 -#define MYKONOS_ADDR_GAIN_TABLE_CONFIGURATION 0x516 -#define MYKONOS_ADDR_CH3_GAIN_TABLE_CONFIGURATION 0x517 -#define MYKONOS_ADDR_RXFE1_LOCM 0x520 -#define MYKONOS_ADDR_RXFE2_LOCM 0x521 -#define MYKONOS_ADDR_RXLOOPBACK1_CNTRL_1 0x540 -#define MYKONOS_ADDR_RXLOOPBACK2_CNTRL_1 0x541 -#define MYKONOS_ADDR_RX_LOOPBACK1_CNTRL_4 0x546 -#define MYKONOS_ADDR_RX_LOOPBACK2_CNTRL_4 0x547 - -/* Mykonos Overload/Peak Detection Registers */ -#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_CFG 0x580 -#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_UPPER_THRSH 0x581 -#define MYKONOS_ADDR_OVRLD_ADC_OVRLD_LOWER_THRSH 0x582 - -#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_CFG 0x583 -#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_UPPER_THRSH 0x584 -#define MYKONOS_ADDR_OVRLD_PD_DEC_OVRLD_LOWER_THRSH 0x585 -#define MYKONOS_ADDR_OVRLD_PD_DEC_VERYLOW_THRSH 0x586 -#define MYKONOS_ADDR_ORX_SNRX_OVRLD_ADC_OVRLD_CFG 0x587 -#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_CFG 0x58A -#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_UPPER_THRSH 0x58B -#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_LOWER_THRSH 0x58C -#define MYKONOS_ADDR_ORX_SNRX_OVRLD_PD_DEC_OVRLD_VERYLOW_THRSH 0x58D - -#define MYKONOS_ADDR_RX_ADC_FLASH_DELAY 0x5B6 -#define MYKONOS_ADDR_RX_ADC_FLASH_CTRL 0x5B7 -#define MYKONOS_ADDR_RX_ADC1_PRFL 0x5DD -#define MYKONOS_ADDR_RX_ADC2_PRFL 0x5DE -#define MYKONOS_ADDR_ORX_ADC_PRFL 0x5DF - -#define MYKONOS_ADDR_RFDC_MEASURE_COUNT_1 0x631 -#define MYKONOS_ADDR_RFDC_MEASURE_COUNT_2 0x632 -#define MYKONOS_ADDR_RFDC_PROGRAM_SHIFT 0x635 -#define MYKONOS_ADDR_RFDC_CONFIG2 0x636 -#define MYKONOS_DPD_Sniffer_RFDC_CAL_TRACK_EN 0x642 -#define MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_1 0x644 -#define MYKONOS_ADDR_RFDC_SNF_MEASURE_COUNT_2 0x645 -#define MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_1 0x650 -#define MYKONOS_ADDR_RFDC_ORX_MEASURE_COUNT_2 0x651 -#define MYKONOS_ADDR_DIGITAL_DC_MIN_CAL_IDX 0x63A -#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_SHIFT 0x674 -#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_CONFIG 0x676 -#define MYKONOS_DIGITAL_DC_OFFSET_CH3_TRACKING 0x67A -#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_SNF 0x67C -#define MYKONOS_ADDR_DIGITAL_DC_OFFSET_CH3_DPD_M_SHIFT 0x67D - -#define MYKONOS_ADDR_RX_GAIN_COMP_DELAY 0x710 -#define MYKONOS_ADDR_RX1_GAIN_COMP_OFFSET 0x711 -#define MYKONOS_ADDR_RX2_GAIN_COMP_OFFSET 0x712 -#define MYKONOS_ADDR_RX_GAIN_COMP_CFG 0x713 -#define MYKONOS_ADDR_RX_SLCR_PIN_CFG 0x714 -#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_DELAY 0x715 -#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_OFFSET 0x716 -#define MYKONOS_ADDR_DPD_SNF_RX_GAIN_COMP_CFG 0x717 -#define MYKONOS_ADDR_DPD_SNF_RX_SLCR_PIN_CFG 0x718 - -#define MYKONOS_ADDR_FLOATING_POINT_CFG 0x750 -#define MYKONOS_ADDR_FLOATING_POINT_RX_CTRL 0x751 -#define MYKONOS_ADDR_FLOATING_POINT_ORX_CTRL 0x752 - - -#define MYKONOS_ADDR_SNRX_LNA_BIAS_C 0x81B - - -#define MYKONOS_ADDR_ORX_ADC_FLASH_DELAY 0x846 -#define MYKONOS_ADDR_ORX_ADC_FLASH_CTRL 0x847 - -#define MYKONOS_ADDR_TX_FILTER_CONFIGURATION 0x910 -#define MYKONOS_ADDR_TX1_ATTENUATION_0_READBACK 0x940 -#define MYKONOS_ADDR_TX1_ATTENUATION_1_READBACK 0x941 -#define MYKONOS_ADDR_TX2_ATTENUATION_0_READBACK 0x942 -#define MYKONOS_ADDR_TX2_ATTENUATION_1_READBACK 0x943 -#define MYKONOS_ADDR_TX_FILTER_OVERFLOW 0x950 - -/* Mykonos PA Protection Block Registers */ -#define MYKONOS_ADDR_PA_PROTECTION_CONFIGURATION 0x955 -#define MYKONOS_ADDR_PA_PROTECTION_ATTEN_CONTROL 0x956 -#define MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_LSB 0x957 -#define MYKONOS_ADDR_PA_PROTECTION_THRESHOLD_MSB 0x958 -#define MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_LSB 0x959 -#define MYKONOS_ADDR_PA_PROTECTION_POWER_READBACK_MSB 0x95A -#define MYKONOS_ADDR_TX1_ATTENUATION_0 0x960 -#define MYKONOS_ADDR_TX1_ATTENUATION_1 0x961 -#define MYKONOS_ADDR_TX2_ATTENUATION_0 0x962 -#define MYKONOS_ADDR_TX2_ATTENUATION_1 0x963 -#define MYKONOS_ADDR_TX1_GAIN_0 0x967 -#define MYKONOS_ADDR_TX1_GAIN_1 0x968 -#define MYKONOS_ADDR_TX1_GAIN_2 0x969 -#define MYKONOS_ADDR_TX2_GAIN_0 0x96A -#define MYKONOS_ADDR_TX2_GAIN_1 0x96B -#define MYKONOS_ADDR_TX2_GAIN_2 0x96C -#define MYKONOS_ADDR_TX_INCR_DECR_WORD 0x96D -#define MYKONOS_ADDR_TX_TPC_CONFIG 0x96E -#define MYKONOS_ADDR_TX_TPC_GPIO_CFG 0x96F - -#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_MSB 0x9CB -#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_I_LSB 0x9CC -#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_MSB 0x9CD -#define MYKONOS_ADDR_TX_ABBF_FREQ_CAL_NCO_Q_LSB 0x9CE - -/* Mykonos GPIO Registers */ -#define MYKONOS_ADDR_GPIO_3V3_DIR_CTL_7_0 0xB00 -#define MYKONOS_ADDR_GPIO_3V3_DIR_CTL_15_8 0xB01 -#define MYKONOS_ADDR_GPIO_3V3_SPI_SRC_7_0 0xB02 -#define MYKONOS_ADDR_GPIO_3V3_SPI_SRC_15_8 0xB03 -#define MYKONOS_ADDR_GPIO_3V3_SPI_READ_7_0 0xB04 -#define MYKONOS_ADDR_GPIO_3V3_SPI_READ_15_8 0xB05 -#define MYKONOS_ADDR_GPIO_3V3_LSB_SRC_CTL 0xB06 -#define MYKONOS_ADDR_GPIO_3V3_MSB_SRC_CTL 0xB07 - -#define MYKONOS_ADDR_GPIO_DIR_CTL_7_0 0xB20 -#define MYKONOS_ADDR_GPIO_DIR_CTL_15_8 0xB21 -#define MYKONOS_ADDR_GPIO_DIR_CTL_18_16 0xB22 -#define MYKONOS_ADDR_GPIO_SPI_SRC_7_0 0xB23 -#define MYKONOS_ADDR_GPIO_SPI_SRC_15_8 0xB24 -#define MYKONOS_ADDR_GPIO_SPI_SRC_18_16 0xB25 -#define MYKONOS_ADDR_GPIO_SPI_READ_7_0 0xB26 -#define MYKONOS_ADDR_GPIO_SPI_READ_15_8 0xB27 -#define MYKONOS_ADDR_GPIO_SPI_READ_18_16 0xB28 -#define MYKONOS_ADDR_SOURCE_CONTROL_LOWER_BYTE 0xB29 -#define MYKONOS_ADDR_SOURCE_CONTROL_UPPER_BYTE 0xB2A -#define MYKONOS_ADDR_SOURCE_CONTROL_EXTRA_BITS 0xB2B - -#define MYKONOS_ADDR_GPIO_MONITOR_INDEX 0xB40 -#define MYKONOS_ADDR_GPIO_MONITOR_ENABLE 0xB41 - -#define MYKONOS_ADDR_GP_INTERRUPT_MASK_1 0xB42 -#define MYKONOS_ADDR_GP_INTERRUPT_MASK_0 0xB43 -#define MYKONOS_ADDR_GP_INTERRUPT_READ_1 0xB44 -#define MYKONOS_ADDR_GP_INTERRUPT_READ_0 0xB45 - -#define MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_5_0 0xB73 -#define MYKONOS_ADDR_PDAUXDAC_MANUAL_CONTROL_9_6 0xB74 -#define MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_5_0 0xB75 -#define MYKONOS_ADDR_PDAUXDAC_MANUAL_IN_9_6 0xB76 -#define MYKONOS_ADDR_AUX_DAC_LATCH_CONTROL 0xB9F -#define MYKONOS_ADDR_AUXDAC_0_WORD_MSB 0xBA0 - -#define MYKONOS_ADR_AUX_ADC_CLOCK_DIVIDE 0xBC0 -#define MYKONOS_ADDR_AUX_ADC_CFG 0xBC1 -#define MYKONOS_ADDR_AUX_ADC_READ_MSB 0xBC2 -#define MYKONOS_ADDR_AUX_ADC_READ_LSB 0xBC3 -#define MYKONOS_ADDR_AUX_ADC_SEL 0xBC4 -#define MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_0 0xBC5 -#define MYKONOS_ADDR_AUX_ADC_BUFFER_CONFIG_1 0xBC6 - -#define MYKONOS_ADDR_TEMP_SENSOR_OFFSET 0xBE0 -#define MYKONOS_ADDR_TEMP_SENSOR_CONTROL_LSB 0xBE1 -#define MYKONOS_ADDR_TEMP_SENSOR_CONTROL_MSB 0xBE2 -#define MYKONOS_ADDR_TEMP_SENSOR_READ 0xBE3 -#define MYKONOS_ADDR_TEMP_SENSOR_CONFIG 0xBE4 - -#define MYKONOS_ADDR_DIGITAL_TEST_BYTE_0 0xC40 - -/* ARM subsystem registers */ -#define MYKONOS_ADDR_ARM_CTL_1 0xD00 -#define MYKONOS_ADDR_ARM_CTL_2 0xD01 -#define MYKONOS_ADDR_ARM_ADDR_BYTE_0 0xD02 -#define MYKONOS_ADDR_ARM_ADDR_BYTE_1 0xD03 -#define MYKONOS_ADDR_ARM_DATA_BYTE_0 0xD04 -#define MYKONOS_ADDR_ARM_DATA_BYTE_1 0xD05 -#define MYKONOS_ADDR_ARM_DATA_BYTE_2 0xD06 -#define MYKONOS_ADDR_ARM_DATA_BYTE_3 0xD07 -#define MYKONOS_ADDR_ARM_CLK_CTL 0xD08 -#define MYKONOS_ADDR_AHB_SPI_BRIDGE 0xD09 -#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_0 0xD0A -#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_1 0xD0B -#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_2 0xD0C -#define MYKONOS_ADDR_ARM_BOOT_ADDR_BYTE_3 0xD0D -#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_0 0xD0E -#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_1 0xD0F -#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_2 0xD10 -#define MYKONOS_ADDR_ARM_STACK_PTR_BYTE_3 0xD11 -#define MYKONOS_ADDR_ARM_BRIDGE_CLK_CTL 0xD14 - -/* ARM mailbox registers */ -#define MYKONOS_ADDR_ARM_CMD 0xD30 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_1 0xD31 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_2 0xD32 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_3 0xD33 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_4 0xD34 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_5 0xD35 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_6 0xD36 -#define MYKONOS_ADDR_ARM_EXT_CMD_BYTE_7 0xD37 -#define MYKONOS_ADDR_ARM_CMD_STATUS_0 0xD38 -#define MYKONOS_ADDR_ARM_CMD_STATUS_1 0xD39 -#define MYKONOS_ADDR_ARM_CMD_STATUS_2 0xD3A -#define MYKONOS_ADDR_ARM_CMD_STATUS_3 0xD3B -#define MYKONOS_ADDR_ARM_CMD_STATUS_4 0xD3C -#define MYKONOS_ADDR_ARM_CMD_STATUS_5 0xD3D -#define MYKONOS_ADDR_ARM_CMD_STATUS_6 0xD3E -#define MYKONOS_ADDR_ARM_CMD_STATUS_7 0xD3F - -#define MYKONOS_ADDR_ARM_OPCODE_STATE_0 0xD40 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_1 0xD41 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_2 0xD42 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_3 0xD43 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_4 0xD44 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_5 0xD45 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_6 0xD46 -#define MYKONOS_ADDR_ARM_OPCODE_STATE_7 0xD47 - -/* Mykonos Power-Down Override Control Registers */ -#define MYKONOS_ADDR_TX_PD_OVERRIDE_CONTROL_7_0 0xD89 - -/* Mykonos Observation Framer Registers */ -#define MYKONOS_ADDR_OBS_FRAMER_RESET 0xDC0 -#define MYKONOS_ADDR_OBS_FRAMER_CLK_EN 0xDC1 -#define MYKONOS_ADDR_OBS_FRAMER_ADDR 0xDC2 -#define MYKONOS_ADDR_OBS_FRAMER_DATA 0xDC3 -#define MYKONOS_ADDR_OBS_FRAMER_WRITE_EN 0xDC4 -#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_FIFO_EN 0xDC5 -#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_F 0xDC6 -#define MYKONOS_ADDR_OBS_FRAMER_LANE_CTL 0xDC7 -#define MYKONOS_ADDR_OBS_FRAMER_ADC_XBAR_SEL 0xDC8 -#define MYKONOS_ADDR_OBS_FRAMER_LANE_XBAR_SEL 0xDC9 -#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_LOOPBACK_XBAR_REV 0xDCA -#define MYKONOS_ADDR_OBS_FRAMER_SYNCN_FILT 0xDCB -#define MYKONOS_ADDR_OBS_FRAMER_LMFC_F_OFFSET 0xDCC -#define MYKONOS_ADDR_OBS_FRAMER_LMFC_K_OFFSET 0xDCD -#define MYKONOS_ADDR_OBS_FRAMER_TEST_CNTR_CTL 0xDCE -#define MYKONOS_ADDR_OBS_FRAMER_STATUS_STRB 0xDCF -#define MYKONOS_ADDR_OBS_FRAMER_STATUS 0xDD0 -#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_TO_LMFC_CNTR_STAT 0xDD1 -#define MYKONOS_ADDR_OBS_FRAMER_SYSREF_TO_LMFC_ERR_MARGIN 0xDD2 -#define MYKONOS_ADDR_OBS_FRAMER_LANE_FIFO_STRB 0xDD3 -#define MYKONOS_ADDR_OBS_FRAMER_LANE0_FIFO_RDWR_ADDR 0xDD4 -#define MYKONOS_ADDR_OBS_FRAMER_LANE1_FIFO_RDWR_ADDR 0xDD5 -#define MYKONOS_ADDR_OBS_FRAMER_LANE2_FIFO_RDWR_ADDR 0xDD6 -#define MYKONOS_ADDR_OBS_FRAMER_LANE3_FIFO_RDWR_ADDR 0xDD7 -#define MYKONOS_ADDR_OBS_FRAMER_PRBS10_CTL 0xDD8 -#define MYKONOS_ADDR_OBS_FRAMER_PRBS20_CTL 0xDD9 -#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_EN 0xDDA -#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_7_TO_0 0xDDB -#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_15_TO_8 0xDDC -#define MYKONOS_ADDR_OBS_FRAMER_PATTERN_GEN_19_TO_16 0xDDD -#define MYKONOS_ADDR_OBS_FRAMER_CONFIG_JTX_GEN 0xDDE -#define MYKONOS_ADDR_OBS_FRAMER_LANE_DATA_CTL 0xDDF -#define MYKONOS_ADDR_OBS_FRAMER_DATA_SAMPLE_CTL 0xDE0 - -#define MYKONOS_ADDR_PFIR_COEFF_CTL 0xDFF -#define MYKONOS_ADDR_PFIR_COEFF_DATA 0xE00 -#define MYKONOS_ADDR_PFIR_COEFF_ADDR 0xE01 - -/* ARM memory */ -#define MYKONOS_ADDR_ARM_START_PROG_ADDR 0x01000000 -#define MYKONOS_ADDR_ARM_END_PROG_ADDR 0x01017FFF -#define MYKONOS_ADDR_ARM_START_DATA_ADDR 0x20000000 -#define MYKONOS_ADDR_ARM_END_DATA_ADDR 0x2000FFFF -#define MYKONOS_ADDR_ARM_BUILD_CHKSUM_ADDR 0x01017FE0 -#define MYKONOS_ADDR_ARM_CALC_CHKSUM_ADDR 0x01017FE4 -#define MYKONOS_ADDR_ARM_VERSION 0x01000128 -#define MYKONOS_ARM_ABORT_OPCODE 0x00 -#define MYKONOS_ARM_RUNINIT_OPCODE 0x02 -#define MYKONOS_ARM_RADIOON_OPCODE 0x04 -#define MYKONOS_ARM_WRITECFG_OPCODE 0x06 -#define MYKONOS_ARM_READCFG_OPCODE 0x08 -#define MYKONOS_ARM_SET_OPCODE 0x0A -#define MYKONOS_ARM_GET_OPCODE 0x0C - -#define MYKONOS_ARM_OBJECTID_DPDINIT_CONFIG 0x0F -#define MYKONOS_ARM_OBJECTID_CLGCINIT_CONFIG 0x10 -#define MYKONOS_ARM_OBJECTID_VSWRINIT_CONFIG 0x11 -#define MYKONOS_ARM_OBJECTID_DPDCONFIG 0x24 -#define MYKONOS_ARM_DPD_RESET 0x02 -#define MYKONOS_ARM_OBJECTID_GS_TRACKCALS 0x66 -#define MYKONOS_ARM_OBJECTID_RXQEC_TRACKING 0x20 -#define MYKONOS_ARM_OBJECTID_ORXQEC_TRACKING 0x21 -#define MYKONOS_ARM_OBJECTID_TXLOL_TRACKING 0x22 -#define MYKONOS_ARM_OBJECTID_TXQEC_TRACKING 0x23 -#define MYKONOS_ARM_OBJECTID_CLGCCONFIG 0x25 -#define MYKONOS_ARM_OBJECTID_VSWRCONFIG 0x26 -#define MYKONOS_ARM_OBJECTID_CAL_STATUS 0x42 -#define MYKONOS_ARM_OBJECTID_INIT_CAL_DONE 0x43 -#define MYKONOS_ARM_OBJECTID_ORX_MODE 0x61 -#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_SUSPEND_RESUME 0x65 -#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_CONTROL 0x66 -#define MYKONOS_ARM_OBJECTID_TRACKING_CAL_PENDING 0x67 -#define MYKONOS_ARM_OBJECTID_RADIO_CONTROL 0x81 -#define MYKONOS_ARM_OBJECTID_CALSCHEDULER 0x83 - -#define MYKONOS_ARM_SYSTEMSTATE_POWERUP 0x00 -#define MYKONOS_ARM_SYSTEMSTATE_READY 0x01 -#define MYKONOS_ARM_SYSTEMSTATE_IDLE 0x02 -#define MYKONOS_ARM_SYSTEMSTATE_RADIO_ON 0x03 - -#define ORX_TRIGGER_SIGNALID 0x00 -#define ORX_MODE_0_SIGNALID 0x01 -#define ORX_MODE_1_SIGNALID 0x02 -#define ORX_MODE_2_SIGNALID 0x03 -#define RX1_ENABLE_ACK_SIGNALID 0x04 -#define RX2_ENABLE_ACK_SIGNALID 0x05 -#define TX1_ENABLE_ACK_SIGNALID 0x06 -#define TX2_ENABLE_ACK_SIGNALID 0x07 -#define ORX1_ENABLE_ACK_SIGNALID 0x08 -#define ORX2_ENABLE_ACK_SIGNALID 0x09 -#define SRX_ENABLE_ACK_SIGNALID 0x0A -#define TX_OBS_SELECT_SIGNALID 0x0B - -#define DISABLE_DPD_ACTUATOR 0x03 -#define ENABLE_DPD_ACTUATOR 0x04 -#define SET_CLGC_DESIRED_GAIN_1 0x05 -#define SET_CLGC_DESIRED_GAIN_2 0x06 -#define SET_PATH_DELAY 0x08 - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_user.c b/df_datalink_ge/src/hardware/mykonos/mykonos_user.c deleted file mode 100644 index 5cedb57..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_user.c +++ /dev/null @@ -1,176 +0,0 @@ -/** - * \file mykonos_user.c - * \brief Contains Mykonos default gain table values for Rx, ObsRx, and SnRx - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#include -#include "t_mykonos.h" -#include "mykonos_user.h" - -/** - * \brief Default Rx gain table settings - */ -uint8_t RxGainTable [61][4] = -{ - /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ - {0, 0, 0, 0}, /* Gain index 255 */ - {3, 0, 2, 1}, /* Gain index 254 */ - {6, 0, 3, 1}, /* Gain index 253 */ - {10, 0, 0, 0}, /* Gain index 252 */ - {13, 0, 1, 1}, /* Gain index 251 */ - {16, 0, 0, 0}, /* Gain index 250 */ - {18, 0, 3, 1}, /* Gain index 249 */ - {21, 0, 1, 1}, /* Gain index 248 */ - {23, 0, 3, 1}, /* Gain index 247 */ - {25, 0, 4, 1}, /* Gain index 246 */ - {28, 0, 0, 0}, /* Gain index 245 */ - {30, 0, 0, 0}, /* Gain index 244 */ - {31, 0, 5, 1}, /* Gain index 243 */ - {33, 0, 4, 1}, /* Gain index 242 */ - {35, 0, 2, 1}, /* Gain index 241 */ - {37, 0, 0, 0}, /* Gain index 240 */ - {38, 0, 4, 1}, /* Gain index 239 */ - {39, 0, 7, 1}, /* Gain index 238 */ - {41, 0, 2, 1}, /* Gain index 237 */ - {42, 0, 4, 1}, /* Gain index 236 */ - {43, 0, 6, 1}, /* Gain index 235 */ - {44, 0, 8, 1}, /* Gain index 234 */ - {45, 0, 9, 1}, /* Gain index 233 */ - {46, 0, 10, 1}, /* Gain index 232 */ - {47, 0, 10, 1}, /* Gain index 231 */ - {48, 0, 9, 1}, /* Gain index 230 */ - {49, 0, 8, 1}, /* Gain index 229 */ - {50, 0, 6, 1}, /* Gain index 228 */ - {51, 0, 3, 1}, /* Gain index 227 */ - {51, 0, 13, 1}, /* Gain index 226 */ - {52, 0, 9, 1}, /* Gain index 225 */ - {53, 0, 5, 1}, /* Gain index 224 */ - {53, 0, 15, 1}, /* Gain index 223 */ - {54, 0, 9, 1}, /* Gain index 222 */ - {54, 0, 19, 1}, /* Gain index 221 */ - {55, 0, 11, 1}, /* Gain index 220 */ - {55, 0, 21, 1}, /* Gain index 219 */ - {56, 0, 11, 1}, /* Gain index 218 */ - {56, 0, 21, 1}, /* Gain index 217 */ - {57, 0, 9, 1}, /* Gain index 216 */ - {57, 0, 19, 1}, /* Gain index 215 */ - {57, 0, 29, 1}, /* Gain index 214 */ - {58, 0, 12, 1}, /* Gain index 213 */ - {58, 0, 22, 1}, /* Gain index 212 */ - {58, 0, 32, 1}, /* Gain index 211 */ - {59, 0, 11, 1}, /* Gain index 210 */ - {59, 0, 21, 1}, /* Gain index 209 */ - {59, 0, 31, 1}, /* Gain index 208 */ - {59, 0, 41, 1}, /* Gain index 207 */ - {60, 0, 13, 1}, /* Gain index 206 */ - {60, 0, 23, 1}, /* Gain index 205 */ - {60, 0, 33, 1}, /* Gain index 204 */ - {60, 0, 43, 1}, /* Gain index 203 */ - {60, 0, 53, 1}, /* Gain index 202 */ - {61, 0, 14, 1}, /* Gain index 201 */ - {61, 0, 24, 1}, /* Gain index 200 */ - {61, 0, 34, 1}, /* Gain index 199 */ - {61, 0, 44, 1}, /* Gain index 198 */ - {61, 0, 54, 1}, /* Gain index 197 */ - {61, 0, 64, 1}, /* Gain index 196 */ - {61, 0, 74, 1}, /* Gain index 195 */ -}; - -/** - * \brief Default ORx gain table settings - */ -uint8_t ORxGainTable [19][4] = -{ - /* Order: {FE table, External Ctl, Digital Gain/Atten, Enable Atten} */ - {0, 0, 0, 0}, /* Gain index 255 */ - {7, 0, 0, 0}, /* Gain index 254 */ - {13, 0, 1, 1}, /* Gain index 253 */ - {18, 0, 3, 1}, /* Gain index 252 */ - {23, 0, 3, 1}, /* Gain index 251 */ - {28, 0, 0, 0}, /* Gain index 250 */ - {32, 0, 0, 0}, /* Gain index 249 */ - {35, 0, 2, 1}, /* Gain index 248 */ - {38, 0, 4, 1}, /* Gain index 247 */ - {41, 0, 2, 1}, /* Gain index 246 */ - {43, 0, 6, 1}, /* Gain index 245 */ - {46, 0, 0, 0}, /* Gain index 244 */ - {47, 0, 10, 1}, /* Gain index 243 */ - {49, 0, 8, 1}, /* Gain index 242 */ - {51, 0, 3, 1}, /* Gain index 241 */ - {52, 0, 9, 1}, /* Gain index 240 */ - {53, 0, 14, 1}, /* Gain index 239 */ - {54, 0, 18, 1}, /* Gain index 238 */ - {56, 0, 0, 0} /* Gain index 237 */ - -}; - -/** - * \brief Default SnRx gain table settings - */ -uint8_t SnRxGainTable [53][4] = -{ - /* Order: {FE table, LNA Bypass, Digital Gain/Atten, Enable Atten} */ - {0, 0, 0, 0}, /* Gain index 255 */ - {1, 0, 7, 1}, /* Gain index 254 */ - {3, 0, 1, 0}, /* Gain index 253 */ - {3, 0, 15, 1}, /* Gain index 252 */ - {5, 0, 0, 0}, /* Gain index 251 */ - {6, 0, 2, 1}, /* Gain index 250 */ - {7, 0, 2, 1}, /* Gain index 249 */ - {8, 0, 12, 1}, /* Gain index 248 */ - {9, 0, 7, 1}, /* Gain index 247 */ - {11, 0, 1, 0}, /* Gain index 246 */ - {11, 0, 15, 1},/* Gain index 245 */ - {13, 0, 1, 0}, /* Gain index 244 */ - {14, 0, 2, 0}, /* Gain index 243 */ - {14, 0, 10, 1},/* Gain index 242 */ - {15, 0, 0, 0}, /* Gain index 241 */ - {15, 0, 20, 1},/* Gain index 240 */ - {16, 0, 2, 1}, /* Gain index 239 */ - {16, 0, 22, 1},/* Gain index 238 */ - {17, 0, 1, 0}, /* Gain index 237 */ - {17, 0, 15, 1},/* Gain index 236 */ - {17, 0, 35, 1},/* Gain index 235 */ - {17, 0, 55, 1},/* Gain index 234 */ - {18, 0, 7, 1}, /* Gain index 233 */ - {18, 0, 27, 1},/* Gain index 232 */ - { 6, 1, 7, 1}, /* Gain index 231 */ - { 7, 1, 7, 1}, /* Gain index 230 */ - { 8, 1, 17, 1}, /* Gain index 229 */ - { 9, 1, 12, 1}, /* Gain index 228 */ - {11, 1, 0, 0}, /* Gain index 227 */ - {12, 1, 3, 1}, /* Gain index 226 */ - {13, 1, 0, 0}, /* Gain index 225 */ - {14, 1, 1, 0}, /* Gain index 224 */ - {14, 1, 15, 1},/* Gain index 223 */ - {15, 1, 5, 1}, /* Gain index 222 */ - {15, 1, 25, 1},/* Gain index 221 */ - {16, 1, 7, 1}, /* Gain index 220 */ - {16, 1, 27, 1},/* Gain index 219 */ - {17, 1, 0, 0}, /* Gain index 218 */ - {17, 1, 20, 1},/* Gain index 217 */ - {17, 1, 40, 1},/* Gain index 216 */ - {17, 1, 60, 1},/* Gain index 215 */ - {18, 1, 12, 1},/* Gain index 214 */ - {18, 1, 32, 1},/* Gain index 213 */ - {18, 1, 52, 1},/* Gain index 212 */ - {18, 1, 72, 1},/* Gain index 211 */ - {18, 1, 92, 1},/* Gain index 210 */ - {19, 1, 1, 0}, /* Gain index 209 */ - {19, 1, 15, 1},/* Gain index 208 */ - {19, 1, 35, 1},/* Gain index 207 */ - {19, 1, 55, 1},/* Gain index 206 */ - {19, 1, 75, 1},/* Gain index 205 */ - {19, 1, 95, 1},/* Gain index 204 */ - {19, 1, 115, 1}/* Gain index 203 */ -}; - diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_user.h b/df_datalink_ge/src/hardware/mykonos/mykonos_user.h deleted file mode 100644 index 2875837..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_user.h +++ /dev/null @@ -1,85 +0,0 @@ -/** - * \file mykonos_user.h - * - * \brief Contains macro definitions and global structure declarations for mykonos_user.c - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _MYKONOSPROFILES_H_ -#define _MYKONOSPROFILES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -/* turns verbose messaging on */ -#define MYKONOS_VERBOSE 1 -#define MYK_ENABLE_SPIWRITEARRAY 1 - -/* 3 Bytes per SPI transaction * 341 transactions = ~1024 byte buffer size */ -/* Minimum MYK_SPIWRITEARRAY_BUFFERSIZE = 27 */ -#define MYK_SPIWRITEARRAY_BUFFERSIZE 341 -/* - ***************************************** - * Rx, ObsRx, and Sniffer gain tables - ****************************************** - */ -#define MAX_GAIN_TABLE_INDEX 255 - -#define START_RX_GAIN_INDEX 255 -#define MAX_RX_GAIN_TABLE_NUMINDEXES (START_RX_GAIN_INDEX + 1) -#define MIN_RX_GAIN_TABLE_INDEX 0 - -#define START_ORX_GAIN_INDEX 47 -#define MAX_ORX_GAIN_TABLE_NUMINDEXES (START_ORX_GAIN_INDEX + 1) -#define MIN_ORX_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_ORX_GAIN_INDEX) - -#define START_SNRX_GAIN_INDEX 127 -#define MAX_SNRX_GAIN_TABLE_NUMINDEXES (START_SNRX_GAIN_INDEX + 1) -#define MIN_SNRX_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_SNRX_GAIN_INDEX) - -#define START_LOOPBACK_GAIN_INDEX 47 -#define MAX_LOOPBACK_GAIN_TABLE_NUMINDEXES (START_LOOPBACK_GAIN_INDEX + 1) -#define MIN_LOOPBACK_GAIN_TABLE_INDEX (MAX_GAIN_TABLE_INDEX - START_SNRX_GAIN_INDEX) - -extern uint8_t RxGainTable [61][4]; -extern uint8_t ORxGainTable [19][4]; -extern uint8_t SnRxGainTable [53][4]; - - -/* - ******************************************** - * Rx, Sniffer, ObsRx and Tx Profiles limits - ******************************************** - */ -#define MIN_RX_IQRATE_KHZ 15000 /*!< Mykonos minimum IQ rate for the Rx channel, expressed in KHz */ -#define MAX_RX_IQRATE_KHZ 320000 /*!< Mykonos maximum IQ rate for the Rx channel, expressed in KHz */ - -#define MIN_TX_IQRATE_KHZ 15000 /*!< Mykonos minimum IQ rate for the Tx channel, expressed in KHz */ -#define MAX_TX_IQRATE_KHZ 492000 /*!< Mykonos maximum IQ rate for the Tx channel, expressed in KHz */ - -#define MIN_SNIFFER_RFBW_HZ 5000000 /*!< Mykonos minimum Sniffer channel bandwidth expressed in Hz */ -#define MAX_SNIFFER_RFBW_HZ 20000000 /*!< Mykonos maximum Sniffer channel bandwidth expressed in Hz */ - -#define MIN_ORX_RFBW_HZ 5000000 /*!< Mykonos minimum Observation channel bandwidth expressed in Hz */ -#define MAX_ORX_RFBW_HZ 250000000 /*!< Mykonos maximum Observation channel bandwidth expressed in Hz */ - -#define MIN_RX_RFBW_HZ 5000000 /*!< Mykonos minimum Rx channel bandwidth expressed in Hz */ -#define MAX_RX_RFBW_HZ 100000000 /*!< Mykonos maximum Rx channel bandwidth expressed in Hz */ - -#define MIN_TX_RFBW_HZ 20000000 /*!< Mykonos minimum Tx channel bandwidth expressed in Hz */ -#define MAX_TX_RFBW_HZ 250000000 /*!< Mykonos maximum Tx channel bandwidth expressed in Hz */ - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/mykonos_version.h b/df_datalink_ge/src/hardware/mykonos/mykonos_version.h deleted file mode 100644 index c7f58d2..0000000 --- a/df_datalink_ge/src/hardware/mykonos/mykonos_version.h +++ /dev/null @@ -1,31 +0,0 @@ -/** - * \file mykonos_version.h - * \brief Contains the version number for the Mykonos API - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in * this zip file. -* -*/ - -#ifndef MYKONOS_VERSION_H_ -#define MYKONOS_VERSION_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#define MYKONOS_CURRENT_SI_VERSION 1 /*!< Mykonos current silicon version */ -#define MYKONOS_CURRENT_MAJOR_VERSION 5 /*!< Mykonos current ARM major version */ -#define MYKONOS_CURRENT_MINOR_VERSION 2 /*!< Mykonos current ARM minor version */ -#define MYKONOS_CURRENT_BUILD_VERSION 3566 /*!< Mykonos current API build version */ - -#ifdef __cplusplus -} -#endif - -#endif /* MYKONOS_VERSION_H_ */ diff --git a/df_datalink_ge/src/hardware/mykonos/t_ad9528.h b/df_datalink_ge/src/hardware/mykonos/t_ad9528.h deleted file mode 100644 index 02cd278..0000000 --- a/df_datalink_ge/src/hardware/mykonos/t_ad9528.h +++ /dev/null @@ -1,194 +0,0 @@ -/** - * \file t_ad9528.h - * \brief Contains enum and structure data types for all AD9528 function calls - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _AD9528_TYPES_H_ -#define _AD9528_TYPES_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../common.h" - -/* AD9528 SPI Address defines */ -#define AD9528_ADDR_ADI_SPI_CONFIG_A 0x000 -#define AD9528_ADDR_ADI_SPI_CONFIG_B 0x001 -#define AD9528_ADDR_IO_UPDATE 0x00F - -#define AD9528_ADDR_REF_A_DIVIDER_LSB 0x100 -#define AD9528_ADDR_REF_A_DIVIDER_MSB 0x101 -#define AD9528_ADDR_REF_B_DIVIDER_LSB 0x102 -#define AD9528_ADDR_REF_B_DIVIDER_MSB 0x103 -#define AD9528_ADDR_PLL1_N_DIV_LSB 0x104 -#define AD9528_ADDR_PLL1_N_DIV_MSB 0x105 -#define AD9528_ADDR_PLL1_CHARGEPUMP 0x106 -#define AD9528_ADDR_PLL1_CP_CTRL2 0x107 -#define AD9528_ADDR_INPUT_RECEIVERS1 0x108 -#define AD9528_ADDR_INPUT_RECEIVERS2 0x109 -#define AD9528_ADDR_INPUT_RECEIVERS3 0x10A -#define AD9528_ADDR_PLL1_FASTLOCK 0x10B - -#define AD9528_ADDR_PLL2_CHARGEPUMP 0x200 -#define AD9528_ADDR_PLL2_N_DIV 0x201 -#define AD9528_ADDR_PLL2_CTRL 0x202 -#define AD9528_ADDR_PLL2_VCO_CTRL 0x203 -#define AD9528_ADDR_PLL2_VCO_DIV 0x204 -#define AD9528_ADDR_PLL2_LF_CTRL1 0x205 -#define AD9528_ADDR_PLL2_LF_CTRL2 0x206 -#define AD9528_ADDR_PLL2_RDIV 0x207 -#define AD9528_ADDR_PLL2_REPLICA_CHDIV 0x208 -#define AD9528_ADDR_PLL2_REPLICA_DIV_PHASE 0x209 - -#define AD9528_ADDR_CH_OUT0_CTRL1 0x300 -#define AD9528_ADDR_CH_OUT0_CTRL2 0x301 -#define AD9528_ADDR_CH_OUT0_CHDIV 0x302 -#define AD9528_ADDR_OUTPUT_SYNC 0x32A -#define AD9528_ADDR_MASK_SYNC1 0x32B -#define AD9528_ADDR_MASK_SYNC2 0x32C -#define AD9528_ADDR_EN_OUTPUT_PATH_SEL1 0x32D -#define AD9528_ADDR_EN_OUTPUT_PATH_SEL2 0x32E - -#define AD9528_ADDR_SYSERF_DIV_LSB 0x400 -#define AD9528_ADDR_SYSERF_DIV_MSB 0x401 -#define AD9528_ADDR_SYSREF_CTRL3 0x402 -#define AD9528_ADDR_SYSREF_CTRL4 0x403 -#define AD9528_ADDR_SYSREF_CTRL5 0x404 - -#define AD9528_ADDR_POWERDOWN_CTRL 0x500 -#define AD9528_ADDR_CH_POWERDOWN1 0x501 -#define AD9528_ADDR_CH_POWERDOWN2 0x502 -#define AD9528_ADDR_LDO_ENABLES1 0x503 -#define AD9528_ADDR_LDO_ENABLES2 0x504 -#define AD9528_ADDR_STATUS0_CTRL 0x505 -#define AD9528_ADDR_STATUS1_CTRL 0x506 -#define AD9528_ADDR_STATUS_OE 0x507 -#define AD9528_ADDR_STATUS_READBACK0 0x508 -#define AD9528_ADDR_STATUS_READBACK1 0x509 - - - -///Enum to select what source outputs from each AD9528 output channel -typedef enum -{ - CHANNEL_DIV = 0, PLL1_OUTPUT = 1, //VCXO frequency - SYSREF = 2, - INV_PLL1_OUTPUT = 5 //VCXO inverted -} ad9528outSourceSel_t; - -///Enum to select what output buffer standard is used for the clock outputs -typedef enum -{ - LVDS = 0, LVDS_BOOST = 1, HSTL = 2 -} ad9528outBufferControl_t; - -///Enum to select the clock input buffer mode. -typedef enum -{ - DISABLED = 0, SINGLE_ENDED, NEG_SINGLE_ENDED, DIFFERENTIAL -} ad9528RefBuffer_t; - -/// Structure to hold AD9528 PLL1 settings -typedef struct -{ - uint32_t refA_Frequency_Hz; - uint16_t refA_Divider; - ad9528RefBuffer_t refA_bufferCtrl; - - uint32_t refB_Frequency_Hz; - uint16_t refB_Divider; - ad9528RefBuffer_t refB_bufferCtrl; - - uint32_t vcxo_Frequency_Hz; - ad9528RefBuffer_t vcxoBufferCtrl; - - uint16_t nDivider; - uint8_t bypassPll1; -} ad9528pll1Settings_t; - -/// Structure to hold AD9528 PLL2 settings -typedef struct -{ - uint8_t rfDivider; //VCO divider: Valid range (3,4,5) - uint8_t n2Divider; //PLL2 N2 Divider - uint8_t totalNdiv; //NDiv = 4*Bdiv + Adiv //Bdiv valid range (3 to 63), Adiv valid range (0-3) -} ad9528pll2Settings_t; - -/// Structure to hold AD9528 Output Clock settings -typedef struct -{ - uint16_t outPowerDown; //bit per output, if 1 power down that output. - ad9528outSourceSel_t outSource[14]; //CHANNEL_DIV, PLL1_OUTPUT, SYSREF, INV_PLL1_OUTPUT - ad9528outBufferControl_t outBufferCtrl[14]; //LVDS, LVDS_BOOST, HSTL - uint8_t outAnalogDelay[14]; //5 bits - uint8_t outDigitalDelay[14]; //6 bits, 1/2 clock resolution @ channel div input frequency - uint8_t outChannelDiv[14]; //8 bit channel divider - uint32_t outFrequency_Hz[14]; //output clock frequency per clock output -} ad9528outputSettings_t; - -///Enum to select the SYSREF output source -typedef enum -{ - EXTERNAL = 0, EXT_RESAMPLED = 1, INTERNAL = 2 -} sysrefSourceSelection_t; - -///Enum to choose the SYSREF pattern mode. -typedef enum -{ - NSHOT = 0, CONTINUOUS = 1, PRBS = 2, STOP = 3 -} sysrefPatternMode_t; - -///Enum to select the SYSREF input pin mode. -typedef enum -{ - LEVEL_ACTIVE_HIGH = 0, LEVEL_ACTIVE_LOW = 1, RISING_EDGE = 2, FALLING_EDGE = 3 -} sysrefPinEdgeMode_t; - -///Enum to select the SYSREF output # of pulses for NSHOT mode. -typedef enum -{ - ONE_PULSE = 0, TWO_PULSES = 2, FOUR_PULSES = 3, SIX_PULSES = 4, EIGHT_PULSES = 5 -} sysrefNshotMode_t; - -//Enum to select how a SYSREF is requested. -typedef enum -{ - SPI = 0, PIN = 1 -} sysrefRequestMethod_t; - -/// Structure to hold AD9528 SYSREF output settings -typedef struct -{ - sysrefRequestMethod_t sysrefRequestMethod; - sysrefSourceSelection_t sysrefSource; - sysrefPinEdgeMode_t sysrefPinEdgeMode; - ad9528RefBuffer_t sysrefPinBufferMode; - sysrefPatternMode_t sysrefPatternMode; - sysrefNshotMode_t sysrefNshotMode; - uint16_t sysrefDivide; - -} ad9528sysrefSettings_t; - -/// Structure to hold AD9528 settings -typedef struct -{ - spiSettings_t *spiSettings; - ad9528pll1Settings_t *pll1Settings; - ad9528pll2Settings_t *pll2Settings; - ad9528outputSettings_t *outputSettings; - ad9528sysrefSettings_t *sysrefSettings; -} ad9528Device_t; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/t_mykonos.h b/df_datalink_ge/src/hardware/mykonos/t_mykonos.h deleted file mode 100644 index 66db0d7..0000000 --- a/df_datalink_ge/src/hardware/mykonos/t_mykonos.h +++ /dev/null @@ -1,1710 +0,0 @@ -/*! - * \file t_mykonos.h - * \brief Contains type definitions for Mykonos API - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef _T_MYKONOS_LIB_H_ -#define _T_MYKONOS_LIB_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -#include "../common.h" - - -/** - * \brief Enum of unique error codes from the Mykonos API functions. - * Each error condition in the library should get its own enum value to allow - * easy debug of errors. - */ -typedef enum -{ - MYKONOS_ERR_OK=0, - MYKONOS_ERR_HAL_LAYER, - MYKONOS_ERR_INV_PARM, - MYKONOS_ERR_FAILED, - MYKONOS_ERR_WAITFOREVENT_INV_PARM, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT, - MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_WAIT, - MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_ALERT, - MYKONOS_ERR_SETENSM_INVALID_NEWSTATE_TXRX, - MYKONOS_ERR_SETENSM_INVALIDSTATE, - MYKONOS_ERR_PU_RXPATH_INV_PARAM, - MYKONOS_ERR_PU_TXPATH_INV_PARAM, - MYKONOS_ERR_PU_OBSRXPATH_INV_PARAM, - MYKONOS_ERR_INIT_INV_ORXCHAN, - MYKONOS_ERR_INIT_INV_RXSYNCB_ORXSYNCB_MODE, - MYKONOS_ERR_INIT_INV_TXFIR_INTERPOLATION, - MYKONOS_ERR_INIT_INV_TXHB2_INTERPOLATION, - MYKONOS_ERR_INIT_INV_TXHB1_INTERPOLATION, - MYKONOS_ERR_INIT_INV_RXFIR_DECIMATION, - MYKONOS_ERR_INIT_INV_RXDEC5_DECIMATION, - MYKONOS_ERR_INIT_INV_RXHB1_DECIMATION, - MYKONOS_ERR_INIT_INV_SNIFFER_RHB1, - MYKONOS_ERR_INIT_INV_SNIFFER_RFIR_DEC, - MYKONOS_ERR_INIT_INV_ORX_RHB1, - MYKONOS_ERR_INIT_INV_ORX_RFIR_DEC, - MYKONOS_ERR_INIT_INV_ADCDIV, - MYKONOS_ERR_INIT_INV_DACDIV, - MYKONOS_ERR_INIT_INV_OBSRX_ADCDIV, - MYKONOS_ERR_CLKPLL_INV_HSDIV, - MYKONOS_ERR_CLKPLL_INV_VCODIV, - MYKONOS_ERR_CLKPLL_INV_RXTXPROFILES, - MYKONOS_ERR_SETCLKPLL_INV_VCOINDEX, - MYKONOS_ERR_SETCLKPLL_INV_FRACWORD, - MYKONOS_ERR_SETRFPLL_INV_PLLNAME, - MYKONOS_ERR_SETRFPLL_INV_LO_PARM, - MYKONOS_ERR_INV_SCALEDDEVCLK_PARAM, - MYKONOS_ERR_NULL_DEVICE_PARAM, - MYKONOS_ERR_CALCDEVCLK_NULLPARAM, - MYKONOS_ERR_SETRFPLL_INV_VCOINDEX, - MYKONOS_ERR_SETRFPLL_INV_REFCLK, - MYKONOS_ERR_SETORXGAIN_INV_CHANNEL, - MYKONOS_ERR_SETORXGAIN_INV_GAIN, - MYKONOS_ERR_GETORX1GAIN_INV_POINTER, - MYKONOS_ERR_GETORX2GAIN_INV_POINTER, - MYKONOS_ERR_GETSNIFFGAIN_INV_POINTER, - MYKONOS_ERR_GETOBSRXGAIN_CH_DISABLED, - MYKONOS_ERR_SETTX1ATTEN_INV_PARM, - MYKONOS_ERR_SETTX1ATTEN_INV_STEPSIZE_PARM, - MYKONOS_ERR_SETTX2ATTEN_INV_PARM, - MYKONOS_ERR_SETTX2ATTEN_INV_STEPSIZE_PARM, - MYKONOS_ERR_PROGRAMFIR_INV_NUMTAPS_PARM, - MYKONOS_ERR_PROGRAMFIR_INV_FIRNAME_PARM, - MYKONOS_ERR_RXFIR_INV_GAIN_PARM, - MYKONOS_ERR_OBSRXFIR_INV_GAIN_PARM, - MYKONOS_ERR_SRXFIR_INV_GAIN_PARM, - MYKONOS_ERR_TXFIR_INV_GAIN_PARM, - MYKONOS_ERR_READFIR_NULL_PARM, - MYKONOS_ERR_READFIR_COEFS_NULL, - MYKONOS_ERR_READFIR_INV_FIRNAME_PARM, - MYKONOS_ERR_READFIR_INV_NUMTAPS_PARM, - MYKONOS_ERR_SETRX1GAIN_INV_GAIN_PARM, - MYKONOS_ERR_SETRX2GAIN_INV_GAIN_PARM, - MYKONOS_ERR_INITSER_INV_VCODIV_PARM, - MYKONOS_ERR_INITSER_INV_VCODIV1_HSCLK_PARM, - MYKONOS_ERR_INITSER_INV_VCODIV1P5_HSCLK_PARM, - MYKONOS_ERR_INITDES_INV_VCODIV_PARM, - MYKONOS_ERR_SER_INV_M_PARM, - MYKONOS_ERR_SER_INV_L_PARM, - MYKONOS_ERR_SER_INV_LANERATE_PARM, - MYKONOS_ERR_SER_INV_LANEEN_PARM, - MYKONOS_ERR_SER_INV_AMP_PARM, - MYKONOS_ERR_SER_INV_PREEMP_PARM, - MYKONOS_ERR_SER_INV_LANEPN_PARM, - MYKONOS_ERR_SER_LANE_CONFLICT_PARM, - MYKONOS_ERR_SER_INV_TXSER_DIV_PARM, - MYKONOS_ERR_SER_LANE_RATE_CONFLICT_PARM, - MYKONOS_ERR_SER_INV_REAL_IF_DATA_PARM, - MYKONOS_ERR_HS_AND_LANE_RATE_NOT_INTEGER_MULT, - MYKONOS_ERR_DES_HS_AND_LANE_RATE_NOT_INTEGER_MULT, - MYKONOS_ERR_DESER_INV_M_PARM, - MYKONOS_ERR_DESER_INV_L_PARM, - MYKONOS_ERR_DESER_INV_HSCLK_PARM, - MYKONOS_ERR_DESER_INV_LANERATE_PARM, - MYKONOS_ERR_DESER_INV_LANEEN_PARM, - MYKONOS_ERR_DESER_INV_EQ_PARM, - MYKONOS_ERR_DESER_INV_LANEPN_PARM, - MYKONOS_ERR_FRAMER_INV_M_PARM, - MYKONOS_ERR_FRAMER_INV_BANKID_PARM, - MYKONOS_ERR_FRAMER_INV_LANEID_PARM, - MYKONOS_ERR_FRAMER_INV_K_OFFSET_PARAM, - MYKONOS_ERR_FRAMER_INV_REAL_IF_DATA_PARM, - MYKONOS_ERR_OBSRX_FRAMER_INV_M_PARM, - MYKONOS_ERR_OBSRX_FRAMER_INV_BANKID_PARM, - MYKONOS_ERR_OBSRX_FRAMER_INV_LANEID_PARM, - MYKONOS_ERR_OBSRX_FRAMER_INV_K_OFFSET_PARAM, - MYKONOS_ERR_OBSRX_FRAMER_INV_REAL_IF_DATA_PARM, - MYKONOS_ERR_DEFRAMER_INV_M_PARM, - MYKONOS_ERR_DEFRAMER_INV_BANKID_PARM, - MYKONOS_ERR_ERR_DEFRAMER_INV_LANEID_PARM, - MYKONOS_ERR_DEFRAMER_INV_K_OFFSET_PARAM, - MYKONOS_ERR_DEFRAMER_INV_K_PARAM, - MYKONOS_ERR_DEFRAMER_INV_FK_PARAM, - MYKONOS_ERR_RX_FRAMER_INV_PRBS_POLYORDER_PARAM, - MYKONOS_ERR_OBSRX_FRAMER_INV_PRBS_POLYORDER_PARAM, - MYKONOS_ERR_DEFRAMER_INV_PRBS_ENABLE_PARAM, - MYKONOS_ERR_DEFRAMER_INV_PRBS_POLYORDER_PARAM, - MYKONOS_ERR_DEFRAMER_INV_PRBS_CNTR_SEL_PARAM, - MYKONOS_ERR_INITARM_INV_DATARATE_PARM, - MYKONOS_ERR_INITARM_INV_REGCLK, - MYKONOS_ERR_INITARM_INV_ARMCLK_PARAM, - MYKONOS_ERR_LOADHEX_INV_CHARCOUNT, - MYKONOS_ERR_LOADHEX_INVALID_FIRSTCHAR, - MYKONOS_ERR_LOADHEX_INVALID_CHKSUM, - MYKONOS_ERR_LOADBIN_INVALID_BYTECOUNT, - MYKONOS_ERR_ARM_INVALID_BUILDCHKSUM, - MYKONOS_ERR_READARMMEM_INV_ADDR_PARM, - MYKONOS_ERR_WRITEARMMEM_INV_ADDR_PARM, - MYKONOS_ERR_ARMCMD_INV_OPCODE_PARM, - MYKONOS_ERR_ARMCMD_INV_NUMBYTES_PARM, - MYKONOS_ERR_ARMCMDSTATUS_INV_OPCODE_PARM, - MYKONOS_ERR_CHECKDEVSTRUCT_SPI, - MYKONOS_ERR_CHECKDEVSTRUCT_RX, - MYKONOS_ERR_CHECKDEVSTRUCT_RXSUB, - MYKONOS_ERR_CHECKDEVSTRUCT_RXFIR, - MYKONOS_ERR_CHECKDEVSTRUCT_TX, - MYKONOS_ERR_CHECKDEVSTRUCT_TXSUB, - MYKONOS_ERR_CHECKDEVSTRUCT_TXFIR, - MYKONOS_ERR_CHECKDEVSTRUCT_OBSRX, - MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXSUB, - MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERFIR, - MYKONOS_ERR_CHECKDEVSTRUCT_ORXFIR, - MYKONOS_ERR_CHECKDEVSTRUCT_ORXGAINCTRL, - MYKONOS_ERR_CHECKDEVSTRUCT_SNIFFERGAINCTRL, - MYKONOS_ERR_CHECKDEVSTRUCT_OBSRXFRAMER, - MYKONOS_ERR_INITSER_INV_PROFILE, - MYKONOS_ERR_INITDES_INV_TXPROFILE, - MYKONOS_ERR_JESD204B_ILAS_MISMATCH, - MYKONOS_ERR_RXGAINTABLE_INV_CHANNEL, - MYKONOS_ERR_RXGAINTABLE_INV_GAIN_INDEX_RANGE, - MYKONOS_ERR_WRITE_CFG_MEMORY_FAILED, - MYKONOS_ERR_INV_RXFRAMER_PCLKDIV_PARM, - MYKONOS_ERR_RXFRAMER_INV_FK_PARAM, - MYKONOS_ERR_OBSRXFRAMER_INV_FK_PARAM, - MYKONOS_ERR_INV_OBSRXFRAMER_PCLKDIV_PARM, - MYKONOS_ERR_PU_OBSRXPATH_INV_LOSOURCE_PARAM, - MYKONOS_ERR_ARM_RADIOON_FAILED, - MYKONOS_ERR_INV_RX_GAIN_MODE_PARM, - MYKONOS_ERR_INV_ORX_GAIN_MODE_PARM, - MYKONOS_ERR_INV_AGC_RX_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_RX_APD_THRESH_DIFF_VS_ATTACK_GAIN_STEP, - MYKONOS_ERR_INV_AGC_RX_PEAK_WAIT_TIME_PARM, - MYKONOS_ERR_INV_AGC_RX_GAIN_UPDATE_TIME_PARM, - MYKONOS_ERR_INV_AGC_RX_APD_HIGH_THRESH_PARM, - MYKONOS_ERR_INV_AGC_RX_APD_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_RX_BLOCK_DET_DECAY_PARM, - MYKONOS_ERR_INV_AGC_RX_APD_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_RECOVERY_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_PMD_MEAS_CONFIG, - MYKONOS_ERR_INV_AGC_PMD_MEAS_DURATION, - MYKONOS_ERR_INV_AGC_RX_ENABLE_SYNC_PULSE_GAIN_COUNTER, - MYKONOS_ERR_INV_AGC_RX_LOW_THS_PREV_GAIN_INC, - MYKONOS_ERR_INV_AGC_RX_PEAK_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_RX_PEAK_THRESH_MODE, - MYKONOS_ERR_INV_AGC_RX_PWR_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_RX_RESET_ON_RX_ENABLE, - MYKONOS_ERR_INV_AGC_RX_SLOW_LOOP_SETTLING_DELAY, - MYKONOS_ERR_INV_AGC_RX1_MAX_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_RX1_MIN_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_RX2_MAX_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_RX2_MIN_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_THRESH, - MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_THRESH, - MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_THRESH, - MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_THRESH, - MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_LOW_GAIN_STEP, - MYKONOS_ERR_INV_AGC_RX_PMD_LOWER_HIGH_GAIN_STEP, - MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_LOW_GAIN_STEP, - MYKONOS_ERR_INV_AGC_RX_PMD_UPPER_HIGH_GAIN_STEP, - MYKONOS_ERR_INV_AGC_RX_APD_HIGH_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_APD_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_HIGH_THRESH_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_RX_HB2_VERY_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_RX_PKDET_FAST_ATTACK_VALUE, - MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_ENABLE, - MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_DUR_CNT, - MYKONOS_ERR_INV_AGC_RX_HB2_OVLD_THRESH_CNT, - MYKONOS_ERR_INV_AGC_OBSRX_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_OBSRX_APD_THRESH_DIFF_VS_ATTACK_GAIN_STEP, - MYKONOS_ERR_INV_AGC_OBSRX_PEAK_WAIT_TIME_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_GAIN_UPDATE_TIME_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_THRESH_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_BLOCK_DET_DECAY_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_APD_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_RECOVERY_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_MAX_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX_MIN_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX_SELECT, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_CONFIG, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_MEAS_DURATION, - MYKONOS_ERR_INV_AGC_OBSRX_ENABLE_SYNC_PULSE_GAIN_COUNTER, - MYKONOS_ERR_INV_AGC_OBSRX_LOW_THS_PREV_GAIN_INC, - MYKONOS_ERR_INV_AGC_OBSRX_PEAK_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_OBSRX_PEAK_THRESH_MODE, - MYKONOS_ERR_INV_AGC_OBSRX_PWR_STRUCT_INIT, - MYKONOS_ERR_INV_AGC_OBSRX_RESET_ON_RX_ENABLE, - MYKONOS_ERR_INV_AGC_OBSRX_SLOW_LOOP_SETTLING_DELAY, - MYKONOS_ERR_INV_AGC_OBSRX1_MAX_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX1_MIN_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX2_MAX_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX2_MIN_GAIN_INDEX, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_THRESH, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_THRESH, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_THRESH, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_THRESH, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_LOW_GAIN_STEP, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_LOWER_HIGH_GAIN_STEP, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_LOW_GAIN_STEP, - MYKONOS_ERR_INV_AGC_OBSRX_PMD_UPPER_HIGH_GAIN_STEP, - MYKONOS_ERR_INV_AGC_OBSRX_APD_HIGH_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_APD_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_HIGH_THRESH_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_GAIN_STEP_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_VERY_LOW_THRESH_PARM, - MYKONOS_ERR_INV_AGC_OBSRX_PKDET_FAST_ATTACK_VALUE, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_ENABLE, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_DUR_CNT, - MYKONOS_ERR_INV_AGC_OBSRX_HB2_OVLD_THRESH_CNT, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CALPLL_LOCK, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLLCP, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_CLKPLL_LOCK, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLLCP, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXPLL_LOCK, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLLCP, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXPLL_LOCK, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLLCP, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_SNIFFPLL_LOCK, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RXBBFCALDONE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_TXBBFCALDONE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RFDCCALDONE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ADCTUNECALDONE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX1ADCPROFILE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RX2ADCPROFILE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ORXADCPROFILE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_RCALDONE, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_ARMBUSY, - MYKONOS_ERR_WAITFOREVENT_TIMEDOUT_INITARMDONE, - MYKONOS_ERR_TIMEDOUT_ARMMAILBOXBUSY, - MYKONOS_ERR_PU_OBSRXPATH_ARMERROR, - MYKONOS_ERR_EN_TRACKING_CALS_ARMSTATE_ERROR, - MYKONOS_ERR_SET_RADIOCTRL_PINS_ARMERROR, - MYKONOS_ERR_EN_TRACKING_CALS_ARMERROR, - MYKONOS_ERR_SETRFPLL_ARMERROR, - MYKONOS_ERR_INIT_INV_TXINPUTHB_PARM, - MYKONOS_ERR_LOAD_ADCPROFILE_INV_VCODIV, - MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_RXREQUIRED, - MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_ORXREQUIRED, - MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_SNRXREQUIRED, - MYKONOS_ERR_SETUP_PA_PROT_INV_AVG_DURATION, - MYKONOS_ERR_SETUP_PA_PROT_INV_STICKY_ENABLE, - MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_STEP, - MYKONOS_ERR_SETUP_PA_PROT_INV_ATTEN_ENABLE, - MYKONOS_ERR_SETUP_PA_PROT_INV_POWER_THRESH, - MYKONOS_ERR_SETUP_PA_PROT_INV_TX_CHANNEL, - MYKONOS_ERR_GET_DAC_PWR_INV_POINTER, - MYKONOS_ERR_GET_PA_FLAG_STATUS_INV_POINTER, - MYKONOS_ERR_GET_OBSRX_OVERLOADS_NULL_PARM, - MYKONOS_ERR_GET_RX1_OVERLOADS_NULL_PARM, - MYKONOS_ERR_GET_RX2_OVERLOADS_NULL_PARM, - MYKONOS_ERR_GETRADIOSTATE_NULL_PARAM, - MYKONOS_ERR_ABORT_INITCALS_NULL_PARAM, - MYKONOS_ERR_ARM_RADIOOFF_FAILED, - MYKONOS_ERR_WAIT_INITCALS_NULL_PARAM, - MYKONOS_ERR_WAIT_INITCALS_CALFAILED, - MYKONOS_ERR_WAIT_INITCALS_ARMERROR, - MYKONOS_ERR_CHECK_PLL_LOCK_NULL_PARM, - MYKONOS_ERR_GET_TXFILTEROVRG_NULL_PARM, - MYKONOS_ERR_PROGRAM_RXGAIN_TABLE_NULL_PARM, - MYKONOS_ERR_PROGRAMFIR_NULL_PARM, - MYKONOS_ERR_PROGRAMFIR_COEFS_NULL, - MYKONOS_ERR_READ_DEFRAMERSTATUS_NULL_PARAM, - MYKONOS_ERR_READ_DEFRAMERPRBS_NULL_PARAM, - MYKONOS_ERR_READ_ORXFRAMERSTATUS_NULL_PARAM, - MYKONOS_ERR_READ_RXFRAMERSTATUS_NULL_PARAM, - MYKONOS_ERR_ARMCMDSTATUS_NULL_PARM, - MYKONOS_ERR_READARMCMDSTATUS_INV_OPCODE_PARM, - MYKONOS_ERR_READARMCMDSTATUS_NULL_PARM, - MYKONOS_ERR_READARMCMDSTATUSBYTE_NULL_PARM, - MYKONOS_ERR_ARMCMD_NULL_PARM, - MYKONOS_ERR_WRITEARMMEM_NULL_PARM, - MYKONOS_ERR_LOADBIN_NULL_PARAM, - MYKONOS_ERR_ARM_INV_ADDR_PARM, - MYKONOS_ERR_LOADARMCON_INVALID_BYTECOUNT, - MYKONOS_ERR_LOADARMCON_NULL_PARAM, - MYKONOS_ERR_GETTX1ATTEN_NULL_PARM, - MYKONOS_ERR_GETTX2ATTEN_NULL_PARM, - MYKONOS_ERR_ENFRAMERLINK_INV_LANESEN_PARM, - MYKONOS_ERR_ENOBSFRAMERLINK_INV_LANESEN_PARM, - MYKONOS_ERR_ENTXNCO_TXPROFILE_INVALID, - MYKONOS_ERR_ENTXNCO_TX1_FREQ_INVALID, - MYKONOS_ERR_ENTXNCO_TX2_FREQ_INVALID, - MYKONOS_ERR_JESD204B_ILAS_MISMATCH_NULLPARAM, - MYKONOS_ERR_LOAD_LBADCPROFILE_ARMMEM_FAILED, - MYKONOS_ERR_LOAD_SNRXADCPROFILE_ARMMEM_FAILED, - MYKONOS_ERR_LOAD_ADCPROFILE_SNRX_ADCDIV_ZERO, - MYKONOS_ERR_LOAD_ORXADCPROFILE_ARMMEM_FAILED, - MYKONOS_ERR_LOAD_ADCPROFILE_ORXADCDIV_ZERO, - MYKONOS_ERR_LOAD_RXADCPROFILE_ARMMEM_FAILED, - MYKONOS_ERR_LOAD_ADCPROFILE_RXADCDIV_ZERO, - MYKONOS_ERR_LOAD_ADCPROFILE_CUSTOM_LBREQUIRED, - MYKONOS_ERR_LOAD_ADCPROFILE_MISSING_ORX_PROFILE, - MYKONOS_ERR_GETRFPLL_INV_PLLNAME, - MYKONOS_ERR_GETRFPLL_ARMERROR, - MYKONOS_ERR_GETRFPLL_NULLPARAM, - MYKONOS_ERR_INITARM_INV_VCODIV, - MYKONOS_ERR_GET_PLLFREQ_INV_HSDIV, - MYKONOS_ERR_GET_PLLFREQ_INV_VCODIV, - MYKONOS_ERR_GET_PLLFREQ_INV_REFCLKDIV, - MYKONOS_ERR_SETORXGAIN_INV_ORX1GAIN, - MYKONOS_ERR_SETORXGAIN_INV_ORX2GAIN, - MYKONOS_ERR_SETORXGAIN_INV_SNRXGAIN, - MYKONOS_ERR_GET_RX1_DEC_POWER_NUM_SAMPLES, - MYKONOS_ERR_GET_RX1_DEC_POWER_NULL_PARM, - MYKONOS_ERR_GET_RX2_DEC_POWER_NUM_SAMPLES, - MYKONOS_ERR_GET_RX2_DEC_POWER_NULL_PARM, - MYKONOS_ERR_GET_OBSRX_DEC_POWER_NUM_SAMPLES, - MYKONOS_ERR_GET_OBSRX_DEC_POWER_NULL_PARM, - MYKONOS_ERR_GETARMVER_NULL_PARM, - MYKONOS_ERR_EN_CLGCTRACKING_ARMSTATE_ERROR, - MYKONOS_ERR_EN_DPDTRACKING_ARMSTATE_ERROR, - MYKONOS_ERR_RESTDPDMOD_WRONGBUFFERSIZE, - MYKONOS_ERR_RESTDPDMOD_ARMSTATE, - MYKONOS_ERR_RESTDPDMOD_INVALID_TXCHANNEL, - MYKONOS_ERR_RESTDPDMOD_ARMERRFLAG, - MYKONOS_ERR_SAVDPDMOD_WRONGBUFFERSIZE, - MYKONOS_ERR_SAVDPDMOD_ARMSTATE, - MYKONOS_ERR_SAVDPDMOD_INVALID_TXCHANNEL, - MYKONOS_ERR_SAVDPDMOD_ARMERRFLAG, - MYKONOS_ERR_WRITEARMCFG_ARMERRFLAG, - MYKONOS_ERR_CFGDPD_TXORX_PROFILE_INV, - MYKONOS_ERR_CFGDPD_NULL_DPDCFGSTRUCT, - MYKONOS_ERR_CFGDPD_INV_DPDDAMPING, - MYKONOS_ERR_CFGDPD_INV_DPDSAMPLES, - MYKONOS_ERR_CFGDPD_INV_DPDOUTLIERTHRESH, - MYKONOS_ERR_CFGDPD_INV_DPDPRIORWEIGHT, - MYKONOS_ERR_CFGCLGC_INV_DESIREDGAIN, - MYKONOS_ERR_CFGCLGC_INV_TXATTENLIMIT, - MYKONOS_ERR_CFGCLGC_INV_CLGC_CTRLRATIO, - MYKONOS_ERR_SETCLGCGAIN_INV_DESIREDGAIN, - MYKONOS_ERR_SETCLGCGAIN_INV_TXCHANNEL, - MYKONOS_ERR_SETCLGCGAIN_TRACK_ARMERRFLAG, - MYKONOS_ERR_CFGDPD_INV_DPD_ADDDELAY, - MYKONOS_ERR_CFGDPD_INV_PNSEQLEVEL, - MYKONOS_ERR_READARMCFG_ARMERRFLAG, - MYKONOS_ERR_GETPENDTRKCALS_NULL_PARAM, - MYKONOS_ERR_ARMCMDSTATUS_ARMERROR, - MYKONOS_ERR_WAITARMCMDSTATUS_TIMEOUT, - MYKONOS_ERR_PU_GETOBSRXPATH_ARMERROR, - MYKONOS_ERR_GETDPDCFG_NULL_DPDCFGSTRUCT, - MYKONOS_ERR_GETDPDCFG_TXORX_PROFILE_INV, - MYKONOS_ERR_GETDPDSTATUS_ARMERRFLAG, - MYKONOS_ERR_GETDPDSTATUS_NULLPARAM, - MYKONOS_ERR_SETDEFOBSRXPATH_NULL_OBSRX_STRUCT, - MYKONOS_ERR_SETDEFOBSRXPATH_NULL_DEF_OBSRX_STRUCT, - MYKONOS_ERR_GETCLGCSTATUS_NULLPARAM, - MYKONOS_ERR_GETCLGCSTATUS_ARMERRFLAG, - MYKONOS_ERR_CHECKDEVSTRUCT_NULLDEVPOINTER, - MYKONOS_ERR_READ_DEFFIFODEPTH_NULL_PARAM, - MYKONOS_ERR_READ_DEFFIFODEPTH_LMFCCOUNT_NULL_PARAM, - MYKONOS_ERR_GETDPDSTATUS_INV_CH, - MYKONOS_ERR_GETCLGCSTATUS_INV_CH, - MYKONOS_ERR_INIT_INV_TXINPUTHB_INV_RATE, - MYKONOS_ERR_INIT_INV_TXINPUTHB0_INV_RATE, - MYKONOS_ERR_TXFIR_TAPSEXCEEDED, - MYKONOS_ERR_TXFIR_INV_NUMROWS, - MYKONOS_ERR_TXFIR_INV_NUMTAPS_PARM, - MYKONOS_ERR_RXFIR_TAPSEXCEEDED, - MYKONOS_ERR_ORXFIR_TAPSEXCEEDED, - MYKONOS_ERR_SNRXFIR_TAPSEXCEEDED, - MYKONOS_ERR_GETINITCALSTATUS_NULL_PARAM, - MYKONOS_ERR_GETINITCALSTATUS_ARMERROR, - MYKONOS_ERR_CFGDPD_INV_NUMWEIGHTS, - MYKONOS_ERR_CFGDPD_INV_MODELVERSION, - MYKONOS_ERR_SETDPDACT_INV_TXCHANNEL, - MYKONOS_ERR_SETDPDACT_INV_STATE, - MYKONOS_ERR_SETDPDACT_ARMERRFLAG, - MYKONOS_ERR_CFGCLGC_TXORX_PROFILE_INV, - MYKONOS_ERR_CFGCLGC_NULL_CLGCCFGSTRUCT, - MYKONOS_ERR_GETCLGCCFG_TXORX_PROFILE_INV, - MYKONOS_ERR_GETCLGCCFG_NULL_CFGSTRUCT, - MYKONOS_ERR_CALCDIGCLK_NULLDEV_PARAM, - MYKONOS_ERR_CALCDIGCLK_NULL_CLKSTRUCT, - MYKONOS_ERR_CFGCLGC_INV_CLGC_ADDDELAY, - MYKONOS_ERR_CFGCLGC_INV_PNSEQLEVEL, - MYKONOS_ERR_CFGVSWR_TXORX_PROFILE_INV, - MYKONOS_ERR_CFGVSWR_ARMSTATE_ERROR, - MYKONOS_ERR_CFGVSWR_INV_3P3GPIOPIN, - MYKONOS_ERR_CFGVSWR_INV_PNSEQLEVEL, - MYKONOS_ERR_CFGVSWR_INV_VSWR_ADDDELAY, - MYKONOS_ERR_CFGVSWR_NULL_VSWRCFGSTRUCT, - MYKONOS_ERR_GETVSWRCFG_NULL_CFGSTRUCT, - MYKONOS_ERR_GETVSWRCFG_TXORX_PROFILE_INV, - MYKONOS_ERR_GETVSWRSTATUS_ARMERRFLAG, - MYKONOS_ERR_GETVSWRSTATUS_INV_CH, - MYKONOS_ERR_GETVSWRSTATUS_NULLPARAM, - MYKONOS_ERR_SET_RX_MAX_GAIN_INDEX, - MYKONOS_ERR_SET_RX_MIN_GAIN_INDEX, - MYKONOS_ERR_AGC_MIN_MAX_RX_CHANNEL, - MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX_CHANNEL, - MYKONOS_ERR_SET_ORX_MAX_GAIN_INDEX, - MYKONOS_ERR_SET_ORX_MIN_GAIN_INDEX, - MYKONOS_ERR_AGC_MIN_MAX_ORX_CHANNEL, - MYKONOS_ERR_RX1_TEMP_GAIN_COMP_RANGE, - MYKONOS_ERR_RX2_TEMP_GAIN_COMP_RANGE, - MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_RANGE, - MYKONOS_ERR_RX1_TEMP_GAIN_COMP_STEP, - MYKONOS_ERR_RX2_TEMP_GAIN_COMP_STEP, - MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_STEP, - MYKONOS_ERR_RX1_TEMP_GAIN_COMP_NULL, - MYKONOS_ERR_RX2_TEMP_GAIN_COMP_NULL, - MYKONOS_ERR_OBS_RX_TEMP_GAIN_COMP_NULL, - MYKONOS_ERR_GETTXLOLSTATUS_NULLPARAM, - MYKONOS_ERR_GETTXLOLSTATUS_INV_CH, - MYKONOS_ERR_GETTXLOLSTATUS_ARMERRFLAG, - MYKONOS_ERR_GETTXQECSTATUS_NULLPARAM, - MYKONOS_ERR_GETTXQECSTATUS_INV_CH, - MYKONOS_ERR_GETTXQECSTATUS_ARMERRFLAG, - MYKONOS_ERR_GETRXQECSTATUS_NULLPARAM, - MYKONOS_ERR_GETRXQECSTATUS_INV_CH, - MYKONOS_ERR_GETRXQECSTATUS_ARMERRFLAG, - MYKONOS_ERR_GETORXQECSTATUS_NULLPARAM, - MYKONOS_ERR_GETORXQECSTATUS_INV_CH, - MYKONOS_ERR_GETORXQECSTATUS_ARMERRFLAG, - MYKONOS_ERR_RESCHEDULE_TRACK_CAL_INV, - MYKONOS_ERR_RESCHEDULE_TRACK_ARMERRFLAG, - - MYKONOS_ERR_SETSTATEALL_TRACK_CAL_INV, - MYKONOS_ERR_SETSTATEALL_TRACK_ARMERRFLAG, - - MYKONOS_ERR_GETSTATEALL_TRACK_NULL_PARAM, - MYKONOS_ERR_GETSTATEALL_TRACK_ARMERRFLAG, - MYKONOS_ERR_GETSTATEALL_TRACK_ARMERROR, - - MYKONOS_ERR_SETSTATE_TRACK_CAL_INV, - MYKONOS_ERR_SETSTATE_TRACK_ARMERRFLAG, - - MYKONOS_ERR_GETSTATE_TRACK_NULL_PARAM, - MYKONOS_ERR_GETSTATE_TRACK_ARMERRFLAG, - MYKONOS_ERR_GETSTATE_TRACK_ARMERROR, - - MYKONOS_ERR_ARMSTATE_PROFILE_ERROR, - MYKONOS_ERR_ARMSTATE_CAL_ERROR, - MYKONOS_ERR_ARMSTATE_EXCEPTION, - MYKONOS_ERR_WAITARMCSTATE_TIMEOUT, - - MYKONOS_ERR_GETPRODUCTID_NULL_PARAM, - MYKONOS_ERR_GET_API_VERSION_NULL_PARAM, - - MYKONOS_ERR_PROFILES_HSDIGCLK, - MYKONOS_ERR_RXPROFILE_RXCHANNEL, - MYKONOS_ERR_RXPROFILE_IQRATE, - MYKONOS_ERR_RXPROFILE_RFBW, - MYKONOS_ERR_RXPROFILE_FILTER_DECIMATION, - MYKONOS_ERR_RXPROFILE_FIR_COEFS, - MYKONOS_ERR_RXPROFILE_ADCDIV, - MYKONOS_ERR_TXPROFILE_IQRATE, - MYKONOS_ERR_TXPROFILE_RFBW, - MYKONOS_ERR_TXPROFILE_FILTER_INTERPOLATION, - MYKONOS_ERR_TXPROFILE_FIR_COEFS, - MYKONOS_ERR_TXPROFILE_DACDIV, - MYKONOS_ERR_RESET_TXLOL_INV_PARAM, - MYKONOS_ERR_RESET_TXLOL_ARMERROR, - MYKONOS_ERR_SETRFPLL_LF_INV_STABILITY, - MYKONOS_ERR_SETRFPLL_LF_PLLNAME, - MYKONOS_ERR_SETRFPLL_LF_INV_TXRX_LOOPBANDWIDTH, - MYKONOS_ERR_SETRFPLL_LF_INV_SNF_LOOPBANDWIDTH, - MYKONOS_ERR_SETRFPLL_LF_ARMERROR, - MYKONOS_ERR_GETRFPLL_LF_ARMERROR, - MYKONOS_ERR_GETRFPLL_LF_NULLPARAM, - MYKONOS_ERR_GETRFPLL_LF_INV_PLLNAME, - MYKONOS_ERR_DC_OFFSET_INV_CHAN, - MYKONOS_ERR_SET_RF_DC_OFFSET_INV_MEASURECNT, - MYKONOS_ERR_SET_RF_DC_OFFSET_MEASURECNT_MIN_LIMIT, - MYKONOS_ERR_GET_RF_DC_OFFSET_NULL_MEASURECNT, - MYKONOS_ERR_RF_DC_OFFSET_INV_ENABLE_MASK, - MYKONOS_ERR_RF_DC_OFFSET_NULL_ENABLE_MASK, - MYKONOS_ERR_SET_DIG_DC_OFFSET_INV_MSHIFT, - MYKONOS_ERR_GET_DIG_DC_OFFSET_NULL_MSHIFT, - MYKONOS_ERR_DIG_DC_OFFSET_INV_ENABLE_MASK, - MYKONOS_ERR_DIG_DC_OFFSET_NULL_ENABLE_MASK, - MYKONOS_ERR_CFGCLGC_INV_THRESHOLD, - MYKONOS_ERR_RESETDPD_INV_TXCHANNEL, - MYKONOS_ERR_RESETDPD_ARMERRFLAG, - MYKONOS_ERR_RESETDPD_WRONG_PARAM, - MYKONOS_WRN_RADIO_ON_NOT_MODIFIABLE, - MYKONOS_ERR_SET_PATH_DELAY_NULL_PARAM, - MYKONOS_ERR_SET_PATH_DELAY_PARAM_OUT_OF_RANGE, - MYKONOS_ERR_GET_PATH_DELAY_NULL_PARAM, - MYKONOS_ERR_GET_PATH_DELAY_INVALID_SELECTION, - MYKONOS_ERR_GET_PATH_DELAY_ARMERRFLAG, - - - MYKONOS_ERR_GETDPD_ERROR_CNT_NULLPARAM, - MYKONOS_ERR_GETDPD_ERROR_CNT_INV_CH, - MYKONOS_ERR_GETDPD_ERROR_CNT_ARMERRFLAG, - - MYKONOS_ERR_SETDPDACT_NULL_ACTSTRUCT, - MYKONOS_ERR_SETDPDACT_INV_ACTMODE, - MYKONOS_ERR_SETDPDACT_INV_LEVEL, - MYKONOS_ERR_GETDPDACT_NULL_ACTSTRUCT, - - MYKONOS_ERR_SETDPDACTCHECK_NULL_ACTSTRUCT, - MYKONOS_ERR_SETDPDACTCHECK_INV_ACTMODE, - MYKONOS_ERR_SETDPDACTCHECK_INV_LEVEL, - MYKONOS_ERR_GETDPDACTCHECK_NULL_ACTSTRUCT, - - MYKONOS_ERR_CLGCATTENTUNCFG_NULL_ATTRANGECFGSTRUCT, - MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_MODE, - MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_PRESET, - MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_RANGE, - MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX1_SETTINGS, - MYKONOS_ERR_CLGCATTENTUNCFG_INVALID_TX2_SETTINGS, - - MYKONOS_ERR_CLGCATTENTUNCFGGET_NULL_ATTRANGECFGSTRUCT, - - MYKONOS_ERR_END -} mykonosErr_t; - -/** - * \brief Enum for Mykonos low voltage GPIO available pins - */ -typedef enum -{ - MYKGPIONAN = 0x00, - MYKGPIO0 = 0x1, - MYKGPIO1 = 0x2, - MYKGPIO2 = 0x4, - MYKGPIO3 = 0x8, - MYKGPIO4 = 0x10, - MYKGPIO5 = 0x20, - MYKGPIO6 = 0x40, - MYKGPIO7 = 0x80, - MYKGPIO8 = 0x100, - MYKGPIO9 = 0x200, - MYKGPIO10 = 0x400, - MYKGPIO11 = 0x800, - MYKGPIO12 = 0x1000, - MYKGPIO13 = 0x2000, - MYKGPIO14 = 0x4000, - MYKGPIO15 = 0x8000, - MYKGPIO16 = 0x10000, - MYKGPIO17 = 0x20000, - MYKGPIO18 = 0x40000 -} mykonosGpioSelect_t; - - -/** - * \brief Enum of valid Mykonos Enable State Machine (ENSM) states - */ -typedef enum -{ - WAIT = 0, /*!< Mykonos ENSM state upon which a power up in the WAIT/SLEEP state occurs */ - INIT = 1, /*!< Mykonos ENSM state upon which a power up delay state ocurrs to allow clocks to stabilize */ - WAITCALS = 2, /*!< Mykonos ENSM state upon which calibrations are initializing */ - ALERTCALS = 3, /*!< Mykonos ENSM state upon which calibrations are occurring */ - ALERTLDS = 4, /*!< Mykonos ENSM state upon which a delay state is occurring when moving from WAIT to ALERT to allow internal circuits to power up */ - ALERT = 5, /*!< Mykonos ENSM state upon which the internal RF synth is powered up, and TX and RX data paths are still powered down */ - TX_RX = 6, /*!< Mykonos ENSM state upon which the ability to power up data paths depending on the TxEnable/RxEnable pins or SPI bits */ - FLUSH = 7 /*!< Mykonos ENSM state upon which the data paths are cleared when exiting the TX_RX state */ -} mykonosEnsmState_t; - - -/** - * \brief Enum of possible Tx channels - */ -typedef enum -{ - TXOFF = 0, - TX1 = 1, - TX2 = 2, - TX1_TX2 = 3 -} mykonosTxChannels_t; - -/** - * \brief Enum of possible Rx channels - */ -typedef enum -{ - RXOFF = 0, - RX1 = 1, - RX2 = 2, - RX1_RX2 = 3 -} mykonosRxChannels_t; - -/** - * \brief Enum of possible Observation Rx channels - */ -typedef enum -{ - OBS_RXOFF = 0, - OBS_RX1_TXLO = 1, - OBS_RX2_TXLO = 2, - OBS_INTERNALCALS = 3, - OBS_SNIFFER = 4, - OBS_RX1_SNIFFERLO = 5, - OBS_RX2_SNIFFERLO = 6, - OBS_SNIFFER_A = 0x14, - OBS_SNIFFER_B = 0x24, - OBS_SNIFFER_C = 0x34 -} mykonosObsRxChannels_t; - -/** - * \brief Enum of possible Sniffer Rx channels - */ -typedef enum -{ - SNIFFER_A = 1, - SNIFFER_B = 2, - SNIFFER_C = 3 -} mykonosSnifferChannel_t; - -/** - * \brief Enum of possible Observation Rx channels to enable and run calibrations for during init. - * Choose ENUM value that enables all channels that will be used in the system. During system use, - * only one channel can be used at a time. This is also used to alert the ARM processor - * which observation channels are valid for the current desired system setup. - */ -typedef enum -{ - MYK_OBS_RXOFF = 0x00, - MYK_ORX1 = 0x01, - MYK_ORX2 = 0x02, - MYK_ORX1_ORX2 = 0x03, - MYK_SNRXA = 0x04, - MYK_SNRXB = 0x08, - MYK_SNRXC = 0x10, - MYK_SNRXA_B_C = 0x1C -} mykonosObsRxChannelsEn_t; - -/** - * \brief Enum of possible DAC divider settings (2x, 2.5x, 4x) - */ -typedef enum -{ - DACDIV_2, - DACDIV_2p5, - DACDIV_4 -} mykonosDacDiv_t; - -/** - * \brief Enum of possible VCO divider settings (1x, 1.5x, 2x, 3x) - */ -typedef enum -{ - VCODIV_1 = 0, - VCODIV_1p5 = 1, - VCODIV_2 = 2, - VCODIV_3 = 3 -} mykonosVcoDiv_t; - -/** - * \brief Enum of possible PRBS pattern settings - */ -typedef enum -{ - MYK_PRBS7 = 0, - MYK_PRBS15 = 1, - MYK_PRBS31 = 2 -} mykonosPrbsOrder_t; - -/** - * \brief Enum of RF PLL names - */ -typedef enum -{ - CLK_PLL, - RX_PLL, - TX_PLL, - SNIFFER_PLL -} mykonosRfPllName_t; - -/** - * \brief Enum of Rx profile types - */ -typedef enum -{ - MYK_RX_PROFILE, - MYK_OBS_PROFILE, - MYK_SNIFFER_PROFILE -} mykonosRxProfType_t; - -/** - * \brief Enum of ORx PLL names - */ -typedef enum -{ - OBSLO_TX_PLL, - OBSLO_SNIFFER_PLL -} mykonosObsRxLoSource_t; - -/** - * \brief Enum of possible wait events to use with MYKONOS_waitForEvent() - */ -typedef enum -{ - CALPLL_LOCK, - CLKPLLCP, - CLKPLL_LOCK, - RF_RXPLLCP, - RF_RXPLL_LOCK, - RF_TXPLLCP, - RF_TXPLL_LOCK, - RF_SNIFFERPLLCP, - RF_SNIFFERPLL_LOCK, - RXBBF_CALDONE, - TXBBF_CALDONE, - RX_RFDC_CALDONE, - RX_ADCTUNER_CALDONE, - RX1_ADCPROFILE, - RX2_ADCPROFILE, - ORX_ADCPROFILE, - RCAL_CALDONE, - ARMBUSY, - INITARM_DONE -} waitEvent_t; - -/** - * \brief Enum to set the desired FIR filter type for related functions - */ -typedef enum -{ - TX1_FIR = 1, - TX2_FIR = 2, - TX1TX2_FIR = 3, - RX1_FIR = 4, - RX2_FIR = 8, - RX1RX2_FIR = 12, - OBSRX_A_FIR = 16, - OBSRX_B_FIR = 32 -} mykonosfirName_t; - -/** - * \brief Enum to set the desired Rx gain table channel - */ -typedef enum -{ - RX1_GT = 1, - RX2_GT, - RX1_RX2_GT, - ORX_GT, - SNRX_GT, - LOOPBACK_GT -}mykonosGainTable_t; - -/** - * \brief Enum to set the Rx Gain control mode - */ -typedef enum -{ - MGC = 0, /*!< Manual Gain Control */ - AGC = 2, /*!< Automatic Gain Control (AGC) */ - HYBRID = 3 /*!< Hybrid AGC Gain Control */ - -} mykonosGainMode_t; - -/** - * \brief Enum to set the Tx Atenuation step size - */ -typedef enum -{ - TXATTEN_0P05_DB = 0, /*!< Tx attenuation 0.05dB step size */ - TXATTEN_0P1_DB = 1, /*!< Tx attenuation 0.1dB step size */ - TXATTEN_0P2_DB = 2, /*!< Tx attenuation 0.2dB step size */ - TXATTEN_0P4_DB = 3 /*!< Tx attenuation 0.4dB step size */ -} mykonosTxAttenStepSize_t; - -/** - * \brief Enum to help set the init calibration mask - */ -typedef enum -{ - TX_BB_FILTER = 0x0001, - ADC_TUNER = 0x0002, - TIA_3DB_CORNER = 0x0004, - DC_OFFSET = 0x0008, - TX_ATTENUATION_DELAY = 0x0010, - RX_GAIN_DELAY = 0x0020, - FLASH_CAL = 0x0040, - PATH_DELAY = 0x0080, - TX_LO_LEAKAGE_INTERNAL = 0x0100, - TX_LO_LEAKAGE_EXTERNAL = 0x0200, - TX_QEC_INIT = 0x0400, - LOOPBACK_RX_LO_DELAY = 0x0800, - LOOPBACK_RX_RX_QEC_INIT = 0x1000, - RX_LO_DELAY = 0x2000, - RX_QEC_INIT = 0x4000, - DPD_INIT = 0x8000, - CLGC_INIT = 0x10000, - VSWR_INIT = 0x20000 -} mykonosInitCalibrations_t; - -/** - * \brief Enum to help set the tracking calibration mask - */ -typedef enum -{ - TRACK_RX1_QEC = 0x00001, - TRACK_RX2_QEC = 0x00002, - TRACK_ORX1_QEC = 0x00004, - TRACK_ORX2_QEC = 0x00008, - TRACK_TX1_LOL = 0x00010, - TRACK_TX2_LOL = 0x00020, - TRACK_TX1_QEC = 0x00040, - TRACK_TX2_QEC = 0x00080, - TRACK_TX1_DPD = 0x00100, - TRACK_TX2_DPD = 0x00200, - TRACK_TX1_CLGC = 0x00400, - TRACK_TX2_CLGC = 0x00800, - TRACK_TX1_VSWR = 0x01000, - TRACK_TX2_VSWR = 0x02000, - TRACK_ORX1_QEC_SNLO = 0x10000, - TRACK_ORX2_QEC_SNLO = 0x20000, - TRACK_SRX_QEC = 0x40000 -} mykonosTrackingCalibrations_t; - - -/** - * \brief Enum to select the desired status calibration path delay read back - */ -typedef enum -{ - MYK_DPD_PATH_DELAY = 0, - MYK_CLGC_PATH_DELAY = 1, - MYK_VSWR_PATH_DELAY = 2 -} mykonosPathDelaySel_t; - -/** - * \brief Enum to set the GPIO3v3 mode - */ -typedef enum -{ - GPIO3V3_LEVELTRANSLATE_MODE = 1, /*!< Level translate mode, signal level on low voltage GPIO output on GPIO3v3 pins */ - GPIO3V3_INVLEVELTRANSLATE_MODE = 2, /*!< Inverted Level translate mode, inverse of signal level on low voltage GPIO output on GPIO3v3 pins */ - GPIO3V3_BITBANG_MODE = 3, /*!< Manual mode, API function sets output pin levels and reads input pin levels */ - GPIO3V3_EXTATTEN_LUT_MODE = 4 /*!< GPIO3v3 output level follows Rx1/Rx2 gain table external control 6bit field. */ -} mykonosGpio3v3Mode_t; - -/** - * \brief Enum to set the low voltage GPIO mode - */ -typedef enum -{ - GPIO_MONITOR_MODE = 0, /*!< Allows a choice of debug signals to output from Mykonos to monitor the state of the device */ - GPIO_BITBANG_MODE = 3, /*!< Manual mode, API function sets output pin levels and reads input pin levels */ - GPIO_ARM_OUT_MODE = 9, /*!< Allows internal ARM processor to output on GPIO pins */ - GPIO_SLICER_OUT_MODE = 10 /*!< Allows Slicer active configuration to the GPIO output pins */ -} mykonosGpioMode_t; - -/** - * \brief Enum for ARM states - */ -typedef enum -{ - MYK_ARM_POWERUP = 0x00, /*!< ARM is powered up and ready to be programmed */ - MYK_ARM_READY = 0x01, /*!< ARM enter this state once the boot up sequence is completed */ - MYK_ARM_IDLE = 0x02, /*!< ARM enter this state after initial calibrations are completed */ - MYK_ARM_RADIO_ON = 0x04, /*!< ARM has moved from MYKONOS_ARM_IDLE state into MYKONOS_ARM_RADIO_ON after the proper command, an abort command will move back to MYKONOS_ARM_IDLE state */ - MYK_ARM_PROFILE_ERROR = 0x08, /*!< ARM has detected an illegal profile */ - MYK_ARM_CAL_ERROR = 0x40, /*!< ARM has detected an error in the tracking calibrations */ - MYK_ARM_EXCEPTION = 0x80 /*!< ARM system problem has been detected */ -} mykonosArmState_t; - -/** - * \brief Enum for channel selection for DC offset settings. - */ -typedef enum -{ - MYK_DC_OFFSET_RX_CHN = 0x01, /*!< Select Rx channel */ - MYK_DC_OFFSET_ORX_CHN = 0x02, /*!< Select ORx channel */ - MYK_DC_OFFSET_SNF_CHN = 0x04 /*!< Select Sniffer channel */ -}mykonosDcOffsetChannels_t; - -/** - * \brief Enum of Rx channels for configuring (Enable /disable) DC offsets. - */ -typedef enum -{ - MYK_DC_OFFSET_ALL_OFF = 0x00, /*!< Disable all the channels */ - MYK_DC_OFFSET_RX1 = 0x01, /*!< Enables Rx1 */ - MYK_DC_OFFSET_RX2 = 0x02, /*!< Enables Rx2 */ - MYK_DC_OFFSET_SNF = 0x04, /*!< Enables Sniffer */ - MYK_DC_OFFSET_ORX = 0x08, /*!< Enables ORx */ - MYK_DC_OFFSET_AVAILABLE = 0x0F /*!< Enables all the channels */ -}mykonosRxDcOffsettEn_t; - -/** - * \brief Enum of build type - */ -typedef enum -{ - MYK_BUILD_RELEASE = 0X00, - MYK_BUILD_DEBUG = 0x01, - MYK_BUILD_TEST_OBJECT = 0x04 -}mykonosBuild_t; - -/** - * \brief Enum for DPD error codes - */ -typedef enum -{ - MYK_NO_ERROR = 0, /*!< No Error */ - MYK_ORX_DISABLED = 1, /*!< ORX_DISABLED */ - MYK_TX_DISABLED = 2, /*!< TX_DISABLED */ - MYK_PATHDELAY_NOT_SETUP = 3, /*!< PATHDELAY_NOT_SETUP */ - MYK_DPD_INIT_NOT_RUN = 4, /*!< DPD_INIT_NOT_RUN */ - MYK_ORX_SIG_TOO_LOW = 5, /*!< ORX_SIG_TOO_LOW */ - MYK_ORX_SIG_SATURATED = 6, /*!< ORX_SIG_SATURATED */ - MYK_TX_SIG_TOO_LOW = 7, /*!< TX_SIG_TOO_LOW */ - MYK_TX_SIG_SATURATED = 8, /*!< TX_SIG_SATURATED */ - MYK_MODEL_ERROR_HIGH = 9, /*!< MODEL_ERROR_HIGH */ - MYK_AM_AM_OUTLIERS = 10, /*!< AM_AM_OUTLIERS */ - MYK_INVALID_TX_PROFILE = 11, /*!< INVALID_TX_PROFILE */ - MYK_ORX_TRACKING_DISABLED = 12, /*!< ORX_TRACKING_DISABLED ORx tracking must be enabled */ - MYK_ERR_RESERVED_13 = 13, /*!< Reserved DPD error */ - MYK_ERR_BAD_ACTUATOR_MODEL = 14, /*!< DPD actuator model is in bad state */ - MYK_ERR_LOW_POWER_ACTUATOR_BYPASS = 15, /*!< DPD actuator bypassed due to low input power */ - - MYK_DPD_ERROR_END -} mykonosDpdErrors_t; - -/** - * \brief Enum for DPD reset modes - */ -typedef enum -{ - MYK_DPD_NO_ACTION = 0, /*!< DPD no Action error */ - MYK_DPD_RESET_FULL = 1, /*!< Full DPD reset */ - MYK_DPD_RESET_PRIOR = 4, /*!< Reset only prior model */ - MYK_DPD_RESET_CORRELATOR = 8, /*!< Reset correlator only */ - - MYK_DPD_RESET_END -} mykonosDpdResetMode_t; - - -/** - * \brief Enum for CLGC Tx attenuation tuning range modes - */ -typedef enum -{ - MYK_CLGC_ATTEN_TUNING_PRESET = 0, /*!< Set attenuation to the tx[]AttenTuningPreset */ - MYK_CLGC_ATTEN_DISCARD = 1, /*!< Ignore calculated attenuation level and keep the existing one */ - MYK_CLGC_ATTEN_UPDATE = 2, /*!< Set attenuation to tx[]AttenTuningPreset + tx[]AttenTuningRange if calculated attenuation is above this level - Set attenuation to tx[]AttenTuningPreset - tx[]AttenTuningRange if calculated attenuation is below this level*/ - - MYK_CLGC_ATTEN_END -} mykonosClgcAttenTuningMode_t; - -/** - * \brief Data structure to hold 3.3 VDC GPIO settings - */ -typedef struct -{ - uint16_t gpio3v3Oe; /*!< Pin direction: bit per 3.3v GPIO, 0=Input, 1=Output from Mykonos device */ - mykonosGpio3v3Mode_t gpio3v3SrcCtrl3_0; /*!< Mode for GPIO3v3[3:0] pins */ - mykonosGpio3v3Mode_t gpio3v3SrcCtrl7_4; /*!< Mode for GPIO3v3[7:4] pins */ - mykonosGpio3v3Mode_t gpio3v3SrcCtrl11_8; /*!< Mode for GPIO3v3[11:8] pins */ -} mykonosGpio3v3_t; - -/** - * \brief Data structure to hold low voltage GPIO settings - */ -typedef struct -{ - uint32_t gpioOe; /*!< Output Enable per low voltage GPIO pin (1=output, 0=input) */ - mykonosGpioMode_t gpioSrcCtrl3_0; /*!< Mode for low voltage GPIO[3:0] pins */ - mykonosGpioMode_t gpioSrcCtrl7_4; /*!< Mode for low voltage GPIO[7:4] pins */ - mykonosGpioMode_t gpioSrcCtrl11_8; /*!< Mode for low voltage GPIO[11:8] pins */ - mykonosGpioMode_t gpioSrcCtrl15_12; /*!< Mode for low voltage GPIO[15:12] pins */ - mykonosGpioMode_t gpioSrcCtrl18_16; /*!< Mode for low voltage GPIO[18:16] pins */ -} mykonosGpioLowVoltage_t; - -/** - * \brief Structure used within the DPD config structure to hold a int8_t complex number - */ -typedef struct{ - int8_t real; /*!< real part of the complex number */ - int8_t imag; /*!< imaginary part of the complex number */ -} int8_cpx; - -/** - * \brief Structure to configure DPD (Only valid for a DPD-enabled transceiver) - * \deprecated robustModeling member of this structure is no longer in use. - * This information is loaded into the ARM memory using the - * MYKONOS_configDpd() function before running the DPD init or tracking - * calibrations. These values can only be changed when the ARM is in the - * radioOff state. - */ -typedef struct -{ - uint8_t damping; /*!< 1/2^(damping + 8) fraction of previous model 'forgotten' per adaptation (default: 5 = '1/8192' , valid 0 to 15), 0 = infinite damping */ - uint8_t numWeights; /*!< number of weights to use for int8_cpx weights weights member of this structure (default = 1) */ - uint8_t modelVersion; /*!< DPD model version: one of four different generalized polynomial models: 0 = same as R0 silicon, 1-3 are new and the best one depends on the PA (default: 2) */ - uint8_t highPowerModelUpdate; /*!< 1 = Update saved model whenever peak Tx digital RMS is within 1dB of historical peak Tx RMS */ - uint8_t modelPriorWeight; /*!< Determines how much weight the loaded prior model has on DPD modeling (Valid 0 - 32, default 20) */ - uint8_t robustModeling; /*!< This is deprecated and no longer in use */ - uint16_t samples; /*!< number of samples to capture (default: 512, valid 64 - 32768) */ - uint16_t outlierThreshold; /*!< threshold for sample in AM-AM plot outside of 1:1 line to be thrown out. (default: 50% = 8192/2, valid 8192 to 1) */ - int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ - uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ - int8_cpx weights[3]; /*!< DPD model error weighting (real/imag valid from -128 to 127) */ -} mykonosDpdConfig_t; - -/** - * \brief Structure to configure the feature to bypass DPD actuator when signal power below a threshold - * - */ -typedef struct -{ - uint8_t bypassActuatorEn; /*!< Enable/Disable feature to bypass actuator when input power below a certain threshold */ - mykonosDpdResetMode_t bypassActuatorMode; /*!< Follows reset DPD enum */ - uint16_t bypassActuatorLevel; /*!< Tx RMS level below which actuator is bypassed. P_dBFS = 20*log10(bypassActuatorLevel/8192) */ -} mykonosDpdBypassConfig_t; - - - -/** - * \brief Structure to configure the DPD actuator gain check - * - */ -typedef struct -{ - uint8_t actuatorGainCheckEn; /*!< Enable Gain check for DPD actuator */ - mykonosDpdResetMode_t actuatorGainCheckMode; /*!< Follows reset DPD enum */ - uint16_t actuatorGainCheckLevel; /*!< If the gain difference before and after the actuator exceeds this value an error will be issued - and the actuator will reset depending on the actuatorGainCheckMode, in 0.01dB, where a value of 200 => 2dB*/ -} mykonosDpdActuatorCheck_t; - -/** - * \brief Structure to configure CLGC (Closed Loop Gain Control) (Only valid for a DPD-enabled transceiver) - * - * This information is loaded into the ARM memory using the - * MYKONOS_configClgc() function before running the CLGC init or tracking - * calibrations. - * These values can be changed when the ARM is in the radioOff or radioOn states. - */ -typedef struct -{ - int16_t tx1DesiredGain; /*!< (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx1 output to ORx1 input in (dB * 100) */ - int16_t tx2DesiredGain; /*!< (value = 100 * dB (valid range -32768 to 32767) - total gain and attenuation from Mykonos Tx2 output to ORx2 input in (dB * 100) */ - uint16_t tx1AttenLimit; /*!< (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx1Atten is not reduced below the limit */ - uint16_t tx2AttenLimit; /*!< (valid range 0 - 40dB), no default, depends on PA, Protects PA by making sure Tx2Atten is not reduced below the limit */ - uint16_t tx1ControlRatio; /*!< valid range 1-100, default 45 */ - uint16_t tx2ControlRatio; /*!< valid range 1-100, default 45 */ - uint8_t allowTx1AttenUpdates; /*!< 0= allow CLGC to run, but Tx1Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx1Atten automatically updated */ - uint8_t allowTx2AttenUpdates; /*!< 0= allow CLGC to run, but Tx2Atten will not be updated. User can still read back power measurements. 1=CLGC runs, and Tx2Atten automatically updated */ - - int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ - uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ - - uint16_t tx1RelThreshold; /*!< Threshold for Tx1 in order to stop tracking, value = 100 * dB, default 6db then value = 600 */ - uint16_t tx2RelThreshold; /*!< Threshold for Tx2 in order to stop tracking, value = 100 * dB, default 6db then value = 600 */ - uint8_t tx1RelThresholdEn; /*!< Threshold feature enable for Tx1, 0 = disable, 1 = enable, default = 0 */ - uint8_t tx2RelThresholdEn; /*!< Threshold feature enable for Tx2, 0 = disable, 1 = enable, default = 0 */ -} mykonosClgcConfig_t; - -/** - * \brief Structure to configure the CLGC attenuation tuning range - */ -typedef struct -{ - mykonosClgcAttenTuningMode_t tx1AttenTuningLimitMode; /*!< Tx1 CLGC Attenuation tuning mode */ - mykonosClgcAttenTuningMode_t tx2AttenTuningLimitMode; /*!< Tx2 CLGC Attenuation tuning mode */ - uint16_t tx1AttenTuningPreset; /*!< Tx1 CLGC nominal attenuation, valid range is 0 to 839 with a 0.05dB*/ - uint16_t tx2AttenTuningPreset; /*!< Tx2 CLGC nominal attenuation, valid range is 0 to 839 with a 0.05dB*/ - uint16_t tx1AttenTuningRange; /*!< Tx1 CLGC relative attenuation range around nominal attenuation, valid range is 0 to 420 with a 0.05dB*/ - uint16_t tx2AttenTuningRange; /*!< Tx2 CLGC relative attenuation range around nominal attenuation, valid range is 0 to 420 with a 0.05dB*/ -} mykonosClgcAttenTuningConfig_t; - -/** - * \brief Structure to configure VSWR (Only valid for a DPD-enabled transceiver) - * - * This information is loaded into the ARM memory using the - * MYKONOS_configVswr() function before running the VSWR init or tracking - * calibrations. - * These values can be changed when the ARM is in the radioOff states. - */ -typedef struct -{ - /* VSWR init cal parameters */ - int16_t additionalDelayOffset; /*!< 16th of an ORx sample (16=1sample), (default 0, valid -64 to 64) */ - uint16_t pathDelayPnSeqLevel; /*!< Default 255 (-30dBFs=(20Log10(value/8192)), (valid range 1 to 8191) */ - - /* VSWR tracking cal parameters */ - uint8_t tx1VswrSwitchGpio3p3Pin; /*!< 3p3V GPIO pin to use to control VSWR switch for Tx1 (valid 0-11) (output from Mykonos) */ - uint8_t tx2VswrSwitchGpio3p3Pin; /*!< 3p3V GPIO pin to use to control VSWR switch for Tx2 (valid 0-11) (output from Mykonos) */ - uint8_t tx1VswrSwitchPolarity; /*!< 3p3v GPIO pin polarity for forward path of Tx1, opposite used for reflection path (1 = high level, 0 = low level) */ - uint8_t tx2VswrSwitchPolarity; /*!< 3p3v GPIO pin polarity for forward path of Tx2, opposite used for reflection path (1 = high level, 0 = low level) */ - uint8_t tx1VswrSwitchDelay_us; /*!< Delay for Tx1 after flipping the VSWR switch until measurement is made. In us resolution with a range from 0 to 255us */ - uint8_t tx2VswrSwitchDelay_us; /*!< Delay for Tx2 after flipping the VSWR switch until measurement is made. In us resolution with a range from 0 to 255us */ -} mykonosVswrConfig_t; - -typedef struct -{ - /** - * errorStatus(decimal) | Description - * ---------------------|----------------------- - * 0 | NO ERROR (Tracking success) - * 1 | Tx data path not enabled - * 2 | ORX data path is not enabled - * 3 | Loopback switch closed - * 4 | VSWR init cal was not run - * 5 | Path delay not setup - * 6 | Data measurement was aborted - * 7 | VSWR disabled - * 8 | If set, entered cal but not finished - * 9 | No GPIO configured in single ORx configuration - * 10 | Tx is not observable with any of the ORx Channels - * 11 | ORX_TRACKING_DISABLED ORx tracking must be enabled - * - */ - uint32_t errorStatus; - uint32_t trackCount; /*!< Number of times VSWR tracking has run since last reset */ - int32_t forwardGainRms_dB; /*!< Forward RMS gain measured from Tx to ORx path (1 = 0.01 dB Gain) */ - int32_t forwardGainReal; /*!< Real part of the forward path complex gain (1 = 0.01 linear Gain) */ - int32_t forwardGainImag; /*!< Imaginary part of the forward path complex gain (1 = 0.01 linear Gain) */ - int32_t reflectedGainRms_dB; /*!< Measured reflection path gain in RMS (1 = 0.01 dB Gain) */ - int32_t reflectedGainReal; /*!< Real part of the reflection path complex gain (1 = 0.01 linear Gain) */ - int32_t reflectedGainImag; /*!< Imaginary part of the reflection path complex gain (1 = 0.01 linear Gain) */ - int32_t vswr_forward_tx_rms; /*!< Forward RMS measured from Tx path (1 = 0.01 dBFS) */ - int32_t vswr_forward_orx_rms; /*!< Forward RMS measured from ORx path (1 = 0.01 dBFS) */ - int32_t vswr_reflection_tx_rms; /*!< Reflected RMS measured from Tx path (1 = 0.01 dBFS) */ - int32_t vswr_reflection_orx_rms; /*!< Reflected RMS measured from ORx path (1 = 0.01 dBFS) */ -} mykonosVswrStatus_t; - -/** - * \brief Data structure to hold Mykonos FIR filter settings - */ -typedef struct -{ - int8_t gain_dB; /*!< Filter gain in dB*/ - uint8_t numFirCoefs; /*!< Number of coefficients in the FIR filter */ - int16_t *coefs; /*!< A pointer to an array of filter coefficients */ -} mykonosFir_t; - -/** - * \brief Data structure to hold Mykonos JESD204b Framer configuration settings - */ -typedef struct -{ - uint8_t bankId; /*!< JESD204B Configuration Bank ID extension to Device ID. Range is 0..15 */ - uint8_t deviceId; /*!< JESD204B Configuration Device ID link identification number. Range is 0..255 */ - uint8_t lane0Id; /*!< JESD204B Configuration starting Lane ID. If more than one lane is used, each lane will increment from the Lane0 ID. Range is 0..31 */ - uint8_t M; /*!< Number of ADCs (0, 2, or 4) where 2 ADCs are required per receive chain (I and Q) */ - uint8_t K; /*!< Number of frames in a multiframe. Default = 32, F*K must be modulo 4. Where, F=2*M/numberOfLanes */ - uint8_t scramble; /*!< Scrambling off if framerScramble = 0, if framerScramble > 0 scrambling is enabled */ - uint8_t externalSysref; /*!< External SYSREF select. 0 = use internal SYSREF, 1 = use external SYSREF */ - uint8_t serializerLanesEnabled; /*!< Serializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ - uint8_t serializerLaneCrossbar; /*!< Lane crossbar to map framer lane outputs to physical lanes */ - uint8_t serializerAmplitude; /*!< Serializer amplitude setting. Default = 22. Range is 0..31 */ - uint8_t preEmphasis; /*!< Serializer pre-emphasis setting. Default = 4 Range is 0..7 */ - uint8_t invertLanePolarity; /*!< Lane inversion select. Default = 0. Where, bit[0] = 0 will invert lane [0], bit[1] = 0 will invert lane 1, etc. */ - uint8_t lmfcOffset; /*!< LMFC offset value for deterministic latency setting. Range is 0..31 */ - uint8_t newSysrefOnRelink; /*!< Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, 0 = not set */ - uint8_t enableAutoChanXbar; /*!< Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set */ - uint8_t obsRxSyncbSelect; /*!< Selects SYNCb input source. Where, 0 = use RXSYNCB for this framer, 1 = use OBSRX_SYNCB for this framer */ - uint8_t rxSyncbMode; /*!< Flag for determining if CMOS mode for RX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS */ - uint8_t overSample; /*!< Selects framer bit repeat or oversampling mode for lane rate matching. Where, 0 = bitRepeat mode (changes effective lanerate), 1 = overSample (maintains same lane rate between ObsRx framer and Rx framer and oversamples the ADC samples) */ - uint8_t enableManualLaneXbar; /*!< Flag for determining if API will calculate the appropriate settings for framer lane outputs to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in serializerLaneCrossbar will be used */ -} mykonosJesd204bFramerConfig_t; - -/* NO Doxygen content required for this data structure as this is used internally */ -/// @cond -typedef struct -{ - uint8_t DID; /*!< JESD204B Configuration Device ID for ILAS check */ - uint8_t BID; /*!< JESD204B Configuration Bank ID for ILAS check */ - uint8_t LID0; /*!< JESD204B Configuration starting Lane ID for ILAS check */ - uint8_t L; /*!< JESD204B Configuration L = lanes per data converter for ILAS check */ - uint8_t SCR; /*!< JESD204B Configuration scramble setting for ILAS check */ - uint8_t F; /*!< JESD204B Configuration F = octets per frame for ILAS check */ - uint8_t K; /*!< JESD204B Configuration K = frames per multiframe for ILAS check */ - uint8_t M; /*!< JESD204B Configuration M = number of data converters for ILAS check */ - uint8_t N; /*!< JESD204B Configuration N = data converter sample resolution for ILAS check */ - uint8_t CS; /*!< JESD204B Configuration CS = number of control bits transferred per sample per frame for ILAS check */ - uint8_t NP; /*!< JESD204B Configuration NP = JESD204B word size based on the highest resolution of the data converter for ILAS check */ - uint8_t S; /*!< JESD204B Configuration S = number of samples/data converter/frame for ILAS check */ - uint8_t CF; /*!< JESD204B Configuration CF = '0' = control bits appended to each sample, '1' = appended to end of frame for ILAS check */ - uint8_t HD; /*!< JESD204B Configuration HD = high density bit - samples are contained within lane (0) or divided over more than one lane (1) for ILAS check */ - uint8_t FCHK0; /*!< JESD204B Configuration checksum for ILAS check */ -} mykonosJesd204bLane0Config_t; -/// @endcond - -/** -* \brief Data structure to hold the settings for the deserializer and deframer configuration -* -* EQ Settings | 3GHz Loss (dB) |6GHz Loss (dB) | max FR408HR Length (in) | max FR4 Length (in) -*-------------|----------------|---------------|-------------------------|--------------------- -* 0 | 6.5 | 14 | 20 | 12 -* 1 | 11.5 | 21 | 30 | 20 -* 2 | 18 | 31 | 46 | 32 -* 3 | 21.5 | 38 | 56 | 40 -* 4 | 22 | 39 | 60 | 43 -*/ -typedef struct -{ - uint8_t bankId; /*!< Extension to Device ID. Range is 0..15 */ - uint8_t deviceId; /*!< Link identification number. Range is 0..255 */ - uint8_t lane0Id; /*!< Lane0 ID. Range is 0..31 */ - uint8_t M; /*!< Number of DACs (0, 2, or 4) - 2 DACs per transmit chain (I and Q) */ - uint8_t K; /*!< Number of frames in a multiframe. Default = 32, F*K = modulo 4. Where, F=2*M/numberOfLanes */ - uint8_t scramble; /*!< Scrambling off if scramble = 0, if framerScramble > 0 scrambling is enabled */ - uint8_t externalSysref; /*!< External SYSREF select. 0 = use internal SYSREF, 1 = external SYSREF */ - uint8_t deserializerLanesEnabled; /*!< Deserializer lane select bit field. Where, [0] = Lane0 enabled, [1] = Lane1 enabled, etc */ - uint8_t deserializerLaneCrossbar; /*!< Lane crossbar to map physical lanes to deframer lane inputs [1:0] = Deframer Input 0 Lane section, [3:2] = Deframer Input 1 lane select, etc */ - uint8_t EQSetting; /*!< Equalizer setting. Applied to all deserializer lanes. Range is 0..4 */ - uint8_t invertLanePolarity; /*!< PN inversion per each lane. bit[0] = 1 Invert PN of Lane 0, bit[1] = Invert PN of Lane 1, etc */ - uint8_t lmfcOffset; /*!< LMFC offset value to adjust deterministic latency. Range is 0..31 */ - uint8_t newSysrefOnRelink; /*!< Flag for determining if SYSREF on relink should be set. Where, if > 0 = set, '0' = not set */ - uint8_t enableAutoChanXbar; /*!< Flag for determining if auto channel select for the xbar should be set. Where, if > 0 = set, '0' = not set */ - uint8_t txSyncbMode; /*!< Flag for determining if CMOS mode for TX Sync signal is used. Where, if > 0 = CMOS, '0' = LVDS */ - uint8_t enableManualLaneXbar; /*!< Flag for determining if API will calculate the appropriate settings for deframer lane in to physical lanes. Where, if '0' = API will set automatic lane crossbar, '1' = set to manual mode and the value in deserializerLaneCrossbar will be used */ -} mykonosJesd204bDeframerConfig_t; - -/** - * \brief Data structure to hold settings for the current Rx specific use case profile - */ -typedef struct -{ - uint8_t adcDiv; /*!< The divider used to generate the ADC clock (Valid: 1,2) */ - mykonosFir_t *rxFir; /*!< Pointer to Rx FIR filter structure */ - uint8_t rxFirDecimation; /*!< Rx FIR decimation (1,2,4) */ - uint8_t rxDec5Decimation; /*!< Decimation of Dec5 or Dec4 filter (5,4) */ - uint8_t enHighRejDec5; /*!< If set, and DEC5 filter used, will use a higher rejection DEC5 FIR filter. Where, 1 = enabled, 0 = disabled */ - uint8_t rhb1Decimation; /*!< RX Halfband1 (HB1) decimation. Can be either 1 or 2 */ - uint32_t iqRate_kHz; /*!< Rx IQ data rate in kHz */ - uint32_t rfBandwidth_Hz; /*!< Rx RF passband bandwidth for the profile */ - uint32_t rxBbf3dBCorner_kHz; /*!< Rx BBF (TIA) 3dB corner in kHz */ - uint16_t *customAdcProfile; /*!< Custom ADC profile to set the bandwidth of the ADC response */ -} mykonosRxProfile_t; - -/** - * \brief Data structure to hold settings for the current Tx specific use case profile - */ -typedef struct -{ - mykonosDacDiv_t dacDiv; /*!< The divider used to generate the DAC clock (ENUM Values)*/ - mykonosFir_t *txFir; /*!< Pointer to Tx FIR filter structure */ - uint8_t txFirInterpolation; /*!< The TX digital FIR filter interpolation (1,2,4) */ - uint8_t thb1Interpolation; /*!< Tx Halfband1 (HB1) filter interpolation (1,2) */ - uint8_t thb2Interpolation; /*!< Tx Halfband2 (HB2) filter interpolation (1,2) */ - uint8_t txInputHbInterpolation; /*!< Interpolation of half band filter before the programmable FIR (valid 1,2,4) */ - uint32_t iqRate_kHz; /*!< Tx IQ data rate in kHz */ - uint32_t primarySigBandwidth_Hz; /*!< Tx primary signal BW */ - uint32_t rfBandwidth_Hz; /*!< Tx RF passband bandwidth for the profile */ - uint32_t txDac3dBCorner_kHz; /*!< DAC filter 3dB corner in kHz */ - uint32_t txBbf3dBCorner_kHz; /*!< Tx BBF 3dB corner in kHz */ - uint8_t enableDpdDataPath; /*!< Enable Tx Dynamic pre distortion - only valid for a DPD-enabled transceiver */ -} mykonosTxProfile_t; - -/** - * \brief Data structure to hold SnRx gain control settings for initialization and during use - */ -typedef struct -{ - mykonosGainMode_t gainMode; /*!< Current Sniffer gain control mode setting */ - uint8_t gainIndex; /*!< Current Sniffer gain index. Can be used differently for Manual Gain control/AGC */ - uint8_t maxGainIndex; /*!< Max gain index for the currently loaded Sniffer Gain table */ - uint8_t minGainIndex; /*!< Min gain index for the currently loaded Sniffer Gain table */ -} mykonosSnifferGainControl_t; - -/** - * \brief Data structure to hold ORx gain control settings for initialization and during use - */ -typedef struct -{ - mykonosGainMode_t gainMode; /*!< Current ORx gain control mode setting */ - uint8_t orx1GainIndex; /*!< ORx1 Gain Index, can be used in different ways for manual and AGC gain control */ - uint8_t orx2GainIndex; /*!< ORx2 Gain Index, can be used in different ways for manual and AGC gain control */ - uint8_t maxGainIndex; /*!< Max gain index for the currently loaded ORx Gain table */ - uint8_t minGainIndex; /*!< Min gain index for the currently loaded ORx Gain table */ -} mykonosORxGainControl_t; - -/** - * \brief Data structure to hold Rx gain control settings for initialization and during use - */ -typedef struct -{ - mykonosGainMode_t gainMode; /*!< Current Rx gain control mode setting */ - uint8_t rx1GainIndex; /*!< Rx1 Gain Index, can be used in different ways for manual and AGC gain control */ - uint8_t rx2GainIndex; /*!< Rx2 Gain Index, can be used in different ways for manual and AGC gain control */ - uint8_t rx1MaxGainIndex; /*!< Max gain index for the currently loaded Rx1 Gain table */ - uint8_t rx1MinGainIndex; /*!< Min gain index for the currently loaded Rx1 Gain table */ - uint8_t rx2MaxGainIndex; /*!< Max gain index for the currently loaded Rx2 Gain table */ - uint8_t rx2MinGainIndex; /*!< Min gain index for the currently loaded Rx2 Gain table */ - uint8_t rx1Rssi; /*!< Stores Rx1 RSSI value read back from the Mykonos */ - uint8_t rx2Rssi; /*!< Stores Rx2 RSSI value read back from the Mykonos */ -} mykonosRxGainControl_t; - -/** - * \brief Data structure to hold peak detector settings for the AGC - */ -typedef struct -{ - /* Threshold Settings */ - uint8_t apdHighThresh; /*!< APD high threshold. Must be greater than apdLowThresh. Min = apdLowThresh, Max = 0x3F. 6-bit field. */ - uint8_t apdLowThresh; /*!< APD low threshold. Must be less than apdHighThresh. Min = 0, Max = apdHighThresh. 6-bit field. */ - uint8_t hb2HighThresh; /*!< HB2 high threshold. Must be greater than hb2LowThresh. Min = hb2LowThresh, Max = 0xFF. 8-bit field. */ - uint8_t hb2LowThresh; /*!< HB2 low threshold. Must be less than hb2HighThresh. Min = 0, Max = hb2HighThresh. 8-bit field. */ - uint8_t hb2VeryLowThresh; /*!< HB2 very low threshold. Must be less than hb2LowThresh. Min = 0, Max = hb2LowThresh. 8-bit field. */ - - /* Threshold Counter Settings */ - uint8_t apdHighThreshExceededCnt; /*!< APD high threshold exceeded counter. Sets number of peaks to detect above apdHighThresh to cause gain decrement according to apdHighGainStepAttack. 8-bit field. */ - uint8_t apdLowThreshExceededCnt; /*!< APD low threshold exceeded counter. Sets number of peaks to detect below apdLowThresh to cause gain increment according to apdLowGainStepRecovery. 8-bit field. */ - uint8_t hb2HighThreshExceededCnt; /*!< HB2 high threshold exceeded counter. Sets number of overloads to detect above hb2HighThresh to cause gain decrement according to hb2HighGainStepAttack. 8-bit field. */ - uint8_t hb2LowThreshExceededCnt; /*!< HB2 low threshold exceeded counter. Sets number of peaks to detect below hb2LowThresh to cause gain increment according to hb2LowGainStepRecovery. 8-bit field. */ - uint8_t hb2VeryLowThreshExceededCnt; /*!< HB2 very low threshold exceeded counter. Sets number of peaks to detect below hb2VeryLowThresh to cause gain increment according to hb2VeryLowGainStepRecovery. 8-bit field. */ - - /* Gain Step Settings */ - uint8_t apdHighGainStepAttack; /*!< Number of gain indices to decrement gain when apdHighThreshExceededCnt is exceeded. 5-bit field. */ - uint8_t apdLowGainStepRecovery; /*!< Number of gain indices to increment gain when apdLowThreshExceededCnt is exceeded. 5-bit field */ - uint8_t hb2HighGainStepAttack; /*!< Number of gain indices to decrement gain when hb2HighThreshExceededCnt is exceeded. 5-bit field */ - uint8_t hb2LowGainStepRecovery; /*!< Number of gain indices to increment gain when hb2LowThreshExceededCnt is exceeded. 5-bit field*/ - uint8_t hb2VeryLowGainStepRecovery; /*!< Number of gain indices to increment gain when hb2VeryLowThreshExceededCnt is exceeded. 5-bit field */ - - /* Fast Attack Settings */ - uint8_t apdFastAttack; /*!< [1] Enables APD fast attack mode - gain decrements immediately when apdHighThreshExceededCnt is exceeded. [0] disables APD fast attack mode - gain decrements at the expiry of agcGainUpdateCounter. 1-bit field. */ - uint8_t hb2FastAttack; /*!< [1] Enables HB2 fast attack mode - gain decrements immediately when hb2HighThreshExceededCnt is exceeded. [0] disables HB2 fast attack mode - gain decrements at the expiry of agcGainUpdateCounter. 1-bit field. */ - - /* HB2 Configuration Settings */ - uint8_t hb2OverloadDetectEnable; /*!< [1] Enables the HB2 overload detector. [0] Disables the HB2 overload detector. 1-bit field. */ - uint8_t hb2OverloadDurationCnt; /*!< Sets the samples size window of the HB2 overload detector. If hb2OverloadThreshCnt number of overloads are detected, the hb2xxxThreshExceededCnt increments. 3-bit field. [001]=1, [001]=4, [010]=8, [011]=12, [100]=16, [101]=24, [110]=32, [111]=INVALID */ - uint8_t hb2OverloadThreshCnt; /*!< Sets the number of individual overloads necessary within hb2OverloadDurationCnt samples to increment the hb2xxxThreshExceededCnt */ -} mykonosPeakDetAgcCfg_t; - -/** - * \brief Data structure to hold power measurement settings for the AGC - */ -typedef struct -{ - /* Threshold Settings */ - uint8_t pmdUpperHighThresh; /*!< Power measurement upper band, high threshold . This value is a positive offset to the pmdUpperLowThresh threshold. 4-bit field */ - uint8_t pmdUpperLowThresh; /*!< Power measurement upper band, low threshold. This value sets the threshold in (negative) -dBFS. Byte value must be less than pmdLowerHighThresh. 7-bit field */ - uint8_t pmdLowerHighThresh; /*!< Power measurement lower band, high threshold. This value sets the threshold in (negative) -dBFS. Byte value must be greater than pmdUpperLowThresh. 7-bit field */ - uint8_t pmdLowerLowThresh; /*!< Power measurement lower band, low threshold. This value is a negative offset to the pmdLowerHighThresh threshold. 4-bit field */ - - /* Gain Step Settings */ - uint8_t pmdUpperHighGainStepAttack; /*!< Number of gain indices to decrement gain if pmdUpperHighThresh is exceeded by the end of the agcGainUpdateCounter. 5-bit field */ - uint8_t pmdUpperLowGainStepAttack; /*!< Number of gain indices to decrement gain if pmdUpperLowThresh is exceeded by the end of the agcGainUpdateCounter. 5-bit field */ - uint8_t pmdLowerHighGainStepRecovery; /*!< Number of gain indices to increment gain if pmdLowerHighThresh is not exceeded by the end of the agcGainUpdateCounter. 5-bit field */ - uint8_t pmdLowerLowGainStepRecovery; /*!< Number of gain indices to increment gain if pmdLowerLowThresh is not exceeded by the end of the agcGainUpdateCounter. 5-bit field */ - - /* PMD Configuration Settings */ - uint8_t pmdMeasDuration; /*!< Number of samples to measure power on. The number of samples corresponding to the 4-bit word is 8*2^(pmdMeasDuration[3:0]). This value must be less than agcGainUpdateCounter */ - uint8_t pmdMeasConfig; /*!< Power measurement configuration. 2-bit field. [00]=PMD disabled, [01]=PMD Enabled at HB2 output, [10]=Enabled at RFIR output (recommended), [11]=PMD Enabled at BBDC2 */ -} mykonosPowerMeasAgcCfg_t; - -/** - * \brief Data structure to hold general AGC settings for initialization and during use - */ -typedef struct -{ - /* Gain Table Settings */ - uint8_t agcRx1MaxGainIndex; /*!< Maximum Rx1 gain index allowed in AGC mode. Must be greater than agcRx1MinGainIndex and valid gain index. 8-bit field */ - uint8_t agcRx1MinGainIndex; /*!< Minimum Rx1 gain index allowed in AGC mode. Must be less than agcRx1MinGainIndex and valid gain index. 8-bit field */ - uint8_t agcRx2MaxGainIndex; /*!< Maximum Rx2 gain index allowed in AGC mode. Must be greater than agcRx2MinGainIndex and valid gain index. 8-bit field */ - uint8_t agcRx2MinGainIndex; /*!< Minimum Rx2 gain index allowed in AGC mode. Must be less than agcRx2MinGainIndex and valid gain index. 8-bit field */ - uint8_t agcObsRxMaxGainIndex; /*!< Maximum ObsRx gain index allowed in AGC mode. Must be greater than agcObsRxMinGainIndex and valid gain index. 8-bit field */ - uint8_t agcObsRxMinGainIndex; /*!< Minimum ObsRx gain index allowed in AGC mode. Must be less than agcObsRxMaxGainIndex and valid gain index. 8-bit field */ - uint8_t agcObsRxSelect; /*!< Sniffer or ObsRx AGC channel select. [1] = SnRx */ - - /* AGC Mode Selection */ - uint8_t agcPeakThresholdMode; /*!< [1] = Peak Threshold Mode, power based gain changes are disabled. [0] = Peak and overload detectors are ignored for gain changes */ - uint8_t agcLowThsPreventGainIncrease; /*!< [1] PMD based gain increments are ignored if apd/hb2LowThreshExceedCnt is high [0] apdLowThreshExceededCnt and hb2LowThreshExceededCnt are "Don't cares" to the AGC gain recovery */ - - /* AGC General Settings */ - uint32_t agcGainUpdateCounter; /*!< Number of samples for the AGC gain update counter. Counter operates on the IQ data rate. 22-bit field. Min = 0x000001, Max = 0x3FFFFF */ - uint8_t agcSlowLoopSettlingDelay; /*!< Number of IQ data rate clock cycles to wait after a gain change before peak/power measurements resume. 7-bit field */ - uint8_t agcPeakWaitTime; /*!< Number of IQ data rate clock cycles to wait to enable peak/overload detectors after AGC is enabled. 5-bit field. Min = 0x02. Max = 0x1F */ - uint8_t agcResetOnRxEnable; /*!< [1] = Performs a reset of the AGC slow loop state machine when Rx is disabled. [0] = AGC slow loop state machine maintains its state when Rx is disabled. */ - uint8_t agcEnableSyncPulseForGainCounter; /*!< [1] = Allows sync of agcGainUpdateCounter to the time-slot boundary. GPIO setup required. [0] = agcGainUpdateCounter functions as normal */ - - mykonosPeakDetAgcCfg_t *peakAgc; /*!< pointer to structure for Peak AGC */ - mykonosPowerMeasAgcCfg_t *powerAgc; /*!< pointer to structure for Power AGC */ -} mykonosAgcCfg_t; - -/** - * \brief Data structure to hold Tx data path settings - */ -typedef struct -{ - mykonosTxProfile_t *txProfile; /*!< Tx datapath profile, 3dB corner frequencies, and digital filter enables */ - mykonosJesd204bDeframerConfig_t *deframer; /*!< Mykonos JESD204b deframer config for the Tx data path */ - mykonosTxChannels_t txChannels; /*!< The desired Tx channels to enable during initialization */ - uint8_t txPllUseExternalLo; /*!< Internal LO=0, external LO*2 if =1 */ - uint64_t txPllLoFrequency_Hz; /*!< Tx PLL LO frequency (internal or external LO) */ - mykonosTxAttenStepSize_t txAttenStepSize; /*!< Tx Attenuation step size */ - uint16_t tx1Atten_mdB; /*!< Initial and current Tx1 Attenuation */ - uint16_t tx2Atten_mdB; /*!< Initial and current Tx2 Attenuation */ - mykonosDpdConfig_t *dpdConfig; /*!< DPD settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ - mykonosClgcConfig_t *clgcConfig; /*!< CLGC settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ - mykonosVswrConfig_t *vswrConfig; /*!< VSWR settings. Only valid for a DPD-enabled transceiver, set pointer to NULL otherwise */ -} mykonosTxSettings_t; - -/** - * \brief Data structure to hold Rx data path settings - */ -typedef struct -{ - mykonosRxProfile_t *rxProfile; /*!< Rx datapath profile, 3dB corner frequencies, and digital filter enables */ - mykonosJesd204bFramerConfig_t *framer; /*!< Rx JESD204b framer configuration structure */ - mykonosRxGainControl_t *rxGainCtrl; /*!< Rx Gain control settings structure */ - mykonosAgcCfg_t *rxAgcCtrl; /*!< Rx AGC control settings structure */ - mykonosRxChannels_t rxChannels; /*!< The desired Rx Channels to enable during initialization */ - uint8_t rxPllUseExternalLo; /*!< Internal LO = 0, external LO*2 = 1 */ - uint64_t rxPllLoFrequency_Hz; /*!< Rx PLL LO Frequency (internal or external LO) */ - uint8_t realIfData; /*!< Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where, if > 0 = real IF data, '0' = zero IF (IQ) data*/ -} mykonosRxSettings_t; - -/** - * \brief Data structure to hold ORx data path settings - */ -typedef struct -{ - mykonosRxProfile_t *orxProfile; /*!< ORx datapath profile, 3dB corner frequencies, and digital filter enables. */ - mykonosORxGainControl_t *orxGainCtrl; /*!< ObsRx gain control settings structure */ - mykonosAgcCfg_t *orxAgcCtrl; /*!< ORx AGC control settings structure */ - mykonosRxProfile_t *snifferProfile; /*!< Sniffer datapath profile, 3dB corner frequencies, and digital filter enables. */ - mykonosSnifferGainControl_t *snifferGainCtrl; /*!< SnRx gain control settings structure */ - mykonosJesd204bFramerConfig_t *framer; /*!< ObsRx JESD204b framer configuration structure */ - mykonosObsRxChannelsEn_t obsRxChannelsEnable; /*!< The desired ObsRx channels to configure/calibrate during initialization */ - mykonosObsRxLoSource_t obsRxLoSource; /*!< The sniffer/ORx mixers can use the TX_PLL or SNIFFER_PLL */ - uint64_t snifferPllLoFrequency_Hz; /*!< SnRx PLL LO frequency in Hz */ - uint8_t realIfData; /*!< Flag to choose if complex baseband or real IF data are selected for Rx and ObsRx paths. Where if > 0 = real IF data, '0' = complex data */ - uint16_t *customLoopbackAdcProfile; /*!< Custom Loopback ADC profile to set the bandwidth of the ADC response */ - mykonosObsRxChannels_t defaultObsRxChannel; /*!< Default ObsRx channel to enter when radioOn called */ -} mykonosObsRxSettings_t; - - -/** - * \brief Data structure to hold ARM GPIO pin assignments for each ARM input/output pin. - */ -typedef struct -{ - uint8_t useRx2EnablePin; /*!< 0= RX1_ENABLE controls RX1 and RX2, 1 = separate RX1_ENABLE/RX2_ENABLE pins */ - uint8_t useTx2EnablePin; /*!< 0= TX1_ENABLE controls TX1 and TX2, 1 = separate TX1_ENABLE/TX2_ENABLE pins */ - uint8_t txRxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up Tx/Rx chains */ - uint8_t orxPinMode; /*!< 0= ARM command mode, 1 = Pin mode to power up ObsRx receiver*/ - - /* Mykonos ARM input GPIO pins -- Only valid if orxPinMode = 1 */ - uint8_t orxTriggerPin; /*!< Select desired GPIO pin (valid 4-15) */ - uint8_t orxMode2Pin; /*!< Select desired GPIO pin (valid 0-18) */ - uint8_t orxMode1Pin; /*!< Select desired GPIO pin (valid 0-18) */ - uint8_t orxMode0Pin; /*!< Select desired GPIO pin (valid 0-18) */ - - /* Mykonos ARM output GPIO pins -- always available, even when pin mode not enabled*/ - uint8_t rx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t rx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t tx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t tx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t orx1EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t orx2EnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t srxEnableAck; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - uint8_t txObsSelect; /*!< Select desired GPIO pin (0-15), [4] = Output Enable */ - /* When 2Tx are used with only 1 ORx input, this GPIO tells the BBIC which Tx channel is */ - /* active for calibrations, so BBIC can route correct RF Tx path into the single ORx input */ -} mykonosArmGpioConfig_t; - -/** - * \brief Data structure to hold auxiliary IO settings (AuxDAC, ARM GPIO, GPIO3.3v, low voltage GPIO, HSCP, etc) - */ -typedef struct -{ - uint16_t auxDacEnable; /*!< Aux DAC enable. One bit per Aux DAC. Where bit[0] = Aux DAC 0, bit[1] = Aux DAC 1, etc */ - uint16_t auxDacValue[10]; /*!< Aux DAC value */ - uint8_t auxDacSlope[10]; /*!< Aux DAC slope */ - uint8_t auxDacVref[10]; /*!< Aux DAC voltage reference value */ - - mykonosGpio3v3_t *gpio3v3; /*!< GPIO 3.3 VDC settings data structure pointer */ - mykonosGpioLowVoltage_t *gpio; /*!< Low voltage GPIO settings data structure pointer */ - mykonosArmGpioConfig_t *armGpio; /*!< Mykonos ARM GPIO settings*/ -} mykonosAuxIo_t; - -/** - * \brief Data structure to hold digital clock settings - */ -typedef struct -{ - uint32_t deviceClock_kHz; /*!< CLKPLL and device reference clock frequency in kHz */ - uint32_t clkPllVcoFreq_kHz; /*!< CLKPLL VCO frequency in kHz */ - mykonosVcoDiv_t clkPllVcoDiv; /*!< CLKPLL VCO divider */ - uint8_t clkPllHsDiv; /*!< CLKPLL high speed clock divider */ -} mykonosDigClocks_t; - - -/** - * \brief Data structure used to read back the Init Calibration Status - */ -typedef struct -{ - uint32_t calsDoneLastRun; /*!< Init cals that completed in the last call to MYKONOS_runInitCals() */ - uint32_t calsDoneLifetime; /*!< Init cals that have completed successfully since loading of the ARM processor */ - uint32_t calsMinimum; /*!< Minimum set of init cals that must complete before device can move to radioOn state */ - uint8_t initErrCal; /*!< If an init cal had an error, this represents the opcode of the init cal that reported an error */ - uint8_t initErrCode; /*!< If an init cal had an error, this represents the ARM error code describing the failure */ -} mykonosInitCalStatus_t; - -/** - * \brief Data structure used to read back DPD calibration status - */ -typedef struct -{ - /** - * dpdErrorStatus (decimal) | Description - * --------------------------|----------------------- - * 0 | No Error - * 1 | ORX_DISABLED - * 2 | TX_DISABLED - * 3 | PATHDELAY_NOT_SETUP - * 4 | DPD_INIT_NOT_RUN - * 5 | ORX_SIG_TOO_LOW - * 6 | ORX_SIG_SATURATED - * 7 | TX_SIG_TOO_LOW - * 8 | TX_SIG_SATURATED - * 9 | MODEL_ERROR_HIGH - * 10 | AM_AM_OUTLIERS - * 11 | INVALID_TX_PROFILE - * 12 | ORX_TRACKING_DISABLED ORx tracking must be enabled - * 13 | Cal suspended - * 14 | Reserved - * 15 | Reserved - * 16 | Reserved - * 17 | Reserved - * 18 | Reserved - */ - uint32_t dpdErrorStatus; - uint32_t dpdTrackCount; /*!< Number of times DPD tracking has run since last reset */ - uint32_t dpdModelErrorPercent; /*!< Percent Error of PA model * 10 to include 1 decimal place */ - uint32_t dpdExtPathDelay; /*!< External path delay from Tx output to ORx input, at 1/16 sample resolution of ORx sample rate */ - uint16_t dpdMaxAdaptationCurrent; /*!< max amplitude of current adaptation */ - uint16_t dpdMaxAdaptation; /*!< max amplitude of adaptation since DPD started*/ - uint32_t dpdIterCount; /*!< number of times DPD tracking has run since last reset*/ -} mykonosDpdStatus_t; - -/** - * \brief Data structure used to read back CLGC calibration status - */ -typedef struct -{ - /** - * clgcErrorStatus(decimal) | Description - * -------------------------|----------------------- - * 0 | NO ERROR - * 1 | TX Disabled - * 2 | ORx is disabled - * 3 | Loopback switch is clo - * 4 | Data measurement aborted during capture - * 5 | No initial calibration was done - * 6 | Path delay not setup - * 7 | No apply control is possible - * 8 | Control value is out of range - * 9 | CLGC feature is disabled - * 10 | TX attenuation is capped - * 11 | Gain measurement - * 12 | No GPIO configured in single ORx configuration - * 13 | Tx is not observable with any of the ORx Channels - * 14 | ORX_TRACKING_DISABLED ORx tracking must be enabled - * 15 | PA Protection Activated - * 16 | Relative Threshold Violated - * 17 | RESERVED - * 18 | Tx power too low - * 19 | ORx power too low - */ - uint32_t errorStatus; - uint32_t trackCount; /*!< Number of times CLGC tracking has run since last reset */ - int32_t desiredGain; /*!< Desired gain/attenuation from Tx output to ORx input of Mykonos device. 0.01 dB resolution */ - int32_t currentGain; /*!< Current measured gain in 0.01 dB resolution. */ - uint32_t txGain; /*!< Current TxAttenuation setting, same as MYKONOS_getTx1/2Attenuation(), in 0.05dB resolution */ - int32_t txRms; /*!< Tx digital sample power measured at DPD block input (0.01 dB resolution) */ - int32_t orxRms; /*!< ORx digital sample power measured at ORx port (0.01 dB resolution) */ -} mykonosClgcStatus_t; - -/** - * \brief Data structure to hold Tx LOL Status - */ -typedef struct -{ - uint32_t errorCode; /*!< error code from Tx LOL */ - uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ - uint32_t performanceMetric; /*!< Variance of the corrections, and gives an indication in dB on how much LO leakage is corrected on an average tracking pass. */ - uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ - uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ -} mykonosTxLolStatus_t; - -/** - * \brief This structure contains the internal path delay - * - */ -typedef struct -{ - uint32_t forwardPathDelayCh1; /*!< Forward path delay for Channel 1 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ - uint32_t reversePathDelayCh1; /*!< Reverse path delay for Channel 1 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ - uint32_t forwardPathDelayCh2; /*!< Forward path delay for Channel 2 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ - uint32_t reversePathDelayCh2; /*!< Reverse path delay for Channel 2 valid range is from 0 to 4095 at 1/16 sample resolution of ORx sample rate */ -} mykonosPathdelay_t; - -/** - * \brief This structure contains the DPD error status counters for the different errors - * - */ -typedef struct -{ - uint32_t dpdErrorCount; /*!< DPD total error count */ - uint32_t errorCounter[MYK_DPD_ERROR_END]; /*!< array for individual error counters corresponding to ::mykonosDpdErrors_t */ -} mykonosDpdErrorCounters_t; - -/** - * \brief Data structure to hold Tx QEC Status - */ -typedef struct -{ - uint32_t errorCode; /*!< error code from Tx QEC */ - uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ - uint32_t performanceMetric; /*!< Number of codes adjusted which is the number of codes of correction made last time which can be converted to an IRR power metric as with Rx QEC, if desired. */ - uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ - uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ -} mykonosTxQecStatus_t; - -/** - * \brief Data structure to hold Rx QEC Status - */ -typedef struct -{ - uint32_t errorCode; /*!< error code from Rx QEC */ - uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ - uint32_t selfcheckIrrDb; /*!< selfCheckIrrdDb - Power-weighted average Image Rejection Ratio (IRR) in dBc. */ - uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ - uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ -} mykonosRxQecStatus_t; - -/** - * \brief Data structure to hold Orx QEC Status - */ -typedef struct -{ - uint32_t errorCode; /*!< error code from Orx QEC */ - uint32_t percentComplete; /*!< percent of required data collected for the current cal. Range 0 to 100 */ - uint32_t selfcheckIrrDb; /*!< selfCheckIrrdDb - Power-weighted average Image Rejection Ratio (IRR) in dBc. */ - uint32_t iterCount; /*!< running counter that increments each time the cal runs to completion */ - uint32_t updateCount; /*!< running counter that increments each time the cal updates the correction/actuator hardware */ -} mykonosOrxQecStatus_t; - -/** - * \brief Data structure to hold Mykonos device settings - */ -typedef struct -{ - spiSettings_t *spiSettings; /*!< SPI settings data structure pointer */ - mykonosRxSettings_t *rx; /*!< Rx settings data structure pointer */ - mykonosTxSettings_t *tx; /*!< Tx settings data structure pointer */ - mykonosObsRxSettings_t *obsRx; /*!< ObsRx settings data structure pointer */ - mykonosAuxIo_t *auxIo; /*!< Auxiliary IO settings data structure pointer */ - mykonosDigClocks_t *clocks; /*!< Holds settings for CLKPLL and reference clock */ - uint8_t profilesValid; /*!< Mykonos initialize function uses this as an output to remember which profile data structure pointers are valid */ -} mykonosDevice_t; - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/df_datalink_ge/src/hardware/mykonos/t_mykonos_gpio.h b/df_datalink_ge/src/hardware/mykonos/t_mykonos_gpio.h deleted file mode 100644 index 71f2cf9..0000000 --- a/df_datalink_ge/src/hardware/mykonos/t_mykonos_gpio.h +++ /dev/null @@ -1,375 +0,0 @@ -/*! - * \file t_mykonos_gpio.h - * \brief Mykonos GPIO error handling and type defines - * - * Mykonos API version: 1.5.2.3566 - */ - -/** -* \page Disclaimer Legal Disclaimer -* Copyright 2015-2017 Analog Devices Inc. -* Released under the AD9371 API license, for more information see the "LICENSE.txt" file in this zip file. -* -*/ - -#ifndef T_MYKONOSGPIO_H_ -#define T_MYKONOSGPIO_H_ - -#ifdef __cplusplus -extern "C" { -#endif - - -#include "../common.h" - -/** - * \brief Enum of unique error codes from the Mykonos GPIO API functions. - * Each error condition in the library should get its own enum value to allow - * easy debug of errors. - */ -typedef enum -{ - MYKONOS_ERR_GPIO_OK = 0, - MYKONOS_ERR_EN_MONITOR_OUT_NOT_ENABLED, - MYKONOS_ERR_EN_MONITOR_OUT_SRC_CTRL, - MYKONOS_ERR_MONITOR_OUT_INDEX_RANGE, - MYKONOS_ERR_GETGPIOMON_INDEX_NULL_PARM, - MYKONOS_ERR_GETGPIOMON_MONITORMASK_NULL_PARM, - - MYKONOS_ERR_MGCRX2_GPIO_DECPIN_INV_PARAM, - MYKONOS_ERR_MGCRX2_GPIO_INCPIN_INV_PARAM, - MYKONOS_ERR_MGCRX2_SOURCE_CONFIG, - MYKONOS_ERR_MGCRX2_STEP_INV_PARAM, - MYKONOS_ERR_MGCRX1_GPIO_DECPIN_INV_PARAM, - MYKONOS_ERR_MGCRX1_GPIO_INCPIN_INV_PARAM, - MYKONOS_ERR_MGCRX1_STEP_INV_PARAM, - MYKONOS_ERR_GETRX2PIN_INCSTEP_NULL_PARM, - MYKONOS_ERR_GETRX2PIN_DECSTEP_NULL_PARM, - MYKONOS_ERR_GETRX2PIN_INCPIN_NULL_PARM, - MYKONOS_ERR_GETRX2PIN_DECPIN_NULL_PARM, - MYKONOS_ERR_GETRX2PIN_EN_NULL_PARM, - MYKONOS_ERR_GETRX1PIN_INCSTEP_NULL_PARM, - MYKONOS_ERR_GETRX1PIN_DECSTEP_NULL_PARM, - MYKONOS_ERR_GETRX1PIN_INCPIN_NULL_PARM, - MYKONOS_ERR_GETRX1PIN_DECPIN_NULL_PARM, - MYKONOS_ERR_GETRX1PIN_EN_NULL_PARM, - - MYKONOS_ERR_TPCTX2_GPIO_DECPIN_INV_PARAM, - MYKONOS_ERR_TPCTX2_GPIO_INCPIN_INV_PARAM, - MYKONOS_ERR_TPCTX2_GPIO_STEP_INV_PARAM, - MYKONOS_ERR_TPCTX1_GPIO_DECPIN_INV_PARAM, - MYKONOS_ERR_TPCTX1_GPIO_INCPIN_INV_PARAM, - MYKONOS_ERR_TPCTX1_GPIO_STEP_INV_PARAM, - MYKONOS_ERR_GETTX2PIN_STEP_NULL_PARM, - MYKONOS_ERR_GETTX2PIN_INC_NULL_PARM, - MYKONOS_ERR_GETTX2PIN_DEC_NULL_PARM, - MYKONOS_ERR_GETTX2PIN_EN_NULL_PARM, - MYKONOS_ERR_GETTX2PIN_TX1TX2_NULL_PARM, - MYKONOS_ERR_GETTX1PIN_STEP_NULL_PARM, - MYKONOS_ERR_GETTX1PIN_INC_NULL_PARM, - MYKONOS_ERR_GETTX1PIN_DEC_NULL_PARM, - MYKONOS_ERR_GETTX1PIN_EN_NULL_PARM, - MYKONOS_ERR_GETTX1PIN_TX1TX2_NULL_PARM, - - MYKONOS_ERR_SPI2_INV_GPIO, - MYKONOS_ERR_SPI2_INV_SETUP, - - MYKONOS_ERR_SET_GPIO_1V8_INV_POINTER, - - MYKONOS_ERR_GETGPIOSETLEVEL_NULL_PARM, - MYKONOS_ERR_READGPIOSPI_NULL_PARM, - MYKONOS_ERR_SET_GPIO_1V8_INV_MODE, - MYKONOS_ERR_GETGPIO_OE_NULL_PARM, - MYKONOS_ERR_GPIO_OE_INV_PARAM, - MYKONOS_ERR_GPIO_SRC_PARAM_INV, - MYKONOS_ERR_GET_GPIO_SOURCE_CONTROL_NULL_PARM, - - MYKONOS_ERR_INV_GP_INT_MASK_PARM, - MYKONOS_ERR_GP_INT_STATUS_NULL_PARAM, - - MYKONOS_ERR_GETGPIO3V3OUT_NULL_PARM, - MYKONOS_ERR_SET_GPIO_3V3_INV_POINTER, - MYKONOS_ERR_GETGPIO3V3SPI_NULL_PARM, - MYKONOS_ERR_GPIO3V3OUTEN_NULL_PARM, - MYKONOS_ERR_SET_GPIO_3V3_INV_MODE, - MYKONOS_ERR_SET_GPIO_3V3_INV_SRC_CTRL, - - MYKONOS_ERR_SET_ARMGPIO_INV_POINTER, - MYKONOS_ERR_SET_ARMGPIO_PINS_ARMERROR, - MYKONOS_ERR_SET_ARMGPIO_PINS_INV_SIGNALID, - MYKONOS_ERR_SET_ARMGPIO_PINS_INV_GPIOPIN, - - MYKONOS_ERR_SETUPAUXDAC_NULL_PARAM, - MYKONOS_ERR_WRITEAUXDAC_NULL_AUXIO, - MYKONOS_ERR_READAUXADC_NULL_PARAM, - MYKONOS_ERR_SETUPAUXDAC_INV_AUXDACCODE, - MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACCODE, - MYKONOS_ERR_WRITEAUXDAC_INV_AUXDACINDEX, - MYKONOS_ERR_INV_AUX_ADC_CHAN_PARM, - MYKONOS_ERR_SETUPAUXADC_INV_VCODIV, - MYKONOS_ERR_INV_AUX_ADC_DEC_PARM, - - MYKONOS_ERR_GAINCOMP_NULL_STRUCT, - MYKONOS_ERR_GAINCOMP_EN_NULL_PARM, - MYKONOS_ERR_GAINCOMP_SET_NULL_STRUCT, - MYKONOS_ERR_GAINCOMP_INV_RX1_OFFSET, - MYKONOS_ERR_GAINCOMP_INV_RX2_OFFSET, - MYKONOS_ERR_GAINCOMP_INV_STEP, - MYKONOS_ERR_GAINCOMP_INV_EN, - - MYKONOS_ERR_OBS_RX_GAINCOMP_SET_NULL_STRUCT, - MYKONOS_ERR_OBS_RX_GAINCOMP_EN_NULL_PARAM, - MYKONOS_ERR_OBS_RX_GAINCOMP_INV_EN, - MYKONOS_ERR_OBS_RX_GAINCOMP_INV_OFFSET, - MYKONOS_ERR_OBS_RX_GAINCOMP_INV_STEP, - MYKONOS_ERR_OBS_RX_GAINCOMP_NULL_STRUCT, - - MYKONOS_ERR_SLICER_STEP_OUT_OF_RANGE, - MYKONOS_ERR_SLICER_INV_RX1_SEL, - MYKONOS_ERR_SLICER_INV_RX2_SEL, - MYKONOS_ERR_SLICER_EN_INV, - - MYKONOS_ERR_SLICER_RX1PIN_NULL_PARM, - MYKONOS_ERR_SLICER_RX2PIN_NULL_PARM, - MYKONOS_ERR_SLICER_STEP_NULL_PARM, - MYKONOS_ERR_SLICER_EN_NULL_PARM, - - MYKONOS_ERR_SLICER_INV_OBS_RX_SEL, - MYKONOS_ERR_SLICER_OBS_RX_STEP_OUT_OF_RANGE, - MYKONOS_ERR_SLICER_OBS_RX_EN_INV, - MYKONOS_ERR_SLICER_OBS_RX_EN_NULL_PARM, - MYKONOS_ERR_SLICER_OBS_RX_STEP_NULL_PARM, - MYKONOS_ERR_SLICER_OBS_RXPIN_NULL_PARM, - - MYKONOS_ERR_FLOATFRMT_NULL_STRUCT, - MYKONOS_ERR_FLOATFRMT_SET_NULL_STRUCT, - MYKONOS_ERR_FLOATFRMT_INV_ROUND_MODE, - MYKONOS_ERR_FLOATFRMT_INV_DATA_FORMAT, - MYKONOS_ERR_FLOATFRMT_INV_ENC_NAN, - MYKONOS_ERR_FLOATFRMT_INV_EXP_BITS, - MYKONOS_ERR_FLOATFRMT_INV_LEADING, - MYKONOS_ERR_FLOATFRMT_INV_RX1ATT, - MYKONOS_ERR_FLOATFRMT_INV_RX2ATT, - MYKONOS_ERR_FLOATFRMT_INV_EN, - MYKONOS_ERR_FLOATFRMT_NULL_RX1ATT, - MYKONOS_ERR_FLOATFRMT_NULL_RX2ATT, - MYKONOS_ERR_FLOATFRMT_NULL_ENABLE, - MYKONOS_ERR_FLOATFRMT_SET_INV_EN, - MYKONOS_ERR_FLOATFRMT_SET_INV_RX1ATT, - MYKONOS_ERR_FLOATFRMT_SET_INV_RX2ATT, - - MYKONOS_ERR_FLOATFRMT_INV_ORXATT, - MYKONOS_ERR_FLOATFRMT_INV_ORXEN, - MYKONOS_ERR_FLOATFRMT_NULL_ORXATT, - MYKONOS_ERR_FLOATFRMT_NULL_ORXENABLE, - - MYKONOS_ERR_SETUPTEMPSENSOR_NULL_PARAM, - MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPDECIMATION, - MYKONOS_ERR_SETUPTEMPSENSOR_INV_OFFSET, - MYKONOS_ERR_SETUPTEMPSENSOR_INV_TEMPWINDOW, - MYKONOS_ERR_GETTEMPSENSORCFG_NULL_PARAM, - MYKONOS_ERR_READTEMPSENSOR_NULL_PARAM, - MYKONOS_ERR_READTEMPSENSOR_NOT_LOCKED, - - MYKONOS_ERR_GAIN_CONTROL_NOT_HYBRID, - MYKONOS_ERR_GPIO_HYBRID_RX1_PIN, - MYKONOS_ERR_GPIO_HYBRID_RX2_PIN, - MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_NULL_PARM, - MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_NULL_PARM, - MYKONOS_ERR_GPIO_HYBRID_RX1_PIN_READ, - MYKONOS_ERR_GPIO_HYBRID_RX2_PIN_READ, - MYKONOS_ERR_AGC_OBS_NOT_IN_HYBRID, - MYKONOS_ERR_GPIO_HYBRID_ORX_PIN, - MYKONOS_ERR_GPIO_HYBRID_ORX_PIN_NULL_PARM, - - MYKONOS_ERR_GAIN_CONTROL_NOT_AGC, - MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN, - MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN, - MYKONOS_ERR_GPIO_AGC_SYNC_RX1_PIN_NULL_PARM, - MYKONOS_ERR_GPIO_AGC_SYNC_RX2_PIN_NULL_PARM, - MYKONOS_ERR_OBS_GAIN_CONTROL_NOT_AGC, - MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN, - MYKONOS_ERR_GPIO_AGC_SYNC_ORX_PIN_NULL_PARM, - - MYKONOS_ERR_GETGPIODRV_NULL_PARAM, - MYKONOS_ERR_GPIO_DRV_INV_PARAM, - - MYKONOS_ERR_GPIO_SLEW_RATE_INV_PARAM, - MYKONOS_ERR_GPIO_GETSLEW_NULL_PARAM, - - MYKONOS_ERR_CMOS_DRV_INV_PARAM, - MYKONOS_ERR_CMOS_DRV_NULL_PARAM -} mykonosGpioErr_t; - -/** - * \brief Enum of possible Rx Slicer pin combinations - */ -typedef enum -{ - GPIO_0_1_2 = 0, /*!< GPIO combination for RX1 */ - GPIO_5_6_7 = 1, /*!< GPIO combination for RX1 or RX2 */ - GPIO_8_9_10 = 2, /*!< GPIO combination for RX1 */ - GPIO_11_12_13 = 3 /*!< GPIO combination for RX2 */ -} mykonosRxSlicer_t; - -/** - * \brief Enum of possible observation channel Slicer pin combinations - */ -typedef enum -{ - GPIO_18_17_16 = 0, /*!< GPIO combination for observation channel */ - GPIO_16_15_14 = 1 /*!< GPIO combination for observation channel */ -} mykonosObsRxSlicer_t; - -/** - * \brief Enum of possible GPIO slew rate settings - */ -typedef enum -{ - MYK_SLEWRATE_NONE = 0, /*!< Lower slew rate for the GPIO */ - MYK_SLEWRATE_LOW = 1, /*!< Low slew rate for the GPIO */ - MYK_SLEWRATE_MEDIUM = 2, /*!< Medium slew rate for the GPIO */ - MYK_SLEWRATE_HIGH = 3 /*!< High slew rate for the GPIO */ -} mykonosGpioSlewRate_t; - -/** - * \brief Enumerated list of CMOS pads drive strength options - */ -typedef enum -{ - MYK_CMOSPAD_DRV_1X = 0x00, /*!< 2.5pF load @ 65MHz */ - MYK_CMOSPAD_DRV_2X = 0x01, /*!< 5pF load @ 65MHz */ - MYK_CMOSPAD_DRV_3X = 0x03, /*!< 7.5pF load @ 65MHz */ - MYK_CMOSPAD_DRV_4X = 0x07, /*!< 10pF load @ 65MHz */ - MYK_CMOSPAD_DRV_5X = 0x0F /*!< 12.5pF load @ 65MHz */ -} mykonosCmosPadDrvStr_t; - - -/** - * \brief Enumerated list for Aux ADCs - */ -typedef enum -{ - MYK_AUXADC_0 = 0x00, /*!< Aux ADC channel 0 */ - MYK_AUXADC_1 = 0x01, /*!< Aux ADC channel 1 */ - MYK_AUXADC_2 = 0x02, /*!< Aux ADC channel 2 */ - MYK_AUXADC_3 = 0x03, /*!< Aux ADC channel 3 */ - MYK_AUXADC_0_DIV2 = 0x04, /*!< Aux ADC channel 0 with the divider by 2 set */ - MYK_TEMPSENSOR = 0x10 /*!< Temperature sensor channel */ -} mykonosAuxAdcChannels_t; - - -/** - * \brief Data structure to hold Gain compensation settings for the main receive channels - **/ -typedef struct -{ - uint8_t rx1Offset; /*!< These parameter contains the Rx1 offset word used for the gain compensation - when the gain index is at its maximum setting. - It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ - uint8_t rx2Offset; /*!< These parameter contains the Rx2 offset word used for the gain compensation - when the gain index is at its maximum setting. - It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ - uint8_t compStep; /*!< These bits contains the value in dB that the total Rx gain changes - when there is an LSB change in the gain index according to the following settings: - compStep | dB ramp - ---------|------------ - 0 | 0.25dB - 1 | 0.5dB - 2 | 1.0dB - 3 | 2.0dB - 4 | 3.0dB - 5 | 4.0dB - 6 | 6.0dB - 7 | Not valid defaulted to 0.25dB */ -} mykonosGainComp_t; - -/** - * \brief Data structure to hold Gain compensation settings for the observation channel - **/ -typedef struct -{ - uint8_t obsRxOffset; /*!< These parameter contains the Rx1 offset word used for the gain compensation - when the gain index is at its maximum setting. - It has a range of 0 to 0x1F with a resolution is 0.5dB per LSB. */ - uint8_t compStep; /*!< These bits contains the value in dB that the total Rx gain changes - when there is an LSB change in the gain index according to the following settings: - compStep | dB ramp - ---------|------------ - 0 | 0.25dB - 1 | 0.5dB - 2 | 1.0dB - 3 | 2.0dB - 4 | 3.0dB - 5 | 4.0dB - 6 | 6.0dB - 7 | Not valid defaulted to 0.25dB */ -} mykonosObsRxGainComp_t; - -/** - * \brief Data structure to hold floating point formatter settings for the floating point - * number generation - **/ -typedef struct -{ - uint8_t roundMode; /*! -#include -#include "platform_drivers.h" - -/******************************************************************************/ -/************************ Functions Definitions *******************************/ -/******************************************************************************/ - -/** - * @brief Initialize the I2C communication peripheral. - * @param desc - The I2C descriptor. - * @param init_param - The structure that contains the I2C parameters. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t i2c_init(struct i2c_desc **desc, - const struct i2c_init_param *param) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - if (param->type) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Free the resources allocated by i2c_init(). - * @param desc - The I2C descriptor. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t i2c_remove(struct i2c_desc *desc) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Write data to a slave device. - * @param desc - The I2C descriptor. - * @param data - Buffer that stores the transmission data. - * @param bytes_number - Number of bytes to write. - * @param stop_bit - Stop condition control. - * Example: 0 - A stop condition will not be generated; - * 1 - A stop condition will be generated. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t i2c_write(struct i2c_desc *desc, - uint8_t *data, - uint8_t bytes_number, - uint8_t stop_bit) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - if (data) { - // Unused variable - fix compiler warning - } - - if (bytes_number) { - // Unused variable - fix compiler warning - } - - if (stop_bit) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Read data from a slave device. - * @param desc - The I2C descriptor. - * @param data - Buffer that will store the received data. - * @param bytes_number - Number of bytes to read. - * @param stop_bit - Stop condition control. - * Example: 0 - A stop condition will not be generated; - * 1 - A stop condition will be generated. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t i2c_read(struct i2c_desc *desc, - uint8_t *data, - uint8_t bytes_number, - uint8_t stop_bit) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - if (data) { - // Unused variable - fix compiler warning - } - - if (bytes_number) { - // Unused variable - fix compiler warning - } - - if (stop_bit) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Initialize the SPI communication peripheral. - * @param desc - The SPI descriptor. - * @param init_param - The structure that contains the SPI parameters. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t spi_init(struct spi_desc **desc, - const struct spi_init_param *param) -{ - spi_desc *descriptor; - int32_t ret; - - descriptor = (struct spi_desc *) calloc(1, sizeof(*descriptor)); - if (!descriptor) - return FAILURE; - - descriptor->mode = param->mode; - descriptor->chip_select = param->chip_select; - descriptor->flags = param->flags; - -#ifdef _XPARAMETERS_PS_H_ - descriptor->config = XSpiPs_LookupConfig(param->id); - if (descriptor->config == NULL) - goto error; - - ret = XSpiPs_CfgInitialize(&descriptor->instance, - descriptor->config, descriptor->config->BaseAddress); - if (ret != 0) - goto error; - - XSpiPs_SetOptions(&descriptor->instance, - XSPIPS_MASTER_OPTION | - ((descriptor->flags & SPI_CS_DECODE) ? - XSPIPS_DECODE_SSELECT_OPTION : 0) | - XSPIPS_FORCE_SSELECT_OPTION | - ((descriptor->mode & SPI_CPOL) ? - XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | - ((descriptor->mode & SPI_CPHA) ? - XSPIPS_CLK_PHASE_1_OPTION : 0)); - - XSpiPs_SetClkPrescaler(&descriptor->instance, - XSPIPS_CLK_PRESCALE_64); - - XSpiPs_SetSlaveSelect(&descriptor->instance, 0xf); -#else - ret = XSpi_Initialize(&descriptor->instance, param->id); - if (ret != 0) - goto error; - - XSpi_SetOptions(&descriptor->instance, - XSP_MASTER_OPTION | - ((descriptor->mode & SPI_CPOL) ? - XSP_CLK_ACTIVE_LOW_OPTION : 0) | - ((descriptor->mode & SPI_CPHA) ? - XSP_CLK_PHASE_1_OPTION : 0)); - - XSpi_Start(&descriptor->instance); - - XSpi_IntrGlobalDisable(&descriptor->instance); -#endif - - *desc = descriptor; - - return SUCCESS; - -error: - free(descriptor); - - return FAILURE; -} - -/** - * @brief Free the resources allocated by spi_init(). - * @param desc - The SPI descriptor. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t spi_remove(struct spi_desc *desc) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Write and read data to/from SPI. - * @param desc - The SPI descriptor. - * @param data - The buffer with the transmitted/received data. - * @param bytes_number - Number of bytes to write/read. - * @return SUCCESS in case of success, FAILURE otherwise. - */ - -int32_t spi_write_and_read(struct spi_desc *desc, - uint8_t *data, - uint8_t bytes_number) -{ -#ifdef _XPARAMETERS_PS_H_ - XSpiPs_SetOptions(&desc->instance, - XSPIPS_MASTER_OPTION | - ((desc->flags & SPI_CS_DECODE) ? - XSPIPS_DECODE_SSELECT_OPTION : 0) | - XSPIPS_FORCE_SSELECT_OPTION | - ((desc->mode & SPI_CPOL) ? - XSPIPS_CLK_ACTIVE_LOW_OPTION : 0) | - ((desc->mode & SPI_CPHA) ? - XSPIPS_CLK_PHASE_1_OPTION : 0)); - - XSpiPs_SetSlaveSelect(&desc->instance, desc->chip_select); - // 0xf & ~desc->chip_select); - XSpiPs_PolledTransfer(&desc->instance, - data, data, bytes_number); -#else - XSpi_SetOptions(&desc->instance, - XSP_MASTER_OPTION | - ((desc->mode & SPI_CPOL) ? - XSP_CLK_ACTIVE_LOW_OPTION : 0) | - ((desc->mode & SPI_CPHA) ? - XSP_CLK_PHASE_1_OPTION : 0)); - - XSpi_SetSlaveSelect(&desc->instance, - desc->chip_select); - - XSpi_Transfer(&desc->instance, - data, data, bytes_number); -#endif - return 0; -} - -/** - * @brief Obtain the GPIO decriptor. - * @param desc - The GPIO descriptor. - * @param gpio_number - The number of the GPIO. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_get(struct gpio_desc **desc, - uint8_t gpio_number) -{ - gpio_desc *descriptor; - int32_t ret; - - descriptor = (struct gpio_desc *) malloc(sizeof(*descriptor)); - if (!descriptor) - return FAILURE; - -#ifdef _XPARAMETERS_PS_H_ - descriptor->config = XGpioPs_LookupConfig(0); - if (descriptor->config == NULL) - goto error; - - ret = XGpioPs_CfgInitialize(&descriptor->instance, - descriptor->config, descriptor->config->BaseAddr); - if (ret != 0) - goto error; -#else - ret = XGpio_Initialize(&descriptor->instance, 0); - if (ret != 0) - goto error; -#endif - - descriptor->number = gpio_number; - - *desc = descriptor; - - return SUCCESS; - -error: - free(descriptor); - - return FAILURE; -} - -/** - * @brief Free the resources allocated by gpio_get(). - * @param desc - The SPI descriptor. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_remove(struct gpio_desc *desc) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - return SUCCESS; -} - -/** - * @brief Enable the input direction of the specified GPIO. - * @param desc - The GPIO descriptor. - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_direction_input(struct gpio_desc *desc) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - return 0; -} - -/** - * @brief Enable the output direction of the specified GPIO. - * @param desc - The GPIO descriptor. - * @param value - The value. - * Example: GPIO_HIGH - * GPIO_LOW - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_direction_output(struct gpio_desc *desc, - uint8_t value) -{ -#ifdef _XPARAMETERS_PS_H_ - XGpioPs_SetDirectionPin(&desc->instance, desc->number, 1); - - XGpioPs_SetOutputEnablePin(&desc->instance, desc->number, 1); - - XGpioPs_WritePin(&desc->instance, desc->number, value); -#else - uint8_t pin = desc->number; - uint8_t channel; - uint32_t reg_val; - - if (pin >= 32) { - channel = 2; - pin -= 32; - } else - channel = 1; - - reg_val = XGpio_GetDataDirection(&desc->instance, channel); - reg_val &= ~(1 << pin); - XGpio_SetDataDirection(&desc->instance, channel, reg_val); - - reg_val = XGpio_DiscreteRead(&desc->instance, channel); - if(value) - reg_val |= (1 << pin); - else - reg_val &= ~(1 << pin); - XGpio_DiscreteWrite(&desc->instance, channel, reg_val); -#endif - - return SUCCESS; -} - -/** - * @brief Get the direction of the specified GPIO. - * @param desc - The GPIO descriptor. - * @param direction - The direction. - * Example: GPIO_OUT - * GPIO_IN - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_get_direction(struct gpio_desc *desc, - uint8_t *direction) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - if (direction) { - // Unused variable - fix compiler warning - } - - return 0; -} - -/** - * @brief Set the value of the specified GPIO. - * @param desc - The GPIO descriptor. - * @param value - The value. - * Example: GPIO_HIGH - * GPIO_LOW - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_set_value(struct gpio_desc *desc, - uint8_t value) -{ -#ifdef _XPARAMETERS_PS_H_ - XGpioPs_WritePin(&desc->instance, desc->number, value); -#else - uint8_t pin = desc->number; - uint8_t channel; - uint32_t reg_val; - - if (pin >= 32) { - channel = 2; - pin -= 32; - } else - channel = 1; - - reg_val = XGpio_DiscreteRead(&desc->instance, channel); - if(value) - reg_val |= (1 << pin); - else - reg_val &= ~(1 << pin); - XGpio_DiscreteWrite(&desc->instance, channel, reg_val); -#endif - - return 0; -} - -/** - * @brief Get the value of the specified GPIO. - * @param desc - The GPIO descriptor. - * @param value - The value. - * Example: GPIO_HIGH - * GPIO_LOW - * @return SUCCESS in case of success, FAILURE otherwise. - */ -int32_t gpio_get_value(struct gpio_desc *desc, - uint8_t *value) -{ - if (desc) { - // Unused variable - fix compiler warning - } - - if (value) { - // Unused variable - fix compiler warning - } - - return 0; -} - -/** - * @brief Generate microseconds delay. - * @param usecs - Delay in microseconds. - * @return None. - */ -void udelay(uint32_t usecs) -{ - usleep(usecs); -} - -/** - * @brief Generate miliseconds delay. - * @param msecs - Delay in miliseconds. - * @return None. - */ -void mdelay(uint32_t msecs) -{ -#ifdef _XPARAMETERS_PS_H_ - usleep(msecs * 1000); -#else - usleep(msecs * 50); // FIXME -#endif -} diff --git a/df_datalink_ge/src/hwconfig.c b/df_datalink_ge/src/hwconfig.c new file mode 100644 index 0000000..477d0ee --- /dev/null +++ b/df_datalink_ge/src/hwconfig.c @@ -0,0 +1,740 @@ +/*****************************************************************************/ +/** + * Description: hwconfig.h + * + + * Date: 2024-02-20 13:19 + * Last Edit Time: [2024-02-20 13:19] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include +// Xilinx +#include "xgpiops.h" +#include "drivers/axi_core/spi_engine/spi_engine.h" +// App +#include "common.h" +#include "error.h" +#include "delay.h" +#include "system_monitor.h" +#include "hwconfig.h" +#include "config/app_config.h" +#include "dev_profile/dev_profile.h" +#ifdef RFSOC +#include "xrfdc.h" +#endif + +/************************** Function Prototypes ******************************/ +/*********************** Driver Instance Definitions **************************/ +static struct hmc7044_dev *hmc7044_inst; +ad9528Device_t *ad9528_inst; +static struct lmk04828_dev *lmk04828_inst; +static struct lmx2594_dev *lmx2594_adc_inst; +static struct lmx2594_dev *lmx2594_dac_inst; +static struct ad9361_reg_dev *ad9361_1_reg_inst; +static struct ad9361_reg_dev *ad9361_2_reg_inst; +static struct ad9361_rf_phy *ad9361_phy; +static struct ad9653_dev *ad9653_inst; +static struct ad9694_dev *ad9694_inst; + +XGpioPs Gpio; +#ifdef RFSOC +XRFdc RFdc; +#endif + +/*****************************************************************************/ +/** + * @brief Hardware_Init + * + * @param none. + * + * @return None. + * + ******************************************************************************/ +int32_t Hardware_Init(void) +{ + int32_t Status; + + // gpio initialization + XGpioPs_Config *ConfigPtr; + ConfigPtr = XGpioPs_LookupConfig(AD9361_GPIO_DEVICE_ID); + Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr); + if (Status != SUCCESS) + { + return FAILURE; + } + +#ifdef RFSOC + /**********************************************************/ + /************* RF Data Converter Configuration ************/ + /**********************************************************/ + // rf data converter initialization + XRFdc_Config *RFdc_ConfigPtr; + RFdc_ConfigPtr = XRFdc_LookupConfig(RFDC_DEVICE_ID); + Status = XRFdc_CfgInitialize(&RFdc, RFdc_ConfigPtr); + if (Status != XST_SUCCESS) + { + return XST_FAILURE; + } + mdelay(100); +#endif + +#ifdef HMC7044 + /**********************************************************/ + /****************** HMC7044 Configuration *****************/ + /**********************************************************/ + Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param); + if (Status != SUCCESS) + { + DBG_ERROR("HDWR: hmc7044_init() error: %" PRId32 "\n", Status); + return FAILURE; + } +#endif + +#ifdef AD9528 + /**********************************************************/ + /****************** AD9528 Configuration ******************/ + /**********************************************************/ + Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param); + if (Status != SUCCESS) { + DBG_ERROR("HDWR: AD9528_init() error: %" PRId32 "\n", Status); + return FAILURE; + } + + Status = AD9528_config(ad9528_inst); + if (Status != SUCCESS) { + return FAILURE; + DBG_ERROR("HDWR: AD9528_config() error: %" PRId32 "\n", Status); + } +#endif + +#ifdef LMK04828 + /**********************************************************/ + /***************** LMK04828 Configuration *****************/ + /**********************************************************/ + Status = lmk04828_init(&lmk04828_inst, &lmk04828_default_init_param); + for(int i = 0; i < lmk04828_default_config_len; i++) + { + Status = lmk04828_write(lmk04828_inst, + lmk04828_default_config[i].addr, lmk04828_default_config[i].value); + if (lmk04828_default_config[i].addr == 0x0000) + { + mdelay(500); + } + } + + uint8_t Lmk04828Read; + + // check pll1 lock status + Status = lmk04828_read(lmk04828_inst, 0x0182, &Lmk04828Read); + if ((Lmk04828Read & 0x02) == 0x02) { + DBG_INFO("HDWR: [LMK04828] PLL1 Locked.\r\n"); + } + else { + DBG_ERROR("HDWR: [LMK04828] PLL1 NOT lock. It takes a while " + "for PLL1 to lock. Lock status is shown on LED.\r\n"); + } + + // check pll2 lock status + Status = lmk04828_read(lmk04828_inst, 0x0183, &Lmk04828Read); + if ((Lmk04828Read & 0x02) == 0x02) { + DBG_INFO("HDWR: [LMK04828] PLL2 Locked.\r\n"); + } + else { + DBG_INFO("HDWR: [LMK04828] PLL2 NOT lock!\r\n"); + } +#endif + +#ifdef LMX2594_ADC + /**********************************************************/ + /************* LMX2594 for ADC Configuration **************/ + /**********************************************************/ + Status = lmx2594_init(&lmx2594_adc_inst, &lmx2594_adc_init_param); + for(int i = 0; i < lmx2594_default_config_len; i++) + { + Status = lmx2594_write(lmx2594_adc_inst, + lmx2594_default_config[i].addr, lmx2594_default_config[i].value); + if (lmx2594_default_config[i].addr == 0) + { + mdelay(500); + } + } + + uint16_t Lmx2594AdcRead; + + // check vco lock status + Status = lmx2594_read(lmx2594_adc_inst, 110, &Lmx2594AdcRead); + if (((Lmx2594AdcRead >> 9) & 0x0003) == 0x0002) { + DBG_INFO("HDWR: [ADC LMX2594] Config Done.\r\n"); + } + else { + DBG_INFO("HDWR: [ADC LMX2594] not lock!\r\n"); + } + + // set mux out to lock status + Status = lmx2594_write(lmx2594_adc_inst, 0x00, 0x259C); + DBG_INFO("HDWR: [ADC LMX2594] SPI readback disabled, " + "lock status is shown on LED.\r\n"); +#endif + +#ifdef LMX2594_DAC + /**********************************************************/ + /************* LMX2594 for DAC Configuration **************/ + /**********************************************************/ + Status = lmx2594_init(&lmx2594_dac_inst, &lmx2594_dac_init_param); + for(int i = 0; i < lmx2594_default_config_len; i++) + { + Status = lmx2594_write(lmx2594_dac_inst, + lmx2594_default_config[i].addr, lmx2594_default_config[i].value); + if (lmx2594_default_config[i].addr == 0) + { + mdelay(500); + } + } + + uint16_t Lmx2594DacRead; + + // check vco lock status + Status = lmx2594_read(lmx2594_dac_inst, 110, &Lmx2594DacRead); + if (((Lmx2594DacRead >> 9) & 0x0003) == 0x0002) { + DBG_INFO("HDWR: [DAC LMX2594] Config Done.\r\n"); + } + else { + DBG_INFO("HDWR: [DAC LMX2594] not lock!\r\n"); + } + + // set mux out to lock status + Status = lmx2594_write(lmx2594_dac_inst, 0x00, 0x259C); + DBG_INFO("HDWR: [DAC LMX2594] SPI readback disabled, " + "lock status is shown on LED.\r\n"); +#endif + +#if defined(AD9361_API) || defined(AD9361_REG) + /**********************************************************/ + /***************** AD9361-1 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_1_RESET_B, AD9361_GPIO_OUTPUT); + +#ifdef AD9361_REG + ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 0); + ad9361_1_reg_config(ad9361_1_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 1); +#endif +#ifdef AD9361_API + Status = ad9361_init(&ad9361_phy, &ad9361_default_init_param); + if (Status != XST_SUCCESS){ + DBG_ERROR("HDWR: ad9361_init() error: %" PRId32 "\n", Status); + return XST_FAILURE; + } + ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config); + ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config); +#endif + /**********************************************************/ + /***************** AD9361-2 Configuration *****************/ + /**********************************************************/ + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_TXNRX, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_ENABLE, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_EN_AGC, AD9361_GPIO_OUTPUT); + XGpioPs_SetDirectionPin(&Gpio, AD9361_2_RESET_B, AD9361_GPIO_OUTPUT); + + ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 0); + ad9361_2_reg_config(ad9361_2_reg_inst); + XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 1); + + // uint8_t rd_back; + // Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back); + // Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back); + +// /**********************************************************/ +// /******* AD9361 Baseband Multichip Synchronization ********/ +// /**********************************************************/ +// XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT); +// XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT); +// +// // SYNC BBPLL and DIGITAL SAMPLING CLOCKS +// ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable +// ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D); +// ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable +// ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80); +// XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); +// mdelay(20); +// XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin +// mdelay(500); +// XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); +// mdelay(2000); +// ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable +// ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B); +// XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin +// mdelay(500); +// XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0); +// ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits +// ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08); +// +// XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); +// mdelay(20); +// XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1); +// mdelay(20); +// XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0); +// +// /**********************************************************/ +// /********* AD9361 Multichip Rx Phase Calibration **********/ +// /**********************************************************/ +// XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT); +// XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT); +// XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT); +// XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT); +// XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT); +// +// // switch to lower frequency +// Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126); +// XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1); +// mdelay(20); +// +// // switch rx channel +// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30); +// Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30); +// +// // enable dual ad9361 tx channels +// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels +// +// // switch ad9361 tx channel +// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B) +// mdelay(20); +// +// // begin to calibrate the 1st ad9361 +// XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); +// XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1); +// mdelay(1); +// XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0); +// +// // read calibration status +// int32_t time_out_cnt = 0; +// do +// { +// mdelay(1); // Wait 1ms +// time_out_cnt++; +// } while (((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); +// +// if (time_out_cnt == AD9361_TIMEOUT_TH) +// { +// return FAILURE; +// } +// +// // begin to calibrate the 2nd ad9361 +// XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1); +// mdelay(1); +// XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0); +// +// // read calibration status +// time_out_cnt = 0; +// do +// { +// mdelay(1); // Wait 1ms +// time_out_cnt++; +// } while (((XGpioPs_ReadPin(&Gpio, AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH)); +// +// if (time_out_cnt == AD9361_TIMEOUT_TH) +// { +// return FAILURE; +// } +// +// // enable single ad9361 tx channels +// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels +// +// // switch ad9361 tx & rx channel +// Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03); +// Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03); +// +// // switch to higher frequency +// Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125); +// XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0); +// + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 0x14); // Rx Gain + Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x14); // Rx Gain + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x14); // Rx Gain + Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x14); // Rx Gain +#endif + +#ifdef AD9653 + Status = ad9653_init(&ad9653_inst, &ad9653_default_init_param); + for(int i = 0; i < ad9653_default_config_len; i++){ + Status = ad9653_write(ad9653_inst, ad9653_default_config[i].addr, + ad9653_default_config[i].value); + if (ad9653_default_config[i].addr == 0x0000){ + mdelay(500); + } + } +#endif + +#ifdef AD9694 + /**********************************************************/ + /****************** AD9694 Configuration ******************/ + /**********************************************************/ + Status = ad9694_init(&ad9694_inst, &ad9694_default_init_param); + for(int i = 0; i < ad9694_default_config_len; i++){ + Status = ad9694_write(ad9694_inst, ad9694_default_config[i].addr, ad9694_default_config[i].value); + if (ad9694_default_config[i].addr == 0x0000){ + mdelay(500); + } + } + +// uint8_t reg0008; +// uint8_t reg056F; +// uint8_t reg0571; +// +// ad9694_read(ad9694_inst,0x008,®0008); +// ad9694_read(ad9694_inst,0x56F,®056F); +// ad9694_read(ad9694_inst,0x571,®0571); +#endif + +#ifdef RFSOC + /* + * DAC Mapping: + * Number Tile Block + * 1 (VOUT_00) 228 (XRFDC_TILE_ID0) DAC 0/DUC 0 (XRFDC_BLK_ID0) + * 2 (VOUT_02) 228 (XRFDC_TILE_ID0) DAC 1/DUC 2 (XRFDC_BLK_ID2) + * 3 (VOUT_10) 229 (XRFDC_TILE_ID1) DAC 1/DUC 0 (XRFDC_BLK_ID0) + * 4 (VOUT_12) 229 (XRFDC_TILE_ID1) DAC 1/DUC 2 (XRFDC_BLK_ID2) + * 5 (VOUT_20) 230 (XRFDC_TILE_ID2) DAC 0/DUC 0 (XRFDC_BLK_ID0) + * 6 (VOUT_22) 230 (XRFDC_TILE_ID2) DAC 1/DUC 2 (XRFDC_BLK_ID2) + * 7 (VOUT_30) 231 (XRFDC_TILE_ID3) DAC 0/DUC 0 (XRFDC_BLK_ID0) + * 8 (VOUT_32) 231 (XRFDC_TILE_ID3) DAC 1/DUC 2 (XRFDC_BLK_ID2) + * + */ + + // get & set mixer settings + XRFdc_Mixer_Settings Mixer_Settings_DAC; + + // 3th channel + Status = XRFdc_GetMixerSettings(&RFdc, XRFDC_DAC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, &Mixer_Settings_DAC); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Mixer_Settings_DAC.Freq = 1500; + + Status = XRFdc_SetMixerSettings(&RFdc, XRFDC_DAC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, &Mixer_Settings_DAC); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + mdelay(100); + + Status = XRFdc_UpdateEvent(&RFdc, XRFDC_DAC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, XRFDC_EVENT_MIXER); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + /* + * ADC Mapping: + * Number Tile Block + * 1 (VIN0_01) 224 (XRFDC_TILE_ID0) ADC 0 (XRFDC_BLK_ID0) + * 2 (VIN0_12) 224 (XRFDC_TILE_ID0) ADC 1 (XRFDC_BLK_ID1) + * 3 (VIN1_01) 225 (XRFDC_TILE_ID1) ADC 0 (XRFDC_BLK_ID0) + * 4 (VIN1_23) 225 (XRFDC_TILE_ID1) ADC 1 (XRFDC_BLK_ID1) + * 5 (VIN2_01) 226 (XRFDC_TILE_ID2) ADC 0 (XRFDC_BLK_ID0) + * 6 (VIN2_23) 227 (XRFDC_TILE_ID2) ADC 1 (XRFDC_BLK_ID1) + * 7 (VIN3_01) 224 (XRFDC_TILE_ID0) ADC 0 (XRFDC_BLK_ID0) + * 8 (VIN3_23) 227 (XRFDC_TILE_ID3) ADC 1 (XRFDC_BLK_ID1) + * + */ + + // get & set mixer settings + XRFdc_Mixer_Settings Mixer_Settings_ADC; + + // 3rd channel + Status = XRFdc_GetMixerSettings(&RFdc, XRFDC_ADC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, &Mixer_Settings_ADC); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + Mixer_Settings_ADC.Freq = 1500; + Mixer_Settings_ADC.EventSource = XRFDC_EVNT_SRC_TILE; + + Status = XRFdc_SetMixerSettings(&RFdc, XRFDC_ADC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, &Mixer_Settings_ADC); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + + mdelay(100); + + Status = XRFdc_UpdateEvent(&RFdc, XRFDC_ADC_TILE, XRFDC_TILE_ID1, + XRFDC_BLK_ID0, XRFDC_EVENT_MIXER); + if (Status != XST_SUCCESS) { + return XST_FAILURE; + } + +#endif + + DBG_INFO("HDWR: Configuration Done.\n"); + + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Hardware_SwitchFreq + * + * @param devSysMonitor_UpdateHardwareStatus(newHwState); + * @param freq + * + * @return None. + * + ******************************************************************************/ +int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq) +{ + int32_t status = 0; + uint8_t value = 0; + int32_t time_out_cnt = 0; + + switch (freq) + { + case TX_FREQ_125: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_126: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Tx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + case TX_FREQ_4125: + { + //************************************************************ + // Setup Tx Frequency-Dependent Syntheisizer Registers + //************************************************************ + status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0] + status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0] + status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0] + status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0] + status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0] + status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0] + status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0] + status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp) + status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1 + status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3 + status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3 + + //************************************************************ + // Write Rx Frequency Words + //************************************************************ + status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0] + status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8] + status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16] + status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8] + status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal) + status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting + + //************************************************************ + // Tx Quadrature Calibration Settings + //************************************************************ + status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency + status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6]) + status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable + status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count + status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp + status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold + status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index + status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count + status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used + + status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration + status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal + + break; + } + + // Wait for cal to complete (Done when 0x016[4]==0) + time_out_cnt = 0; + do + { + status |= ad9361_reg_read(dev, 0x0016, &value); + mdelay(1); // Wait 1ms + time_out_cnt++; + } while ((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH); + } + + return status; +} + +// @ Get AD9361 - 1 temperature (Celsius Degree) +/** + * Read corresponding register to get AD9361 - 1 current temperature. + */ +int8_t Hardware_GetAD9361Temp_1(void) +{ + int8_t scaleTemp; + double temp; + + ad9361_reg_write(ad9361_1_reg_inst, 0x000B, -64); + ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x01); // disable aux adc + ad9361_reg_read(ad9361_1_reg_inst, 0x000E, (uint8_t*)&scaleTemp); + ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x00); // enable aux adc + + temp = ((double)scaleTemp + 64)/1.16; + return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp); +} + +// @ Get AD9361 - 2 temperature (Celsius Degree) +/** + * Read corresponding register to get AD9361 - 2 current temperature. + */ +int8_t Hardware_GetAD9361Temp_2(void) +{ + int8_t scaleTemp; + double temp; + + ad9361_reg_write(ad9361_2_reg_inst, 0x000B, -64); + ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x01); // disable aux adc + ad9361_reg_read(ad9361_2_reg_inst, 0x000E, (uint8_t*)&scaleTemp); + ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x00); // enable aux adc + temp = ((double)scaleTemp + 64)/1.16; + return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp); +} + +// @ Determine AD9361 lock state +/** + * Read corresponding register to determine AD9361(both) lock state. + */ +uint8_t Hardware_GetAD9361LockStatus(void) +{ + uint8_t ret = 0; + uint8_t regVal; + + // bbpll + ad9361_reg_read(ad9361_1_reg_inst, 0x005E, ®Val); // [D7] is lock indicator + ret |= ((regVal & 0x80) == 0x80) ? CLK_AD0_BBPLL_LOCK : 0; + ad9361_reg_read(ad9361_2_reg_inst, 0x005E, ®Val); // [D7] is lock indicator + ret |= ((regVal & 0x80) == 0x80) ? CLK_AD1_BBPLL_LOCK : 0; + + // rfpll + ad9361_reg_read(ad9361_1_reg_inst, 0x0287, ®Val); // [D1] is lock indicator + ret |= ((regVal & 0x02) == 0x02) ? CLK_AD0_RFPLL_LOCK : 0; + ad9361_reg_read(ad9361_2_reg_inst, 0x0287, ®Val); // [D1] is lock indicator + ret |= ((regVal & 0x02) == 0x02) ? CLK_AD1_RFPLL_LOCK : 0; + + return ret; +} + +// @ Determine HMC7044 lock state +/** + * Read corresponding register to determine clock lock state. + */ +uint8_t Hardware_GetHMC7044LockStatus(void) +{ + uint8_t ret = 0; + uint8_t regVal; + + // pll1 + hmc7044_read(hmc7044_inst, 0x007C, ®Val); // [D5] is lock indicator + ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL1_LOCK : 0; + + // pll2 + hmc7044_read(hmc7044_inst, 0x007D, ®Val); // [D0] is lock indicator + ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL2_LOCK : 0; + + return ret; +} diff --git a/df_datalink_ge/src/hwconfig.h b/df_datalink_ge/src/hwconfig.h new file mode 100644 index 0000000..969ceb4 --- /dev/null +++ b/df_datalink_ge/src/hwconfig.h @@ -0,0 +1,32 @@ +/*****************************************************************************/ +/** + * Description: hwconfig.h + * + + * Date: 2024-02-20 13:19 + * Last Edit Time: [2024-02-20 13:19] + * + * Revisions: Rev 0.0 + * History: + * [2023-05-07]: Initial edition. + * + * Copyright(c) 2024 Beijing Institute of Technology. + * + ******************************************************************************/ + +/***************************** Include Files *********************************/ +// Standard +#include +#include "config/app_config.h" +#include "drivers/rf-transceiver/ad9361_reg/ad9361_reg.h" +#include "drivers/rf-transceiver/ad9361/ad9361_api.h" + +/************************** Function Prototypes ******************************/ +int32_t Hardware_Init(void); +int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq); +int8_t Hardware_GetAD9361Temp_1(void); +int8_t Hardware_GetAD9361Temp_2(void); +uint8_t Hardware_GetAD9361LockStatus(void); +uint8_t Hardware_GetHMC7044LockStatus(void); + + diff --git a/df_datalink_ge/src/include/circ_queue.h b/df_datalink_ge/src/include/circ_queue.h index a6dc655..684dc58 100644 --- a/df_datalink_ge/src/include/circ_queue.h +++ b/df_datalink_ge/src/include/circ_queue.h @@ -1,33 +1,25 @@ /*****************************************************************************/ /** - * Description: A simple circular FIFO bounded queue - * - * Author: Fan Hao - * Date: 2023-02-23 10:29 - * LastEditors: Fan Hao - * LastEditTime: 2023-02-23 12:53 - * Revisions: Rev 0.0 - * History: - * [2023-02-23]: Initial Version. - * - * Copyright(c) 2023 Beijing Institute of Technology. - * Lab of Communication and Networking - * NOTE: Forked from https://github.com/chrismerck/rpa_queue.git - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at + * @file circ_queue.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A simple circular FIFO bounded queue + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/chrismerck/rpa_queue.git + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. -******************************************************************************/ + ******************************************************************************/ + +/** + * @addtogroup Utility + * @{ + */ + +/** + * @defgroup CircularQueue + * @{ + */ #ifndef CIRC_QUEUE_H #define CIRC_QUEUE_H @@ -36,76 +28,73 @@ #include #include - /** - * opaque structure + * @struct CIRC_QUEUE + * @brief Circular queue Instance */ -typedef struct { - void **data; - volatile uint32_t nelts; /**< # elements */ - uint32_t in; /**< next empty location */ - uint32_t out; /**< next filled location */ - uint32_t bounds;/**< max size of queue */ +typedef struct +{ + void **data; + volatile uint32_t nelts; ///< number of elements + uint32_t in; ///< next empty location + uint32_t out; ///< next filled location + uint32_t bounds; ///< max size of queue } CIRC_QUEUE; - - /** - * create a FIFO queue + * @brief create a FIFO queue * @param queue The new queue * @param queue_capacity maximum size of the queue - * @param a pool to allocate queue from */ bool CircQueueCreate(CIRC_QUEUE **queue, uint32_t queue_capacity); -/** free queue memory -- call after destroy - * @note we do not free in destroy() to follow pthreads convention -*/ -void CircQueueFree(CIRC_QUEUE * queue); +/** + * @brief free queue memory -- call after destroy + */ +void CircQueueFree(CIRC_QUEUE *queue); /** - * Detects when the CIRC_QUEUE is full. This utility function is expected + * @brief Detects when the CIRC_QUEUE is full. This utility function is expected * to be called from within critical sections, and is not threadsafe. */ bool isCircQueueFull(CIRC_QUEUE *queue); /** - * Detects when the CIRC_QUEUE is empty. This utility function is expected + * @brief Detects when the CIRC_QUEUE is empty. This utility function is expected * to be called from within critical sections, and is not threadsafe. */ bool isCircQueueEmpty(CIRC_QUEUE *queue); /** - * push/add an object to the queue, blocking if the queue is already full + * @brief push/add an object to the queue, blocking if the queue is already full * * @param queue the queue * @param data the data - * @returns RPA_EINTR the blocking was interrupted (try again) - * @returns RPA_EOF the queue has been terminated - * @returns RPA_SUCCESS on a successful push + * @return True on a successful push + * @return False push failed */ bool CircQueuePush(CIRC_QUEUE *queue, void *data); - /** - * pop/get an object from the queue, blocking if the queue is already empty + * @brief pop/get an object from the queue, blocking if the queue is already empty * * @param queue the queue * @param data the data - * @returns RPA_EINTR the blocking was interrupted (try again) - * @returns RPA_EOF if the queue has been terminated - * @returns RPA_SUCCESS on a successful pop + * @return false pop failed + * @return true on a successful pop */ bool CircQueuePop(CIRC_QUEUE *queue, void **data); /** - * returns the size of the queue. + * @brief returns the size of the queue. * - * @warning this is not threadsafe, and is intended for reporting/monitoring - * of the queue. * @param queue the queue - * @returns the size of the queue + * @return the size of the queue */ uint32_t CircQueueSize(CIRC_QUEUE *queue); #endif /* CIRC_QUEUE_H */ + +/** @} CircularQueue*/ + +/** @} Utility*/ \ No newline at end of file diff --git a/df_datalink_ge/src/include/clist.h b/df_datalink_ge/src/include/clist.h index 8a2e925..6206b53 100644 --- a/df_datalink_ge/src/include/clist.h +++ b/df_datalink_ge/src/include/clist.h @@ -1,9 +1,25 @@ +/*****************************************************************************/ +/** + * @file clist.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief A basic list data structure + * @version 0.1 + * @date 2023-02-23 + * @note Forked from https://github.com/clibs/list + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ -// -// clist.h -// -// Copyright (c) 2010 TJ Holowaychuk -// +/** + * @addtogroup Utility + * @{ + */ + +/** + * @defgroup cList + * @{ + */ #ifndef __CLIST_H__ #define __CLIST_H__ @@ -16,103 +32,107 @@ extern "C" #include #include - /* - * clist_t iterator direction. - */ + /** + * @enum clist_direction_t + * @brief clist_t iterator direction. + */ + typedef enum + { + LIST_HEAD, + LIST_TAIL + } clist_direction_t; - typedef enum - { - LIST_HEAD, - LIST_TAIL - } clist_direction_t; + /** + * @struct clist_node_t + * @brief clist_t node struct. + */ + typedef struct clist_node + { + struct clist_node *prev; ///< previous node + struct clist_node *next; ///< next node + void *val; + } clist_node_t; - /* - * clist_t node struct. - */ + /** + * @struct clist_t + * @brief clist_t struct. + */ + typedef struct + { + clist_node_t *head; ///< first node + clist_node_t *tail; ///< last node + uint32_t len; ///< list length + void (*free)(void *val); ///< node free function handle + int8_t (*compare)(void *a, void *b); ///< node compare function handle + } clist_t; - typedef struct clist_node - { - struct clist_node *prev; - struct clist_node *next; - void *val; - } clist_node_t; + /** + * @struct clist_iterator_t + * @brief clist_t iterator struct. + */ + typedef struct + { + clist_node_t *next; ///< next element + clist_direction_t direction; ///< iter direction + } clist_iterator_t; - /* - * clist_t struct. - */ + // Node prototypes. - typedef struct - { - clist_node_t *head; - clist_node_t *tail; - uint32_t len; - void (*free)(void *val); - int8_t (*compare)(void *a, void *b); - } clist_t; + clist_node_t * + clist_node_new(void *val); - /* - * clist_t iterator struct. - */ + // clist_t prototypes. - typedef struct - { - clist_node_t *next; - clist_direction_t direction; - } clist_iterator_t; + clist_t * + clist_new(void); - // Node prototypes. + clist_node_t * + clist_rpush(clist_t *self, clist_node_t *node); - clist_node_t * - clist_node_new(void *val); + clist_node_t * + clist_lpush(clist_t *self, clist_node_t *node); - // clist_t prototypes. + clist_node_t * + clist_find(clist_t *self, void *val); - clist_t * - clist_new(void); + clist_node_t * + clist_at(clist_t *self, int index); - clist_node_t * - clist_rpush(clist_t *self, clist_node_t *node); + clist_node_t * + clist_rpop(clist_t *self); - clist_node_t * - clist_lpush(clist_t *self, clist_node_t *node); + clist_node_t * + clist_lpop(clist_t *self); - clist_node_t * - clist_find(clist_t *self, void *val); + void + clist_remove(clist_t *self, clist_node_t *node); - clist_node_t * - clist_at(clist_t *self, int index); + void + clist_clear(clist_t *self); - clist_node_t * - clist_rpop(clist_t *self); + void + clist_destroy(clist_t *self); - clist_node_t * - clist_lpop(clist_t *self); + // clist_t iterator prototypes. - void - clist_remove(clist_t *self, clist_node_t *node); + clist_iterator_t * + clist_iterator_new(clist_t *list, clist_direction_t direction); - void - clist_clear(clist_t *self); + clist_iterator_t * + clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction); - void - clist_destroy(clist_t *self); + clist_node_t * + clist_iterator_next(clist_iterator_t *self); - // clist_t iterator prototypes. - - clist_iterator_t * - clist_iterator_new(clist_t *list, clist_direction_t direction); - - clist_iterator_t * - clist_iterator_new_from_node(clist_node_t *node, clist_direction_t direction); - - clist_node_t * - clist_iterator_next(clist_iterator_t *self); - - void - clist_iterator_destroy(clist_iterator_t *self); + void + clist_iterator_destroy(clist_iterator_t *self); #ifdef __cplusplus } #endif #endif /* __CLIBS_LIST_H__ */ + +/** @} cList*/ + +/** @} Utility*/ \ No newline at end of file diff --git a/df_datalink_ge/src/include/common.h b/df_datalink_ge/src/include/common.h index 6cd0362..1421565 100644 --- a/df_datalink_ge/src/include/common.h +++ b/df_datalink_ge/src/include/common.h @@ -1,20 +1,19 @@ /*****************************************************************************/ /** - * Description: Common definitions - * - * Date: 2023-12-21 16:32 - * LastEditors: Fan Hao - * LastEditTime: 2022-07-16 17:13 - * Revisions: Rev 0.1 - * History: - * [2023-12-21]: Ensure the code conform ISO C11 standard. - * [2022-07-16]: New branch for Dijian. - * [2021-11-16]: Initial version. - * - * Copyright(c) 2021 Beijing Institute of Technology. - * Lab of Communication and Networking + * @file common.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Common macros + * @version 0.0 + * @date 2022-07-16 + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network * ******************************************************************************/ +/** + * @defgroup COMMON_MACRO + * @{ + */ + /***************************** Include Files *********************************/ #ifndef __COMMON_H_ #define __COMMON_H_ @@ -25,7 +24,6 @@ #include #include "util.h" #include "error.h" -#include "../config/app_config.h" /************************** Constant Definitions *****************************/ /***************** Macros (Inline Functions) Definitions *********************/ @@ -48,8 +46,8 @@ #endif #if _DEBUG_LEVEL >= 1 #define DBG_ERROR(...) __PRINT_BLOCK( \ - printf("in"__FILE__ \ - ":%d [error]\t", \ + printf("in "__FILE__ \ + ":%d [error]\t", \ __LINE__); \ printf(__VA_ARGS__);) #endif @@ -91,3 +89,5 @@ /************************** Function Prototypes ******************************/ void AppAssert(const char *file, int line); #endif /* __COMMON_H_ */ + +/** @} */ diff --git a/df_datalink_ge/src/hardware/parameters.h b/df_datalink_ge/src/include/delay.h similarity index 66% rename from df_datalink_ge/src/hardware/parameters.h rename to df_datalink_ge/src/include/delay.h index 114eeff..d1dee17 100644 --- a/df_datalink_ge/src/hardware/parameters.h +++ b/df_datalink_ge/src/include/delay.h @@ -1,6 +1,6 @@ /***************************************************************************//** - * @file ad9371/src/devices/adi_hal/parameters.h - * @brief Platform dependent parameters. + * @file delay.h + * @brief Header file of Delay functions * @author DBogdan (dragos.bogdan@analog.com) ******************************************************************************** * Copyright 2019(c) Analog Devices, Inc. @@ -36,46 +36,35 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ -#ifndef _PARAMETERS_H_ -#define _PARAMETERS_H_ + +#ifndef _DELAY_H_ +#define _DELAY_H_ /******************************************************************************/ /***************************** Include Files **********************************/ /******************************************************************************/ -#include "platform_drivers.h" -#include "xparameters.h" + +#include + +/** + * @struct time + * @brief Structure holding time data (seconds, microseconds). + */ +struct time { + unsigned int s, us; +}; /******************************************************************************/ -/********************** Macros and Constants Definitions **********************/ +/************************ Functions Declarations ******************************/ /******************************************************************************/ -#define DDR_MEM_BASEADDR XPAR_DDR_MEM_BASEADDR -#define GPIO_0_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID -//#define FREQ_CTRL_DEVICE_ID XPAR_AXI_9731_FREQ_CTRL_DEVICE_ID -//#define GAIN_CTRL_DEVICE_ID XPAR_AXI_9731_RX_GAIN_DEVICE_ID -//#define ATTN_CTRL_DEVICE_ID XPAR_AXI_9731_TX_ATTN_DEVICE_ID -// -//#define FREQ_CTRL_INTR_ID XPAR_FABRIC_AXI_9731_FREQ_CTRL_IP2INTC_IRPT_INTR -//#define GAIN_CTRL_INTR_ID XPAR_FABRIC_AXI_9731_RX_GAIN_IP2INTC_IRPT_INTR -//#define ATTN_CTRL_INTR_ID XPAR_FABRIC_AXI_9731_TX_ATTN_IP2INTC_IRPT_INTR +/* Generate microseconds delay. */ +void udelay(uint32_t usecs); -#define GPIO_OFFSET 54 -#define AD9528_CS 1 -#define AD9371_CS 2 +/* Generate miliseconds delay. */ +void mdelay(uint32_t msecs); -#define TX_FREQ_INTR_MASK XGPIO_IR_CH1_MASK -#define RX_FREQ_INTR_MASK XGPIO_IR_CH2_MASK -#define TX1_ATTN_INTR_MASK XGPIO_IR_CH1_MASK -#define TX2_ATTN_INTR_MASK XGPIO_IR_CH2_MASK -#define RX1_ATTN_INTR_MASK XGPIO_IR_CH1_MASK -#define RX2_ATTN_INTR_MASK XGPIO_IR_CH2_MASK +/* Get current time */ +struct time get_time(void); -#define AXI_GPIO_BANK_1 1 -#define AXI_GPIO_BANK_2 2 - -//#define DAC_GPIO_PLDDR_BYPASS GPIO_OFFSET + 60 -#define AD9528_RESET_B GPIO_OFFSET + 4 -#define AD9528_SYSREF_REQ GPIO_OFFSET + 3 -#define AD9371_RESET_B GPIO_OFFSET + 1 - -#endif +#endif // _DELAY_H_ diff --git a/df_datalink_ge/src/include/error.h b/df_datalink_ge/src/include/error.h index 1e20199..5870a4e 100644 --- a/df_datalink_ge/src/include/error.h +++ b/df_datalink_ge/src/include/error.h @@ -1,19 +1,19 @@ /*****************************************************************************/ /** - * Description: Error code definitions. + * @file common.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Common error numbers + * @version 0.0 + * @date 2022-06-18 + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network * - * Author: Fan Hao - * Date: 2022-06-18 16:37 - * LastEditors: Fan Hao - * LastEditTime: 2022-06-18 17:12 - * Revisions: Rev 0.0 - * History: - * [2022-06-18]: Initial version. - * - * Copyright(c) 2022 Beijing Institute of Technology. - * Lab of Communication and Networking - * -******************************************************************************/ + ******************************************************************************/ + +/** + * @addtogroup COMMON_MACRO + * @{ + */ #ifndef SRC_ERROR_H_ #define SRC_ERROR_H_ @@ -24,6 +24,11 @@ /********************** Macros and Constants Definitions **********************/ /******************************************************************************/ +/** + * @name ERRORNO + * @{ + */ + #ifdef SUCCESS #undef SUCCESS #endif @@ -36,7 +41,7 @@ #define EPARAM -2 /*!< Data crc check failed */ #define ECRC -3 /*!< Data crc check failed */ #define EDINVAL -4 /*!< Device is invalid (sleep or power off) */ -#define EDCONF -5 /*!< Device confugure error */ +#define EDCONF -5 /*!< Device configure error */ #define ETIMEOUT -6 /*!< Timeout error */ #define EIGNORE -7 /*!< Received an unsupported command, and ignore it */ #define EQUEUE -8 /*!< Queue overflow */ @@ -45,3 +50,7 @@ #define IS_ERR_VALUE(x) ((x) != SUCCESS) #endif // ERROR_H_ + +/** @} ERRORNO*/ + +/** @} COMMON_MACRO*/ \ No newline at end of file diff --git a/df_datalink_ge/src/include/i2c.h b/df_datalink_ge/src/include/i2c.h new file mode 100644 index 0000000..86284cc --- /dev/null +++ b/df_datalink_ge/src/include/i2c.h @@ -0,0 +1,134 @@ +/***************************************************************************//** + * @file i2c.h + * @brief Header file of I2C Interface + * @author DBogdan (dragos.bogdan@analog.com) +******************************************************************************** + * Copyright 2019(c) Analog Devices, Inc. + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * - Neither the name of Analog Devices, Inc. nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * - The use of this software may or may not infringe the patent rights + * of one or more patent holders. This license does not release you + * from the requirement that you obtain separate licenses from these + * patent holders to use this software. + * - Use of the software either in source or binary form, must be run + * on or directly connected to an Analog Devices Inc. component. + * + * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*******************************************************************************/ + +#ifndef _I2C_H_ +#define _I2C_H_ + +/******************************************************************************/ +/***************************** Include Files **********************************/ +/******************************************************************************/ + +#include + +/******************************************************************************/ +/*************************** Types Declarations *******************************/ +/******************************************************************************/ + +/** + * @struct i2c_platform_ops + * @brief Structure holding I2C function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops ; + +/** + * @struct i2c_init_param + * @brief Structure holding the parameters for I2C initialization. + */ +struct i2c_init_param { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_desc + * @brief Structure holding I2C descriptor + */ +struct i2c_desc { + /** Device ID */ + uint32_t device_id; + /** I2C maximum transfer speed supported */ + uint32_t max_speed_hz; + /** Slave address */ + uint8_t slave_address; + /** I2C platform specific functions */ + const struct i2c_platform_ops *platform_ops; + /** I2C extra parameters (device specific parameters) */ + void *extra; +}; + +/** + * @struct i2c_platform_ops + * @brief Structure holding i2c function pointers that point to the platform + * specific function + */ +struct i2c_platform_ops { + /** i2c initialization function pointer */ + int32_t (*i2c_ops_init)(struct i2c_desc **, + const struct i2c_init_param *); + /** i2c write function pointer */ + int32_t (*i2c_ops_write)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c write function pointer */ + int32_t (*i2c_ops_read)(struct i2c_desc *, uint8_t *, uint8_t, uint8_t); + /** i2c remove function pointer */ + int32_t (*i2c_ops_remove)(struct i2c_desc *); +}; + +/******************************************************************************/ +/************************ Functions Declarations ******************************/ +/******************************************************************************/ + +/* Initialize the I2C communication peripheral. */ +int32_t i2c_init(struct i2c_desc **desc, + const struct i2c_init_param *param); + +/* Free the resources allocated by i2c_init(). */ +int32_t i2c_remove(struct i2c_desc *desc); + +/* Write data to a slave device. */ +int32_t i2c_write(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +/* Read data from a slave device. */ +int32_t i2c_read(struct i2c_desc *desc, + uint8_t *data, + uint8_t bytes_number, + uint8_t stop_bit); + +#endif // _I2C_H_ diff --git a/df_datalink_ge/src/hardware/platform_drivers.h b/df_datalink_ge/src/include/spi.h similarity index 52% rename from df_datalink_ge/src/hardware/platform_drivers.h rename to df_datalink_ge/src/include/spi.h index 5a744b9..26d0a84 100644 --- a/df_datalink_ge/src/hardware/platform_drivers.h +++ b/df_datalink_ge/src/include/spi.h @@ -1,9 +1,9 @@ /***************************************************************************//** - * @file platform_drivers.h - * @brief Header file of Xilinx Platform Drivers. + * @file spi.h + * @brief Header file of SPI Interface * @author DBogdan (dragos.bogdan@analog.com) ******************************************************************************** - * Copyright 2018(c) Analog Devices, Inc. + * Copyright 2019(c) Analog Devices, Inc. * * All rights reserved. * @@ -37,187 +37,173 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *******************************************************************************/ -#ifndef PLATFORM_DRIVERS_H_ -#define PLATFORM_DRIVERS_H_ +#ifndef _SPI_H_ +#define _SPI_H_ /******************************************************************************/ /***************************** Include Files **********************************/ /******************************************************************************/ + #include -#include -#ifdef _XPARAMETERS_PS_H_ -#include -#include -#else -#include -#include -#endif /******************************************************************************/ /********************** Macros and Constants Definitions **********************/ /******************************************************************************/ -#define SUCCESS 0 -#define FAILURE -1 - #define SPI_CPHA 0x01 #define SPI_CPOL 0x02 - -#define SPI_CS_DECODE 0x01 -#define SPI_CS_DECODE_DISABLE 0x00 - -#define GPIO_OUT 0x01 -#define GPIO_IN 0x00 - -#define GPIO_HIGH 0x01 -#define GPIO_LOW 0x00 +#define SPI_3WIRE 0x04 /******************************************************************************/ /*************************** Types Declarations *******************************/ /******************************************************************************/ -typedef enum i2c_type { - XILINX_I2C -} i2c_type; - -typedef struct i2c_init_param { - enum i2c_type type; - uint32_t id; - uint32_t max_speed_hz; - uint8_t slave_address; -} i2c_init_param; - -typedef struct i2c_desc { - enum i2c_type type; - uint32_t id; - uint32_t max_speed_hz; - uint8_t slave_address; -} i2c_desc; - -typedef enum spi_type { - XILINX_SPI -} spi_type; - /** * @enum spi_mode * @brief SPI configuration for clock phase and polarity. */ -typedef enum spi_mode { +enum spi_mode { /** Data on rising, shift out on falling */ SPI_MODE_0 = (0 | 0), /** Data on falling, shift out on rising */ SPI_MODE_1 = (0 | SPI_CPHA), - /** Data on falling, shift out on rising */ - SPI_MODE_2 = (SPI_CPOL | 0), /** Data on rising, shift out on falling */ - SPI_MODE_3 = (SPI_CPOL | SPI_CPHA) -} spi_mode; + SPI_MODE_2 = (SPI_CPOL | 0), + /** Data on falling, shift out on rising */ + SPI_MODE_3 = (SPI_CPOL | SPI_CPHA), + /** Data on rising, shift out on falling */ + SPI_MODE_4 = SPI_3WIRE +}; -typedef struct spi_init_param { - enum spi_type type; - uint32_t id; +/** + * @enum spi_bit_order + * @brief SPI configuration for bit order (MSB/LSB). + */ +enum spi_bit_order { + /** Most-significant bit (MSB) first */ + SPI_BIT_ORDER_MSB_FIRST = 0, + /** Least-significant bit (LSB) first */ + SPI_BIT_ORDER_LSB_FIRST = 1, +}; + +/** + * @struct spi_msg_list + * @brief List item describing a SPI transfer + */ +struct spi_msg { + /** Buffer with data to send. If NULL, 0x00 will be sent */ + uint8_t *tx_buff; + /** Buffer where to store data. If NULL, incoming data won't be saved */ + uint8_t *rx_buff; + /** Length of buffers. Must have equal size. */ + uint32_t bytes_number; + /** If set, CS will be deasserted after the transfer */ + uint8_t cs_change; + /** + * Minimum delay (in us) between the CS de-assert event of the current message + * and the assert of the next one. + */ + uint32_t cs_change_delay; + /** Delay (in us) between the CS assert and the first SCLK edge. */ + uint32_t cs_delay_first; + /** Delay (in us) between the last SCLK edge and the CS deassert */ + uint32_t cs_delay_last; +}; + +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops ; + +/** + * @struct spi_init_param + * @brief Structure holding the parameters for SPI initialization + */ +struct spi_init_param { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ uint32_t max_speed_hz; - enum spi_mode mode; + /** SPI chip select */ uint8_t chip_select; - uint32_t flags; -} spi_init_param; - -typedef struct spi_desc { - enum spi_type type; - uint32_t id; - uint32_t max_speed_hz; + /** SPI mode */ enum spi_mode mode; - uint8_t chip_select; - uint32_t flags; -#ifdef _XPARAMETERS_PS_H_ - XSpiPs_Config *config; - XSpiPs instance; -#else - XSpi instance; -#endif -} spi_desc; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; -typedef enum gpio_type { - XILINX_GPIO -} gpio_type; +/** + * @struct spi_desc + * @brief Structure holding SPI descriptor. + */ +struct spi_desc { + /** Device ID */ + uint32_t device_id; + /** maximum transfer speed */ + uint32_t max_speed_hz; + /** SPI chip select */ + uint8_t chip_select; + /** SPI mode */ + enum spi_mode mode; + /** SPI bit order */ + enum spi_bit_order bit_order; + const struct spi_platform_ops *platform_ops; + /** SPI extra parameters (device specific) */ + void *extra; + /** Parent of the device */ + struct spi_desc *parent; +}; -typedef struct gpio_desc { - enum gpio_type type; - uint32_t id; - uint8_t number; -#ifdef _XPARAMETERS_PS_H_ - XGpioPs_Config *config; - XGpioPs instance; -#else - XGpio instance; -#endif -} gpio_desc; +/** + * @struct spi_platform_ops + * @brief Structure holding SPI function pointers that point to the platform + * specific function + */ +struct spi_platform_ops { + /** SPI initialization function pointer */ + int32_t (*init)(struct spi_desc **, const struct spi_init_param *); + /** SPI write/read function pointer */ + int32_t (*write_and_read)(struct spi_desc *, uint8_t *, uint16_t); + /** SPI write function pointer */ + int32_t (*write_and_read_3wire)(struct spi_desc *, uint8_t *,uint8_t *,uint16_t, uint16_t); + /** Iterate over the spi_msg array and send all messages at once */ + int32_t (*transfer)(struct spi_desc *, struct spi_msg *, uint32_t); + /** SPI remove function pointer */ + int32_t (*remove)(struct spi_desc *); +}; /******************************************************************************/ /************************ Functions Declarations ******************************/ /******************************************************************************/ -/* Initialize the I2C communication peripheral. */ -int32_t i2c_init(struct i2c_desc **desc, - const struct i2c_init_param *param); - -/* Free the resources allocated by i2c_init(). */ -int32_t i2c_remove(struct i2c_desc *desc); - -/* Write data to a slave device. */ -int32_t i2c_write(struct i2c_desc *desc, - uint8_t *data, - uint8_t bytes_number, - uint8_t stop_bit); - -/* Read data from a slave device. */ -int32_t i2c_read(struct i2c_desc *desc, - uint8_t *data, - uint8_t bytes_number, - uint8_t stop_bit); - /* Initialize the SPI communication peripheral. */ int32_t spi_init(struct spi_desc **desc, - const struct spi_init_param *param); + const struct spi_init_param *param); -/* Free the resources allocated by spi_init() */ +/* Free the resources allocated by spi_init(). */ int32_t spi_remove(struct spi_desc *desc); /* Write and read data to/from SPI. */ int32_t spi_write_and_read(struct spi_desc *desc, - uint8_t *data, - uint8_t bytes_number); + uint8_t *data, + uint16_t bytes_number); +int32_t spi_write_and_read_3wire(struct spi_desc *desc, + uint8_t *write_data, + uint8_t *read_data, + uint16_t write_bytes_number, + uint16_t read_bytes_number); -/* Obtain the GPIO decriptor. */ -int32_t gpio_get(struct gpio_desc **desc, - uint8_t gpio_number); +/* Iterate over the spi_msg array and send all messages at once */ +int32_t spi_transfer(struct spi_desc *desc, + struct spi_msg *msgs, + uint32_t len); -/* Free the resources allocated by gpio_get() */ -int32_t gpio_remove(struct gpio_desc *desc); -/* Enable the input direction of the specified GPIO. */ -int32_t gpio_direction_input(struct gpio_desc *desc); - -/* Enable the output direction of the specified GPIO. */ -int32_t gpio_direction_output(struct gpio_desc *desc, - uint8_t value); - -/* Get the direction of the specified GPIO. */ -int32_t gpio_get_direction(struct gpio_desc *desc, - uint8_t *direction); - -/* Set the value of the specified GPIO. */ -int32_t gpio_set_value(struct gpio_desc *desc, - uint8_t value); - -/* Get the value of the specified GPIO. */ -int32_t gpio_get_value(struct gpio_desc *desc, - uint8_t *value); - -/* Generate microseconds delay. */ -void udelay(uint32_t usecs); - -/* Generate miliseconds delay. */ -void mdelay(uint32_t msecs); - -#endif // PLATFORM_DRIVERS_H_ +#endif // _SPI_H_ diff --git a/df_datalink_ge/src/include/util.h b/df_datalink_ge/src/include/util.h index a4a4608..d49aa84 100644 --- a/df_datalink_ge/src/include/util.h +++ b/df_datalink_ge/src/include/util.h @@ -1,41 +1,21 @@ -/******************************************************************************* - * @file util.h - * @brief Implementation of utility functions. - * @author DBogdan (dragos.bogdan@analog.com) -******************************************************************************** - * Copyright 2018(c) Analog Devices, Inc. +/*****************************************************************************/ +/** + * @file util.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief Utility functions header file + * @version 0.0 + * @date 2023-05-06 * - * All rights reserved. + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - Neither the name of Analog Devices, Inc. nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - The use of this software may or may not infringe the patent rights - * of one or more patent holders. This license does not release you - * from the requirement that you obtain separate licenses from these - * patent holders to use this software. - * - Use of the software either in source or binary form, must be run - * on or directly connected to an Analog Devices Inc. component. - * - * THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES "AS IS" AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, NON-INFRINGEMENT, - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL ANALOG DEVICES BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, INTELLECTUAL PROPERTY RIGHTS, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*******************************************************************************/ + ******************************************************************************/ + +/** + * @defgroup Utility + * @{ + */ + #ifndef __UTIL_H_ #define __UTIL_H_ @@ -91,6 +71,14 @@ #define round_up(x, y) \ (((x) + (y)-1) / (y)) +#ifdef __aarch64__ +#define NORMALIZE_SIZE(x) \ + (((x) + sizeof(uint64_t) - 1) & 0xFFFFFFFFFFFFFFF8) +#else +#define NORMALIZE_SIZE(x) \ + (((x) + sizeof(uint32_t) - 1) & 0xFFFFFFFC) +#endif + #define BITS_PER_LONG 32 #define GENMASK(h, l) ({ \ @@ -193,3 +181,5 @@ bool crc16_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_ int crc8_gen(uint8_t *buffPtr, uint32_t dataLen, uint16_t poly, uint8_t *crcVal); bool crc8_check(uint8_t *buffPtr, uint32_t dataLen, uint32_t crcOffset, uint16_t poly); #endif // __UTIL_H_ + +/** @} */ diff --git a/df_datalink_ge/src/lscript.ld b/df_datalink_ge/src/lscript.ld index 9ca5b4b..13606b7 100644 --- a/df_datalink_ge/src/lscript.ld +++ b/df_datalink_ge/src/lscript.ld @@ -2,35 +2,33 @@ /* */ /* This file is automatically generated by linker script generator.*/ /* */ -/* Version: 2019.1.3 */ +/* Version: 2018.3 */ /* */ -/* Copyright (c) 2010-2016 Xilinx, Inc. All rights reserved. */ +/* Copyright (c) 2010-2019 Xilinx, Inc. All rights reserved. */ /* */ -/* Description : Cortex-A9 Linker Script */ +/* Description : ARM v8 Linker Script */ /* */ /*******************************************************************/ -_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x40000; -_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x800000; +_STACK_SIZE = DEFINED(_STACK_SIZE) ? _STACK_SIZE : 0x800000; +_HEAP_SIZE = DEFINED(_HEAP_SIZE) ? _HEAP_SIZE : 0x20000; -_ABORT_STACK_SIZE = DEFINED(_ABORT_STACK_SIZE) ? _ABORT_STACK_SIZE : 1024; -_SUPERVISOR_STACK_SIZE = DEFINED(_SUPERVISOR_STACK_SIZE) ? _SUPERVISOR_STACK_SIZE : 2048; -_IRQ_STACK_SIZE = DEFINED(_IRQ_STACK_SIZE) ? _IRQ_STACK_SIZE : 1024; -_FIQ_STACK_SIZE = DEFINED(_FIQ_STACK_SIZE) ? _FIQ_STACK_SIZE : 1024; -_UNDEF_STACK_SIZE = DEFINED(_UNDEF_STACK_SIZE) ? _UNDEF_STACK_SIZE : 1024; +_EL0_STACK_SIZE = DEFINED(_EL0_STACK_SIZE) ? _EL0_STACK_SIZE : 1024; +_EL1_STACK_SIZE = DEFINED(_EL1_STACK_SIZE) ? _EL1_STACK_SIZE : 2048; +_EL2_STACK_SIZE = DEFINED(_EL2_STACK_SIZE) ? _EL2_STACK_SIZE : 1024; /* Define Memories in the system */ MEMORY { - phy_data_interface_tx_frame_bram_ctrl_Mem0 : ORIGIN = 0x40000000, LENGTH = 0x2000 - phy_data_interface_ant_info_bram_ctrl_Mem0 : ORIGIN = 0x42000000, LENGTH = 0x2000 - mpc_bram_interface_mpc_bram_ctrl_Mem0 : ORIGIN = 0x44000000, LENGTH = 0x8000 - phy_data_interface_rx_frame_bram_ctrl_Mem0 : ORIGIN = 0x46000000, LENGTH = 0x2000 - ps7_ddr_0 : ORIGIN = 0x100000, LENGTH = 0x1FF00000 - ps7_qspi_linear_0 : ORIGIN = 0xFC000000, LENGTH = 0x1000000 - ps7_ram_0 : ORIGIN = 0x0, LENGTH = 0x30000 - ps7_ram_1 : ORIGIN = 0xFFFF0000, LENGTH = 0xFE00 + phy_data_interface_ant_beam_bram_ctrl_Mem0 : ORIGIN = 0x82000000, LENGTH = 0x1000 + phy_data_interface_ant_config_bram_ctrl_Mem0 : ORIGIN = 0x84000000, LENGTH = 0x2000 + phy_data_interface_rx_frame_bram_ctrl_Mem0 : ORIGIN = 0x86000000, LENGTH = 0x1000 + phy_data_interface_tx_frame_bram_ctrl_Mem0 : ORIGIN = 0x88000000, LENGTH = 0x1000 + psu_ddr_0_MEM_0 : ORIGIN = 0x0, LENGTH = 0x7FF00000 + psu_ddr_1_MEM_0 : ORIGIN = 0x800000000, LENGTH = 0x80000000 + psu_ocm_ram_0_MEM_0 : ORIGIN = 0xFFFC0000, LENGTH = 0x40000 + psu_qspi_linear_0_MEM_0 : ORIGIN = 0xC0000000, LENGTH = 0x20000000 } /* Specify the default entry point to the program */ @@ -42,6 +40,7 @@ ENTRY(_vector_table) SECTIONS { .text : { + . = ALIGN(2048); KEEP (*(.vectors)) *(.boot) *(.text) @@ -52,51 +51,63 @@ SECTIONS *(.gcc_execpt_table) *(.glue_7) *(.glue_7t) - *(.vfp11_veneer) *(.ARM.extab) *(.gnu.linkonce.armextab.*) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 -.init : { +.init (ALIGN(64)) : { KEEP (*(.init)) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 -.fini : { +.fini (ALIGN(64)) : { KEEP (*(.fini)) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 + +.interp : { + KEEP (*(.interp)) +} > psu_ddr_0_MEM_0 + +.note-ABI-tag : { + KEEP (*(.note-ABI-tag)) +} > psu_ddr_0_MEM_0 .rodata : { + . = ALIGN(64); __rodata_start = .; *(.rodata) *(.rodata.*) *(.gnu.linkonce.r.*) __rodata_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .rodata1 : { + . = ALIGN(64); __rodata1_start = .; *(.rodata1) *(.rodata1.*) __rodata1_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .sdata2 : { + . = ALIGN(64); __sdata2_start = .; *(.sdata2) *(.sdata2.*) *(.gnu.linkonce.s2.*) __sdata2_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .sbss2 : { + . = ALIGN(64); __sbss2_start = .; *(.sbss2) *(.sbss2.*) *(.gnu.linkonce.sb2.*) __sbss2_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .data : { + . = ALIGN(64); __data_start = .; *(.data) *(.data.*) @@ -105,20 +116,34 @@ SECTIONS *(.got) *(.got.plt) __data_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .data1 : { + . = ALIGN(64); __data1_start = .; *(.data1) *(.data1.*) __data1_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .got : { *(.got) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 + +.got1 : { + *(.got1) +} > psu_ddr_0_MEM_0 + +.got2 : { + *(.got2) +} > psu_ddr_0_MEM_0 + +.note.gnu.build-id : { + KEEP (*(.note.gnu.build-id)) +} > psu_ddr_0_MEM_0 .ctors : { + . = ALIGN(64); __CTOR_LIST__ = .; ___CTORS_LIST___ = .; KEEP (*crtbegin.o(.ctors)) @@ -127,9 +152,10 @@ SECTIONS KEEP (*(.ctors)) __CTOR_END__ = .; ___CTORS_END___ = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .dtors : { + . = ALIGN(64); __DTOR_LIST__ = .; ___DTORS_LIST___ = .; KEEP (*crtbegin.o(.dtors)) @@ -138,108 +164,130 @@ SECTIONS KEEP (*(.dtors)) __DTOR_END__ = .; ___DTORS_END___ = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .fixup : { __fixup_start = .; *(.fixup) __fixup_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .eh_frame : { *(.eh_frame) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .eh_framehdr : { __eh_framehdr_start = .; *(.eh_framehdr) __eh_framehdr_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .gcc_except_table : { *(.gcc_except_table) -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 -.mmu_tbl (ALIGN(16384)) : { - __mmu_tbl_start = .; - *(.mmu_tbl) - __mmu_tbl_end = .; -} > ps7_ddr_0 +.mmu_tbl0 (ALIGN(4096)) : { + __mmu_tbl0_start = .; + *(.mmu_tbl0) + __mmu_tbl0_end = .; +} > psu_ddr_0_MEM_0 + +.mmu_tbl1 (ALIGN(4096)) : { + __mmu_tbl1_start = .; + *(.mmu_tbl1) + __mmu_tbl1_end = .; +} > psu_ddr_0_MEM_0 + +.mmu_tbl2 (ALIGN(4096)) : { + __mmu_tbl2_start = .; + *(.mmu_tbl2) + __mmu_tbl2_end = .; +} > psu_ddr_0_MEM_0 .ARM.exidx : { __exidx_start = .; *(.ARM.exidx*) *(.gnu.linkonce.armexidix.*.*) __exidx_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .preinit_array : { + . = ALIGN(64); __preinit_array_start = .; KEEP (*(SORT(.preinit_array.*))) KEEP (*(.preinit_array)) __preinit_array_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .init_array : { + . = ALIGN(64); __init_array_start = .; KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array)) __init_array_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .fini_array : { + . = ALIGN(64); __fini_array_start = .; KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array)) __fini_array_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .ARM.attributes : { __ARM.attributes_start = .; *(.ARM.attributes) __ARM.attributes_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .sdata : { + . = ALIGN(64); __sdata_start = .; *(.sdata) *(.sdata.*) *(.gnu.linkonce.s.*) __sdata_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .sbss (NOLOAD) : { + . = ALIGN(64); __sbss_start = .; *(.sbss) *(.sbss.*) *(.gnu.linkonce.sb.*) + . = ALIGN(64); __sbss_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .tdata : { + . = ALIGN(64); __tdata_start = .; *(.tdata) *(.tdata.*) *(.gnu.linkonce.td.*) __tdata_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .tbss : { + . = ALIGN(64); __tbss_start = .; *(.tbss) *(.tbss.*) *(.gnu.linkonce.tb.*) __tbss_end = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .bss (NOLOAD) : { - __bss_start = .; + . = ALIGN(64); + __bss_start__ = .; *(.bss) *(.bss.*) *(.gnu.linkonce.b.*) *(COMMON) - __bss_end = .; -} > ps7_ddr_0 + . = ALIGN(64); + __bss_end__ = .; +} > psu_ddr_0_MEM_0 _SDA_BASE_ = __sdata_start + ((__sbss_end - __sdata_start) / 2 ); @@ -248,44 +296,33 @@ _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2 ); /* Generate Stack and Heap definitions */ .heap (NOLOAD) : { - . = ALIGN(16); + . = ALIGN(64); _heap = .; HeapBase = .; _heap_start = .; . += _HEAP_SIZE; _heap_end = .; HeapLimit = .; -} > ps7_ddr_0 +} > psu_ddr_0_MEM_0 .stack (NOLOAD) : { - . = ALIGN(16); - _stack_end = .; + . = ALIGN(64); + _el3_stack_end = .; . += _STACK_SIZE; - . = ALIGN(16); - _stack = .; - __stack = _stack; - . = ALIGN(16); - _irq_stack_end = .; - . += _IRQ_STACK_SIZE; - . = ALIGN(16); - __irq_stack = .; - _supervisor_stack_end = .; - . += _SUPERVISOR_STACK_SIZE; - . = ALIGN(16); - __supervisor_stack = .; - _abort_stack_end = .; - . += _ABORT_STACK_SIZE; - . = ALIGN(16); - __abort_stack = .; - _fiq_stack_end = .; - . += _FIQ_STACK_SIZE; - . = ALIGN(16); - __fiq_stack = .; - _undef_stack_end = .; - . += _UNDEF_STACK_SIZE; - . = ALIGN(16); - __undef_stack = .; -} > ps7_ddr_0 + __el3_stack = .; + _el2_stack_end = .; + . += _EL2_STACK_SIZE; + . = ALIGN(64); + __el2_stack = .; + _el1_stack_end = .; + . += _EL1_STACK_SIZE; + . = ALIGN(64); + __el1_stack = .; + _el0_stack_end = .; + . += _EL0_STACK_SIZE; + . = ALIGN(64); + __el0_stack = .; +} > psu_ddr_0_MEM_0 _end = .; } diff --git a/df_datalink_ge/src/main.c b/df_datalink_ge/src/main.c index cfd2b25..2f7569e 100644 --- a/df_datalink_ge/src/main.c +++ b/df_datalink_ge/src/main.c @@ -3,17 +3,14 @@ * Description: main.c * - * Date: 2021-11-13 13:19 - * Last Editors: Fan Hao - * Last Edit Time: [2022-03-28 20:32] + * Date: 2023-05-07 13:19 + * Last Edit Time: [2023-05-07 20:32] * * Revisions: Rev 0.0 * History: - * [2021-11-13]: Initial edition. - * [2022-03-28]: Add bit error test mode. + * [2023-05-07]: Initial edition. * - * Copyright(c) 2021 Beijing Institute of Technology. - * Lab of Communication and Networking + * Copyright(c) 2024 Beijing Institute of Technology. * ******************************************************************************/ @@ -23,163 +20,138 @@ #include #include // Xilinx -#include "sleep.h" -#include "xil_cache.h" #include "xscugic.h" -#include "xscutimer.h" -#include "xgpiops.h" #include "drivers/platform/xilinx_irq.h" #include "drivers/platform/xilinx_timer.h" // App #include "common.h" #include "error.h" #include "timer.h" +#include "hwconfig.h" +#include "system_monitor.h" #include "config/app_config.h" #include "dev_profile/dev_profile.h" -#include "mpc/mpc.h" +#include "systembus/systembus.h" #include "networking/phy_layer/phy_layer.h" #include "networking/link_layer/link_layer.h" -// RF-Driver -#include "hardware/headless.h" -#include "hardware/platform_drivers.h" + +#ifdef HSJL_GE +#include +#endif /************************** Function Prototypes ******************************/ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr); void Phy_IntrHandler(void *context); -void PeriodicPoll_Handler(void *callBackRef); -void ScuTimer_IntrHandler(void *context); -void Mpc_RxIntrHandler(void *context); -void Mpc_TxIntrHandler(void *context); +void PeriodicPull_Handler(void *callBackRef); +void AppTimer_IntrHandler(void *context); +void Systembus_RxIntrHandler(void *context); +void Systembus_TxIntrHandler(void *context); + /************************** Constant Definitions *****************************/ -struct callback_desc phy_callback_desc = -{ +struct callback_desc phy_callback_desc = { .callback = Phy_IntrHandler, .ctx = NULL }; -struct callback_desc periodicpoll_callback_desc = -{ - .callback = PeriodicPoll_Handler, +struct callback_desc periodicpull_callback_desc = { + .callback = PeriodicPull_Handler, .ctx = NULL }; -struct callback_desc mpc_rx_callback_desc = -{ - .callback = Mpc_RxIntrHandler, +struct callback_desc sysbus_rx_callback_desc = { + .callback = Systembus_RxIntrHandler, .ctx = NULL }; -struct callback_desc mpc_tx_callback_desc = -{ - .callback = Mpc_TxIntrHandler, +struct callback_desc sysbus_tx_callback_desc = { + .callback = Systembus_TxIntrHandler, .ctx = NULL }; -struct callback_desc scutm_callback_desc = -{ - .callback = ScuTimer_IntrHandler, +struct callback_desc apptimer_callback_desc = { + .callback = AppTimer_IntrHandler, .ctx = NULL }; -L2_CONFIG linkConfig = -{ - .myType = L2_NODE_HEAD, +//L2_CONFIG linkConfig = { +// .myType = L2_NODE_HEAD, +// .clustId = 1, +// .myId = 1, +// .headId = 1, +// .netScale = 3, +// .phyInstPtr = NULL, // physical layer reference +// .tmcInstPtr = NULL +//}; + +L2_CONFIG linkConfig = { + .myType = L2_NODE_MEMBER, .clustId = 1, - .myId = 1, + .myId = 2, .headId = 1, .netScale = 10, - .serviceRate = L2_SVC_128K, .phyInstPtr = NULL, // physical layer reference .tmcInstPtr = NULL }; -// L2_CONFIG linkConfig = { -// .myType = L2_NODE_MEMBER, -// .clustId = 1, -// .myId = 2, -// .headId = 1, -// .netScale = 2, -// .phyInstPtr = NULL, // physical layer reference -// .tmcInstPtr = NULL -// }; - -static PHY_CONFIG phyConfig = -{ - .devId = 0, +static PHY_CONFIG phyConfig = { + .devId = PHY_DEVICE_ID, .baseAddr = PHY_BASEADDR, .antBramId = PHY_ANTCONFIG_BRAM_DEVICE_ID, - .antInfoBramId = -1, .txBramId = PHY_TXBUFF_BRAM_DEVICE_ID, .rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID, - .hwXadcId = PHY_HW_XADC_DEVICE_ID, + .hwSysmonId = PHY_HW_SYSMON_DEVICE_ID, .get_clk_state = NULL, .get_ad_lock_state = NULL, .get_ad0_temp = NULL, .get_ad1_temp = NULL }; -TMC_CONFIG tmcConfig = -{ +TMC_CONFIG tmcConfig = { .baseAddr = TIME_CONTROLLER_BASEADDR, .reset = 10 }; -static MPC_CONFIG mpcConfig = { - .bramId = MPC_BRAM_ID, - .gpioId = MPC_GPIO_ID, +static SYSBUS_CONFIG sysbusConfig = { + .baseAddr = SYSBUS_BASE_ADDR, .txQueueMax = 16, .rxQueueMax = 16 }; - -#ifdef APP_EMULATE_DATA -uint8_t testDataLj[] = -{ - 0xEA, 0xDF, 0x3F, 0x27, 0xCE, 0x9B, 0xE6, 0x3F, - 0xB5, 0xA3, 0x38, 0x47, 0x1D, 0x1D, 0xFA, 0x3F, - 0x39, 0xB4, 0xC8, 0x76, 0xBE, 0xAB, 0x8E, 0x40, - 0xC9, 0xE8, 0x80, 0x24, 0xEC, 0xCB, 0x13, 0x40, - 0x37, 0x38, 0x7F, 0x22, 0x72, 0x06, 0xF0, 0x01, - 0x00, 0x00, 0xB8, 0xAA, 0x08, 0x47, 0x1E, 0xC6, - 0xB0, 0x47, 0x54, 0xFD, 0xEB, 0x45, 0xA1, 0x8A, - 0x86, 0x44, 0x43, 0xB6, 0xC8, 0x44, 0x4E, 0x19, - 0xA8, 0x42 -}; - -uint8_t testDataFlj[] = -{ - 0xFD, 0x1E, 0xA5, 0x22, 0x72, 0x02, 0x5A, 0x02, - 0x00, 0x00, 0x81, 0x97, 0x39, 0x3F, 0xF1, 0xF4, - 0xC0, 0x3F, 0x27, 0xF1, 0x65, 0x44, 0x53, 0x5C, - 0xD3, 0x3F, 0xB5, 0x24, 0xA6, 0x22, 0x72, 0x02, - 0x83, 0x01, 0x00, 0x00, 0xFC, 0xE0, 0x44, 0x47, - 0xB7, 0x83, 0x35, 0x47, 0xA4, 0xBF, 0xE5, 0xC4, - 0xE8, 0xDC, 0xD1, 0x44, 0x5D, 0x5D, 0xE7, 0x44, - 0x7D, 0x1B, 0xE8, 0xC1, 0x60, 0x97, 0x57, 0x42, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x5D, 0x86, 0xA6, 0x22, 0x72, 0x02, 0xA5, 0x02, - 0x00, 0x00, 0x97, 0x4E, 0xB5, 0x47, 0xC4, 0x2A, - 0xB0, 0x47, 0x2D, 0x00, 0x21, 0xC5, 0x8A, 0x85, - 0xD1, 0x44, 0x23, 0xFD, 0xC8, 0x44, 0xA1, 0xC4, - 0xEA, 0xC1, 0x91, 0x4E, 0x71, 0xC2, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6D, 0xAD, - 0xA6, 0x22, 0x72, 0x02, 0xA5, 0x02, 0x00, 0x00, - 0xCD, 0x07, 0xD6, 0x47, 0x1D, 0xA4, 0xCE, 0x47, - 0x6E, 0x61, 0x33, 0xC5, 0x85, 0x55, 0xD1, 0x44, - 0x9C, 0x16, 0xBD, 0x44, 0x36, 0xC0, 0xEB, 0xC1, - 0xF0, 0xFF, 0x5B, 0x42, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x78, 0x25, 0x03, 0x00 -}; -#endif - -/************************** Function Prototypes ******************************/ +/*********************** Driver Instance Definitions **************************/ static struct irq_ctrl_desc *intcDescPtr; // General interrupt controller descriptor static struct timer_desc *logTmPtr; -static MPC *mpcDescPtr; +static SYSBUS *sysbusDescPtr; static PHY_INST *phyInstPtr; static TMC_INST *tmcInstPtr = NULL; L2_INST *linkInstPtr; +#ifdef HSJL_GE +void MetalLogHandler(enum metal_log_level level, const char *format, ...) +{ + char msg[1024]; + va_list args; + static const char * const level_strs[] = { + "metal: emergency: ", + "metal: alert: ", + "metal: critical: ", + "metal: error: ", + "metal: warning: ", + "metal: notice: ", + "metal: info: ", + "metal: debug: ", + }; + + va_start(args, format); + vsnprintf(msg, sizeof(msg), format, args); + va_end(args); + + if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG) + level = METAL_LOG_EMERGENCY; + + printf("%s%s", level_strs[level], msg); +} +#endif + /****************************************************************************/ /** * This function is responsible for initializing the SCUGIC instance, looking @@ -247,7 +219,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) return Status; } // Connect the interrupt service routine isr1 to the interrupt controller - Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpoll_callback_desc); + Status = irq_register_callback(descPtr, PERIODIC_5MS_INTR_ID, &periodicpull_callback_desc); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); @@ -255,14 +227,14 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) } /* Initialize system bus interrupt. */ - Status = irq_trigger_level_set(descPtr, MPC_TX_INTR_ID, IRQ_EDGE_RISING); + Status = irq_trigger_level_set(descPtr, SYSBUS_TX_INTR_ID, IRQ_EDGE_RISING); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } // Set interrupt priority - Status = irq_set_priority(descPtr, MPC_TX_INTR_ID, 0x10); + Status = irq_set_priority(descPtr, SYSBUS_TX_INTR_ID, 0x10); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); @@ -270,20 +242,20 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) } // Connect the interrupt service routine isr1 to the interrupt controller - Status = irq_register_callback(descPtr, MPC_TX_INTR_ID, &mpc_tx_callback_desc); + Status = irq_register_callback(descPtr, SYSBUS_TX_INTR_ID, &sysbus_tx_callback_desc); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } - Status = irq_trigger_level_set(descPtr, MPC_RX_INTR_ID, IRQ_EDGE_RISING); + Status = irq_trigger_level_set(descPtr, SYSBUS_RX_INTR_ID, IRQ_EDGE_RISING); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR trigger level set FAILED, ErrorCode: %" PRId32 ".\n", Status); return Status; } // Set interrupt priority - Status = irq_set_priority(descPtr, MPC_RX_INTR_ID, 0x18); + Status = irq_set_priority(descPtr, SYSBUS_RX_INTR_ID, 0x18); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR priority level set FAILED, ErrorCode: %" PRId32 ".\n", Status); @@ -291,7 +263,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) } // Connect the interrupt service routine isr1 to the interrupt controller - Status = irq_register_callback(descPtr, MPC_RX_INTR_ID, &mpc_rx_callback_desc); + Status = irq_register_callback(descPtr, SYSBUS_RX_INTR_ID, &sysbus_rx_callback_desc); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); @@ -300,7 +272,7 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) /* Initialize Scu timer interrupt. */ // Connect the interrupt service routine isr1 to the interrupt controller - Status = irq_register_callback(descPtr, SCUTIMER_INTR_ID, &scutm_callback_desc); + Status = irq_register_callback(descPtr, APPTIMER_INTR_ID, &apptimer_callback_desc); if (Status != SUCCESS) { DBG_ERROR("PHY_INTR register callback FAILED, ErrorCode: %" PRId32 ".\n", Status); @@ -310,9 +282,9 @@ int32_t SetupInterruptSystem(struct irq_ctrl_desc *descPtr) // Enable interrupts irq_enable(descPtr, PHY_INTR_ID); irq_enable(descPtr, PERIODIC_5MS_INTR_ID); - irq_enable(descPtr, MPC_RX_INTR_ID); - irq_enable(descPtr, MPC_TX_INTR_ID); - irq_enable(descPtr, SCUTIMER_INTR_ID); + irq_enable(descPtr, SYSBUS_RX_INTR_ID); + irq_enable(descPtr, SYSBUS_TX_INTR_ID); + irq_enable(descPtr, APPTIMER_INTR_ID); // Enable Exceptions Status = irq_global_enable(descPtr); @@ -342,14 +314,14 @@ void Phy_IntrHandler(void *context) /****************************************************************************/ /** - * Handler of periodic 2 ms interrupt + * Handler of periodic 5ms interrupt * * @param callBackRef is the linklayer instance pointer. * * @return None. * *****************************************************************************/ -void PeriodicPoll_Handler(void *callBackRef) +void PeriodicPull_Handler(void *callBackRef) { int32_t Status; Status = Linklayer_Proc(linkInstPtr); @@ -358,7 +330,7 @@ void PeriodicPoll_Handler(void *callBackRef) DBG_ERROR("Link layer runs failed, with error code: %" PRId32 "\n", Status); _nop_(); } -} // PeriodicPoll_Handler +} // PeriodicPull_Handler /*****************************************************************************/ /** @@ -369,13 +341,13 @@ void PeriodicPoll_Handler(void *callBackRef) * @return None. * ******************************************************************************/ -void Mpc_RxIntrHandler(void *context) +void Systembus_RxIntrHandler(void *context) { int32_t Status; - Status = Mpc_RxIrqHandler(mpcDescPtr); + Status = SystemBus_RxIntrHandler(sysbusDescPtr); if (Status != SUCCESS) { - DBG_ERROR("Mpc_RxIrqHandler exit with error code %" PRId32 ",\n", Status); + DBG_ERROR("SystemBus_RxIntrHandler exit with error code %" PRId32 ",\n", Status); } } @@ -388,29 +360,30 @@ void Mpc_RxIntrHandler(void *context) * @return None. * ******************************************************************************/ -void Mpc_TxIntrHandler(void *context) +void Systembus_TxIntrHandler(void *context) { int32_t Status; - Status = Mpc_TxIrqHandler(mpcDescPtr); + Status = SystemBus_TxIntrHandler(sysbusDescPtr); if (Status != SUCCESS) { - DBG_ERROR("Mpc_TxIrqHandler exit with error code %" PRId32 ",\n", Status); + DBG_ERROR("SystemBus_TxIntrHandler exit with error code %" PRId32 ",\n", Status); } } /*****************************************************************************/ /** - * @brief Handler of ScuTimer interrupt. + * @brief Handler of AppTimer interrupt. * * @param context * * @return None. * ******************************************************************************/ -void ScuTimer_IntrHandler(void *context) +void AppTimer_IntrHandler(void *context) { struct xil_timer_desc *xdesc; xdesc = (struct xil_timer_desc *)(logTmPtr->extra); +#ifdef XPAR_XSCUTIMER_NUM_INSTANCES if (XScuTimer_IsExpired((XScuTimer *)xdesc->instance)) { // Refresh log @@ -420,29 +393,27 @@ void ScuTimer_IntrHandler(void *context) Phy_UpdateLogging(phyInstPtr); } - if (Mpc_IsEnable(mpcDescPtr)) - { - if (Mpc_PendRemoteTest(mpcDescPtr) != SUCCESS) - { - DBG_ERROR("Failed to apply remote test.\n"); - } -#ifdef APP_EMULATE_DATA - if (L2_GetNodeType(linkInstPtr) == L2_NODE_HEAD) - { - SysMonitor_UpdateSendPayload(testDataFlj, PAYLOAD_LEN_FLJ_TX); - } - else - { - SysMonitor_UpdateSendPayload(testDataLj, PAYLOAD_LEN_LJ_TX); - } -#endif - } - XScuTimer_ClearInterruptStatus((XScuTimer *)xdesc->instance); } +#elif defined(XPAR_XTMRCTR_NUM_INSTANCES) + if (XTmrCtr_IsExpired((XTmrCtr *)xdesc->instance, 0)) + { + // Refresh log + Phy_RefreshHwSate(phyInstPtr); + if (TimeCtrl_GetIntCnt(tmcInstPtr) - phyInstPtr->lastLogTime >= PHY_LOG_EXPIRE) + { + Phy_UpdateLogging(phyInstPtr); + } + + XTmrCtr_WriteReg(((XTmrCtr *)xdesc->instance)->BaseAddress, 0, + XTC_TCSR_OFFSET, XTC_CSR_INT_OCCURED_MASK); + } +#else +#error No timer implementation! +#endif else { - DBG_WARNING("UNEXPECTED CALL of ScuTimer_IntrHandler\n"); + DBG_WARNING("UNEXPECTED CALL of AppTimer_IntrHandler\n"); } } @@ -451,13 +422,18 @@ void ScuTimer_IntrHandler(void *context) * @brief Main function, initialize all the device needed, initialize * interrupt system, halt in while(1) wait for event interrupt. * - * @param None. + * @param none. * * @return * ******************************************************************************/ int main(void) { + #ifdef HSJL_GE + metal_set_log_handler(MetalLogHandler); + metal_set_log_level(METAL_LOG_DEBUG); + #endif + int32_t Status; DBG_PRINT("Application Version: %2d.%2d.%4d.\n", _APP_VER_MAIN, _APP_VER_MINOR, _APP_VER_PATCH); @@ -473,7 +449,8 @@ int main(void) return Status; } - Status = HARDWARE_initialize(); + /* Hardware Initialize */ + Status = Hardware_Init(); if (Status == SUCCESS) { DBG_PRINT("Hardware Init SUCCESS! \n"); @@ -484,7 +461,7 @@ int main(void) return Status; } - // Init time controller + /* Time controller Initialize */ Status = TimeCtrl_Init(&tmcInstPtr, &tmcConfig); if (Status == SUCCESS) { @@ -523,18 +500,18 @@ int main(void) } /* System Bus Initialize */ - Status = Mpc_Init(&mpcDescPtr, &mpcConfig); + Status = SystemBus_Init(&sysbusDescPtr, &sysbusConfig); if (Status != SUCCESS) { - DBG_ERROR("MPC init FAILED, with error code: %" PRId32 "\n", Status); - return Status; + DBG_ERROR("Systembus init FAILED, with error code: %" PRId32 "\n", Status); + return Status; } /* System Monitor log timer Initialize */ - Status = timer_init(&logTmPtr, &scutimer_init_param); + Status = timer_init(&logTmPtr, &apptimer_init_param); if (Status != SUCCESS) { - DBG_ERROR("SCU Timer init FAILED, with error code: %" PRId32 "\n", Status); + DBG_ERROR("APP Timer init FAILED, with error code: %" PRId32 "\n", Status); return Status; } @@ -558,22 +535,22 @@ int main(void) while (true) { - // System bus handler - if (Mpc_IsReqPending(mpcDescPtr)) - { - Status = Mpc_HandleCmd(mpcDescPtr); - if (Status != SUCCESS) + // System bus handler + if (SystemBus_IsReqPending(sysbusDescPtr)) { - DBG_ERROR("Mpc_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); + Status = SystemBus_HandleCmd(sysbusDescPtr); + if (Status != SUCCESS) + { + DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); + } } - } - if (Mpc_IsRsqPending(mpcDescPtr) && (!Mpc_IsTxBusy(mpcDescPtr))) - { - Status = Mpc_MakeResp(mpcDescPtr); - if (Status != SUCCESS) + if (SystemBus_IsRsqPending(sysbusDescPtr) && (!SystemBus_IsTxBusy(sysbusDescPtr))) { - DBG_ERROR("Mpc_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); + Status = SystemBus_MakeResp(sysbusDescPtr); + if (Status != SUCCESS) + { + DBG_ERROR("SystemBus_HandleCmd exit with ErrorCode: %" PRId32 ".\n", Status); + } } } - } } // main diff --git a/df_datalink_ge/src/system_monitor.c b/df_datalink_ge/src/system_monitor.c index d8d8d8a..fb8193e 120000 --- a/df_datalink_ge/src/system_monitor.c +++ b/df_datalink_ge/src/system_monitor.c @@ -1 +1,408 @@ -../../df_datalink_sp/src/system_monitor.c \ No newline at end of file +/** + * @addtogroup SystemMonitor + * @{ + */ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include "common.h" +#include "system_monitor.h" +/************************** Constant Definitions *****************************/ +/** + * @name SystemMonitor_Private_Constants + * @{ + */ +#define BUFF_A 0x00 +#define BUFF_B 0x01 +#define BUFF_NONE 0xFF + +#define SYSINFO_PACK_LEN 54 // bytes +#define PAYLOAD_PACK_LEN 46 // bytes +#define SLOTLOG_PACK_LEN 88 // bytes +#define PRTCLLOG_PACK_ELN 24 // bytes +#define HWSTATE_PACK_ELN 12 // bytes +/** @} SystemMonitor_Private_Constants*/ +/************************** Data Type Definitions ****************************/ +/** + * @struct PINGPONG + * @brief PingPing Control + */ +typedef struct +{ + uint8_t latest; ///< latest available index + uint8_t rBusy; ///< current read busy index + uint8_t wBusy; ///< current write busy index +} PINGPONG; + +/** + * @struct SYSMONITOR + * @brief System Monitor struct holds all the system log info + */ +typedef struct +{ + PINGPONG recvCtrl; + PAYLOAD recv[2]; + PINGPONG sendCtrl; + PAYLOAD send[2]; + PINGPONG sysInfoCtrl; + SYSINFO sysInfo[2]; + PINGPONG linkLogCtrl; + LINKLOG linkLog[2]; + PINGPONG phyLogCtrl; + PHYLOG phyLog[2]; + PINGPONG hwStateCtrl; + HWSTATE hwState[2]; +} SYSMONITOR; + +/************************** Function Prototypes ******************************/ +static uint8_t GetWritable(PINGPONG ctrllor); +static uint8_t GetReadable(PINGPONG ctrllor); +/************************** Variable Definitions *****************************/ +static SYSMONITOR *sysMonitorInst; + +/*********************** Function Implementations ***************************/ +inline static uint8_t GetWritable(PINGPONG ctrllor) +{ + // Allow only one write. + ASSERT(ctrllor.wBusy == BUFF_NONE); + if (ctrllor.rBusy == BUFF_NONE) + return ((ctrllor.latest == BUFF_B) ? BUFF_A : BUFF_B); + else + return ((ctrllor.rBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +inline static uint8_t GetReadable(PINGPONG ctrllor) +{ + if (ctrllor.wBusy == BUFF_NONE || ctrllor.wBusy != ctrllor.latest) + return ((ctrllor.latest == BUFF_NONE) ? BUFF_A : BUFF_B); + else + return ((ctrllor.wBusy == BUFF_B) ? BUFF_A : BUFF_B); +} + +/** + * @brief Initialize System monitor + * + * @return SUCCESS + */ +int32_t SysMonitor_Init(void) +{ + sysMonitorInst = calloc(1, sizeof(SYSMONITOR)); + if (sysMonitorInst == NULL) + { + return ENOMEM; + } + memset(&(sysMonitorInst->recvCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sendCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->sysInfoCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->linkLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->phyLogCtrl), BUFF_NONE, sizeof(PINGPONG)); + memset(&(sysMonitorInst->hwStateCtrl), BUFF_NONE, sizeof(PINGPONG)); + + sysMonitorInst->recv[0].dataId = DATA_ID_NONE; + sysMonitorInst->recv[1].dataId = DATA_ID_NONE; + sysMonitorInst->send[0].dataId = DATA_ID_NONE; + sysMonitorInst->send[1].dataId = DATA_ID_NONE; + return SUCCESS; +} + +/** + * @brief Destroy system monitor release all allocated memory + */ +void SysMonitor_Destroy(void) +{ + free(sysMonitorInst); +} + +/** + * @name SystemInfo_API + * @{ + */ + +/** + * @brief Update system info. + * + * @param info + */ +void SysMonitor_UpdateSysinfo(const SYSINFO *info) +{ + ASSERT(info != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->sysInfo[buffIndx]), info, sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.latest = buffIndx; + sysMonitorInst->sysInfoCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get system info. + * + * @param info + */ +void SysMonitor_GetSysinfo(SYSINFO *info) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(info != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sysInfoCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->sysInfoCtrl); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndx; + memcpy(info, &(sysMonitorInst->sysInfo[buffIndx]), sizeof(SYSINFO)); + sysMonitorInst->sysInfoCtrl.rBusy = buffIndex_old; +} +/** @} SystemInfo_API*/ + +/** + * @name ServicePayload_API + * @{ + */ + +/** + * @brief Update send payload by + * + * @param buff + * @param len + */ +void SysMonitor_UpdateSendPayload(const uint8_t *buff, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->sendCtrl); + sysMonitorInst->sendCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->send[buffIndx].data, buff, len); + sysMonitorInst->send[buffIndx].dataId++; + sysMonitorInst->sendCtrl.latest = buffIndx; + sysMonitorInst->sendCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest send payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_GetSendPayload(uint8_t *buff, uint32_t *id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + ASSERT(id != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->sendCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + { + buffIndx = buffIndex_old; // Keep it busy + } + else + { + buffIndx = GetReadable(sysMonitorInst->sendCtrl); + } + sysMonitorInst->sendCtrl.rBusy = buffIndx; + if (sysMonitorInst->send[buffIndx].dataId != DATA_ID_NONE) + { + memcpy(buff, sysMonitorInst->send[buffIndx].data, len); + } + *id = sysMonitorInst->send[buffIndx].dataId; + sysMonitorInst->sendCtrl.rBusy = buffIndex_old; +} + +/** + * @brief Update receive payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_UpdateRecvPayload(const uint8_t *buff, uint32_t id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + if (id == DATA_ID_NONE || len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->recvCtrl); + sysMonitorInst->recvCtrl.wBusy = buffIndx; + memcpy(sysMonitorInst->recv[buffIndx].data, buff, len); + sysMonitorInst->recv[buffIndx].dataId = id; + sysMonitorInst->recvCtrl.latest = buffIndx; + sysMonitorInst->recvCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest receive payload. + * + * @param buff + * @param id + * @param len + */ +void SysMonitor_GetRecvPayload(uint8_t *buff, uint32_t *id, size_t len) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(buff != NULL); + ASSERT(id != NULL); + if (len > PAYLOAD_LEN_MAX) + { + return; + } + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->recvCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->recvCtrl); + sysMonitorInst->recvCtrl.rBusy = buffIndx; + if (sysMonitorInst->recv[buffIndx].dataId != DATA_ID_NONE) + { + memcpy(buff, sysMonitorInst->recv[buffIndx].data, len); + } + *id = sysMonitorInst->recv[buffIndx].dataId; + sysMonitorInst->recvCtrl.rBusy = buffIndex_old; +} +/** @} ServicePayload_API*/ + +/** + * @name Linklayer_Log_API + * @{ + */ + +/** + * @brief Update link layer log + * + * @param log + */ +void SysMonitor_UpdateLinklayerLog(const LINKLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->linkLogCtrl); + sysMonitorInst->linkLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->linkLog[buffIndx]), log, sizeof(LINKLOG)); + sysMonitorInst->linkLogCtrl.latest = buffIndx; + sysMonitorInst->linkLogCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest link layer log + * + * @param log + */ +void SysMonitor_GetLinklayerLog(LINKLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->linkLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->linkLogCtrl); + sysMonitorInst->linkLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->linkLog[buffIndx]), sizeof(LINKLOG)); + sysMonitorInst->linkLogCtrl.rBusy = buffIndex_old; +} +/** @} Linklayer_Log_API*/ + +/** + * @name PhysicalLayer_Log_API + * @{ + */ + +/** + * @brief Update physical layer log + * + * @param log + */ +void SysMonitor_UpdatePhysicalLayerLog(const PHYLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->phyLogCtrl); + sysMonitorInst->phyLogCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->phyLog[buffIndx]), log, sizeof(PHYLOG)); + sysMonitorInst->phyLogCtrl.latest = buffIndx; + sysMonitorInst->phyLogCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest physical layer log + * + * @param log + */ +void SysMonitor_GetPhysicalLayerLog(PHYLOG *log) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(log != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->phyLogCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->phyLogCtrl); + sysMonitorInst->phyLogCtrl.rBusy = buffIndx; + memcpy(log, &(sysMonitorInst->phyLog[buffIndx]), sizeof(PHYLOG)); + sysMonitorInst->phyLogCtrl.rBusy = buffIndex_old; +} +/** @} */ + +/** + * @name HardwareState_Log_API + * @{ + */ + +/** + * @brief Log hardware running status. + * + * @param state + */ +void SysMonitor_UpdateHardwareStatus(const HWSTATE *state) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(state != NULL); + uint8_t buffIndx; + buffIndx = GetWritable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.wBusy = buffIndx; + memcpy(&(sysMonitorInst->hwState[buffIndx]), state, sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.latest = buffIndx; + sysMonitorInst->hwStateCtrl.wBusy = BUFF_NONE; +} + +/** + * @brief Get the latest hardware running status. + * + * @param state + */ +void SysMonitor_GetHardwareStatus(HWSTATE *state) +{ + ASSERT(sysMonitorInst != NULL); + ASSERT(state != NULL); + uint8_t buffIndx, buffIndex_old; + buffIndex_old = sysMonitorInst->hwStateCtrl.rBusy; + if (buffIndex_old != BUFF_NONE) + buffIndx = buffIndex_old; // Keep it busy + else + buffIndx = GetReadable(sysMonitorInst->hwStateCtrl); + sysMonitorInst->hwStateCtrl.rBusy = buffIndx; + memcpy(state, &(sysMonitorInst->hwState[buffIndx]), sizeof(HWSTATE)); + sysMonitorInst->hwStateCtrl.rBusy = buffIndex_old; +} + +/** @} HardwareState_Log_API */ + +/** @} SystemMonitor*/ \ No newline at end of file diff --git a/df_datalink_ge/src/system_monitor.h b/df_datalink_ge/src/system_monitor.h index 44c445a..d5d8655 120000 --- a/df_datalink_ge/src/system_monitor.h +++ b/df_datalink_ge/src/system_monitor.h @@ -1 +1,249 @@ -../../df_datalink_sp/src/system_monitor.h \ No newline at end of file +/** + * @defgroup SystemMonitor + * @{ + */ + +#ifndef __SYSTEM_MONITOR_H_ +#define __SYSTEM_MONITOR_H_ + +/***************************** Include Files *********************************/ +#include +#include +#include "util.h" + +/************************* Constant Definitions ******************************/ +/** + * @name SystemMonitor_Constants + * @{ + */ +#define PAYLOAD_LEN_MAX 256 +#define PAYLOAD_LEN_FLJ_RX 168 +#define PAYLOAD_LEN_FLJ_TX 66 +#define PAYLOAD_LEN_LJ_RX 66 +#define PAYLOAD_LEN_LJ_TX 168 + +#define DATA_ID_NONE UINT32_MAX +#define DATA_ID_TEST 0x02030203 + +#define VOLTAGE_LSB 0.01 // volt +#define VOLTAGE_MAX 2.55 // volt + +#define VOLT_PS_STD 1.0 +#define VOLT_PSAUX_STD 1.8 +#define VOLT_DDR_STD 1.5 +#define VOLT_PL_STD 1.0 +#define VOLT_PLAUX_STD 1.8 +#define VOLT_BRAM_STD 1.0 + +#define VOLT_PS_OK BIT(0) +#define VOLT_PSAUX_OK BIT(1) +#define VOLT_DDR_OK BIT(2) +#define VOLT_PL_OK BIT(3) +#define VOLT_PLAUX_OK BIT(4) +#define VOLT_BRAM_OK BIT(5) + +#define VOLT_ANT_PROC_OK BIT(0) +#define VOLT_ANT_RF_OK BIT(2) +#define VOLT_ANT_NIL_OK BIT(4) +#define ANT_STATE_OK BIT(6) + +// Xilinx Recommended +// #define IS_PS_VALID(x) (x <= 1.05 && x >= 0.95) +// #define IS_PSAUX_VALID(x) (x <= 1.89 && x >= 1.71) +// #define IS_DDR_VALID(x) (x <= 1.89 && x >= 1.14) +// #define IS_PL_VALID(x) (x <= 1.03 && x >= 0.97) +// #define IS_PLAUX_VALID(x) (x <= 1.89 && x >= 1.71) +// #define IS_BRAM_VALID(x) (x <= 1.03 && x >= 0.97) +#define IS_PS_VALID(x) ((x) <= 1.1 && (x) >= 0.9) +#define IS_PSAUX_VALID(x) ((x) <= 2.0 && (x) >= 1.6) +#define IS_DDR_VALID(x) ((x) <= 1.7 && (x) >= 1.3) +#define IS_PL_VALID(x) (x <= 1.1 && (x) >= 0.9) +#define IS_PLAUX_VALID(x) ((x) <= 2.0 && (x) >= 1.6) +#define IS_BRAM_VALID(x) ((x) <= 1.1 && (x) >= 0.9) + +#define CLK_SP_PLL1_LOCK BIT(0) +#define CLK_SP_PLL2_LOCK BIT(1) + +#define CLK_AD0_BBPLL_LOCK BIT(0) +#define CLK_AD0_RFPLL_LOCK BIT(2) +#define CLK_AD1_BBPLL_LOCK BIT(4) +#define CLK_AD1_RFPLL_LOCK BIT(6) + +#define CLK_ANT_BBPLL_LOCK BIT(0) +#define CLK_ANT_RFPLL1_LOCK BIT(2) +#define CLK_ANT_RFPLL2_LOCK BIT(4) + +#define TEMPERATURE_LSB 1.0 // Celsius degree +#define TEMPERATURE_MAX 127.0 // Celsius degree +#define TEMPERATURE_MIN -128.0 // Celsius degree +/** @} SystemMonitor_Constants */ + +/************************* Data Type Definitions ****************************/ + +/** + * @struct SYSINFO + * @brief System Infomation log + */ +typedef struct __attribute__((packed)) +{ + uint32_t psBDS; ///< -- unit: ms, 0~604799999 + uint16_t pBDS; ///< -- unit: week, 0~0~8191 + uint32_t psGPS; ///< -- unit: ms, 0~604799999 + uint16_t pGPS; ///< -- unit: week, 0~0~8191 + uint8_t tmInd; ///< Time validation indicator \n + // -- [0] GPS\n + // -- [1] reserve.\n + // -- [2] UTC\n + // -- [3] BDS\n + float tmFly; ///< Time of flying uint: s + uint8_t stFly; ///< Status of flying \n + // [7:6] departure status 11 - departed/00 - not departed \n + // [5:4] ready status 11 - ready/00 - not ready \n + // [3:2] attitude status 11 - attitude ok/00 - attitude not ok \n + // [1:0] attitude adjust status 11 - adjusted/00 - not adjusted + float posX; ///< coord X Position in launch coordinate system + float posY; ///< coord Y Position in launch coordinate system + float posZ; ///< coord Z Position in launch coordinate system + float vX; ///< Speed X in launch coordinate system + float vY; ///< Speed Y in launch coordinate system + float vZ; ///< Speed Z in launch coordinate system + float pitch; ///< Pitch Attitude in launch inertia coordinate system + float yaw; ///< Yaw Attitude in launch inertia coordinate system + float roll; ///< Roll Attitude in launch inertia coordinate system +} SYSINFO; + +/** + * @struct SYSBUSLOG + * @brief System Info holds the system bus log + */ +typedef struct __attribute__((packed)) +{ + // SystemBus log + + uint8_t lastConfig[2]; ///< Last valid config \n + // byte 0: 0x11 FLJ, 0x00 LJ \n + // byte 1: 0x66 Full Power, 0x88 Low Power + uint32_t pollCnt; ///< number of poll commands + uint32_t svcCnt; ///< number of service commands + uint32_t remoteCnt; ///< number of remote check commands +} SYSBUSLOG; + +/** + * @struct LINKLOG + * @brief Linklayer Log struct holds the Linklayer log + */ +typedef struct __attribute__((packed)) +{ + // Network log + uint32_t tuNum; ///< current time unite number + uint8_t slotNum; ///< current slot number + uint8_t nodeType; ///< current node type + uint8_t cxnStatus; ///< current connection status + uint8_t linkStage; ///< current linklayer working stage + uint32_t recxnCnt; ///< reconnect trial count + uint8_t antIndex; ///< current working antenna index + uint16_t advTxCnt; ///< adv frame send count + uint16_t advRecvCnt; ///< adv frame received count + uint16_t advCorrectCnt; ///< adv frame received correctly count + uint32_t ackTxCnt; ///< ack frame send count + uint32_t ackRecvCnt; ///< ack frame received count + uint32_t ackCorrectCnt; ///< ack frame received correctly count + uint32_t disTxCnt; ///< dist frame send count + uint32_t disRecvCnt; ///< dist frame received count + uint32_t disCorrectCnt;///< dist frame received correctly count + uint32_t mngTxCnt; ///< mng frame send count + uint32_t mngRecvCnt; ///< mng frame received count + uint32_t mngCorrectCnt; ///< mng frame received correctly count + uint32_t rttTxCnt; ///< rtt frame send count + uint32_t rttRecvCnt; ///< rtt frame received count + uint32_t rttCorrectCnt; ///< rtt frame received correctly count + uint32_t svcTxCnt; ///< svc frame send count + uint32_t svcRecvCnt; ///< svc frame received count + uint32_t svcCorrectCnt; ///< svc frame received correctly count + int32_t timeDev; ///< last time deviation result + uint32_t sendId; ///< last send data id + uint32_t recvId; ///< last received data id + uint8_t reserve[4]; ///< reserved data +} LINKLOG; + +/** + * @struct PHYLOG + * @brief Physical Layer Log struct holds the Linklayer log + */ +typedef struct __attribute__((packed)) +{ + uint32_t acqCnt; ///< aquisition count + uint32_t fsyncCnt; ///< frame sync count + uint32_t decodeCnt; ///< decode count + uint32_t crcCnt; ///< crc valid count + double doppler; ///< last doppler estimation result + uint64_t recvStamp; ///< last frame arrival time + double acqPAPR; ///< last acquisition peak-average ration + uint8_t acqPhase; ///< last acquisition phase estimation + uint8_t acqFreqCh; ///< last acquisition frequency deviation estimation + double fsyncPAPR; ///< last frame sync peak-average ration + uint8_t fsyncFreqCh; ///< last frame sync frequency estimation + uint16_t deintlvAmpEst; ///< de-interleave amplitude estimation + uint8_t antControl; ///< current antenna rf mode + uint8_t reserve[3]; ///< reserved data +} PHYLOG; + +/** + * @struct HWSTATE + * @brief Hardware Status Log struct holds all hardware status + */ +typedef struct __attribute__((packed)) +{ + bool isSpOk; ///< signal processor state + bool isAntOk; ///< antenna state + // -- Signal processor status + uint8_t spFpgaVolt; ///< Signal processor voltage state indicator + uint8_t spClkState; ///< Signal processor clock state indicator + uint8_t spAdLockState; ///< Signal processor adc lock state indicator + int8_t spAdTemp_0; ///< Signal processor adc0 temperature + int8_t spAdTemp_1; ///< Signal processor adc1 temperature + int8_t spFpgaTemp; ///< Signal processor FPGA temperature + // -- Antenna status + uint16_t ant1Freq; ///< Antenna 1 frequency + uint16_t ant2Freq; ///< Antenna 2 frequency + uint16_t ant3Freq; ///< Antenna 3 frequency + uint8_t antPll; ///< Antenna pll lock state indicator + uint8_t antMode; ///< Antenna mode indicator + int8_t antTemp; ///< Antenna rf temperature + uint8_t antRsvd; ///< Antenna reserved status register + uint8_t phyId; + uint8_t reserve[1]; +} HWSTATE; + +/** + * @struct PAYLOAD + * @brief Payload struct holds the service payload + */ +typedef struct +{ + uint32_t dataId; + uint8_t data[PAYLOAD_LEN_MAX]; +} PAYLOAD; + +/************************** Function Prototypes ******************************/ +int32_t SysMonitor_Init(void); +void SysMonitor_Destroy(void); + +void SysMonitor_UpdateSysinfo(const SYSINFO *info); +void SysMonitor_GetSysinfo(SYSINFO *info); + +void SysMonitor_UpdateSendPayload(const uint8_t *buff, size_t len); +void SysMonitor_UpdateRecvPayload(const uint8_t *buff, uint32_t id, size_t len); +void SysMonitor_GetSendPayload(uint8_t *buff, uint32_t *id, size_t len); +void SysMonitor_GetRecvPayload(uint8_t *buff, uint32_t *id, size_t len); + +void SysMonitor_UpdateLinklayerLog(const LINKLOG *log); +void SysMonitor_UpdatePhysicalLayerLog(const PHYLOG *log); +void SysMonitor_UpdateHardwareStatus(const HWSTATE *state); +void SysMonitor_GetLinklayerLog(LINKLOG *log); +void SysMonitor_GetPhysicalLayerLog(PHYLOG *log); +void SysMonitor_GetHardwareStatus(HWSTATE *state); + +#endif //__SYSTEM_MONITOR_H_ + +/** @} */ diff --git a/df_datalink_ge/src/systembus/systembus.c b/df_datalink_ge/src/systembus/systembus.c new file mode 100644 index 0000000..2fe3d28 --- /dev/null +++ b/df_datalink_ge/src/systembus/systembus.c @@ -0,0 +1,780 @@ +/*****************************************************************************/ +/** + * @file systembus.c + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief System bus protocol implementation file. + * @version 0.1 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup SystemBus + * @{ + */ + +/***************************** Include Files *********************************/ +#include +#include +#include +#include +#include "systembus_uart.h" +#include "systembus.h" +#include "util.h" +#include "common.h" +#include "error.h" +#include "circ_queue.h" +#include "../system_monitor.h" + +/** + * @addtogroup SystemBus_Protocol_Routine + * @{ + */ + +/************************** Constant Definitions *****************************/ +/** + * @name SystemBus_MSG_Constants + * @{ + */ +// Common Field +// -- Command word +#define WD_CMD 0x00 + +// -- Production type +#define WD_PRD 0x01 +#define PRD_DL_K 0xDD +#define PRD_DL_S 0xEE +#define PRD_ALL 0xFF + +// Self-Test +#define CMD_SELF_TEST 0xE1 +// -- Request +// -- -- -- +// -- Response +// -- -- Self-Test Result +#define ST_RSP_LEN 16 +#define WD_ST_RET 0x02 +#define ST_RET_OK 0xAA +#define ST_RET_ERROR 0x55 +#define ST_RET_INFO_LEN 13 +// -- -- Signal processor PS voltage +#define WD_SP_FPGA_VOLT 0x03 +// -- -- Signal processor PS AUX voltage +#define WD_SP_CLK_STATE 0x04 +// -- -- Signal processor DDR voltage +#define WD_SP_AD_LOCK_STATE 0x05 +// -- -- Signal processor PL voltage +#define WD_SP_AD_TEMP_0 0x06 +// -- -- Signal processor PL AUX voltage +#define WD_SP_AD_TEMP_1 0x07 +// -- -- Signal processor Bram voltage +#define WD_SP_FPGA_TEMP 0x08 + +// -- -- Signal processor antenna voltage status +#define WD_ANT_VOLT 0x09 + +// -- -- Signal processor antenna RF temperature +#define WD_ANT_RF_TEMP 0x0A +// -- -- Signal processor antenna PLL lock status +#define WD_ANT_RF_PLL 0x0B +// -- -- Signal processor antenna MGC +#define WD_ANT_MGC_0 0x0C +#define WD_ANT_MGC_1 0x0D +// -- -- Reserved +#define WD_ANT_RESERVE 0x0E + +// Data Send Test Command +#define CMD_DATA_TEST_A 0xE2 +// -- Request +#define DATA_TEST_REQ_A_LEN 68 +// -- -- 68 byte payload +// -- Response +#define DATA_TEST_RSP_A_LEN 68 +// -- -- 68 byte payload + +// Data Send Test Command +#define CMD_DATA_TEST_B 0xF2 +// -- Request +#define DATA_TEST_REQ_B_LEN 170 +// -- -- 170 byte payload +// -- Response +#define DATA_TEST_RSP_B_LEN 170 +// -- -- 170 byte payload + +// Config load +#define CMD_CONFIG 0xE3 +// -- Request +#define WD_EN_CMD 0x02 +#define EN_CMD_ON_HIGH_POWER 0x66 +#define EN_CMD_ON_LOW_POWER 0x77 +#define EN_CMD_SILENT 0x88 + +#define WD_MODE_CMD 0x03 +#define MODE_CMD_HEAD 0x11 +#define MODE_CMD_MEMBER 0x00 +// -- Response +// -- -- none response + +// System info update +#define CMD_SYS_INFO 0x33 +#define SYS_INFO_OFFSET 2 +// -- Request +// -- -- 54 byte system info +// -- Response +// -- -- none response + +// Data Send Test Command +#define CMD_FLJ_SEND 0xE4 +#define FLJ_DATA_OFFSET 2 +// -- Request +// -- -- 78 byte payload +// -- Response +// -- -- none response + +// Data Send Test Command +#define CMD_LJ_SEND 0xF4 +#define LJ_DATA_OFFSET 2 +// -- Request +// -- -- 156 byte payload +// -- Response +// -- -- none response + +// FLJ Poll +#define CMD_FLJ_POLL 0xE5 +// -- Request +#define WD_FLJ_POLL 0x02 +#define FLJ_POLL_CODE 0x77 +// -- Response +#define FLJ_POLL_RESP_LEN 170 +// -- -- received 170 byte payload + +// LJ Poll +#define CMD_LJ_POLL 0xF5 +// -- Request +#define WD_LJ_POLL 0x02 +#define LJ_POLL_CODE 0x77 +// -- Response +#define LJ_POLL_RESP_LEN 68 +// -- -- received 68 byte payload + +// Remote Test FLJ +#define CMD_FLJ_RM_TEST 0xE6 +// -- Request +#define WD_FLJ_RM_TEST 0x02 +#define FLJ_RM_TEST_CODE 0x99 +// -- Response +#define WD_FLJ_TIME_STAMP 0x02 +#define WD_FLJ_TIME_STAMP_LEN 8 +#define WD_FLJ_SYSBUS_LOG 0x0A +#define WD_FLJ_SYSBUS_LOG_LEN 14 +#define WD_FLJ_LINK_LOG 0x18 +#define WD_FLJ_LINK_LOG_LEN 64 +#define WD_FLJ_PHY_LOG 0x58 +#define WD_FLJ_PHY_LOG_LEN 57 +#define WD_FLJ_HARDWARE_ST 0x91 +#define WD_FLJ_HARDWARE_ST_LEN 13 + +#define FLJ_RM_TEST_RESP_LEN 158 + +// Remote Test LJ +#define CMD_LJ_RM_TEST 0xF6 +// -- Request +#define WD_LJ_RM_TEST 0x02 +#define LJ_RM_TEST_CODE 0x99 +// -- Response +#define WD_LJ_TIME_STAMP 0x02 +#define WD_LJ_TIME_STAMP_LEN 8 +#define WD_LJ_SYSBUS_LOG 0x0A +#define WD_LJ_SYSBUS_LOG_LEN 14 +#define WD_LJ_LINK_LOG 0x18 +#define WD_LJ_LINK_LOG_LEN 64 +#define WD_LJ_PHY_LOG 0x58 +#define WD_LJ_PHY_LOG_LEN 57 +#define WD_LJ_HARDWARE_ST 0x91 +#define WD_LJ_HARDWARE_ST_LEN 13 + +#define LJ_RM_TEST_RESP_LEN 158 + +// My Production Type +#define MY_PRD_ID PRD_DL_K +/** @} SystemBus_MSG_Constants*/ +/************************** Function Prototypes ******************************/ +static int32_t SystemBus_GenSelfTestRsp(SYSBUS *instPtr); +static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg); +static int32_t SystemBus_Echo(SYSBUS *instPtr, SYSBUS_UART_FRAME *frame); +static int32_t SystemBus_GenPollRsp(SYSBUS *instPtr, uint8_t *msg); +static int32_t SystemBus_GenRemoteTestRsp(SYSBUS *instPtr, uint8_t *msg); +/**************************** Type Definitions *******************************/ +/************************** Variable Definitions *****************************/ +// TODO: better approach? +#include "../networking/link_layer/link_layer.h" +#include "../networking/phy_layer/phy_layer.h" +extern L2_INST *linkInstPtr; +extern L2_CONFIG linkConfig; + +inline bool SystemBus_IsReqPending(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + return (!isCircQueueEmpty(instPtr->rxQueue)); +} + +inline bool SystemBus_IsRsqPending(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + return (!isCircQueueEmpty(instPtr->txQueue)); +} + +inline bool SystemBus_IsTxBusy(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + return (!instPtr->isTxDone); +} +inline bool SystemBus_IsRxBusy(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + return SysbusUart_IsRxBusy(instPtr->uartInst); +} + +/** + * @brief Generate System Bus SelfTest response. + */ +static int32_t SystemBus_GenSelfTestRsp(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusRsp == NULL) + { + DBG_ERROR("Failed to allocate memory for SELF TEST Response!\n"); + return ENOMEM; + } + HWSTATE *hwStatsPtr = &(instPtr->hwState); + sysbusRsp->len = ST_RSP_LEN; + memset(sysbusRsp->data, 0x00, ST_RSP_LEN); + sysbusRsp->data[WD_CMD] = CMD_SELF_TEST; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + SysMonitor_GetHardwareStatus(hwStatsPtr); + if (L2_isStarted(linkInstPtr)) + { + sysbusRsp->data[WD_ST_RET] = (hwStatsPtr->isSpOk && hwStatsPtr->isAntOk) ? ST_RET_OK : ST_RET_ERROR; + } + else + { + sysbusRsp->data[WD_ST_RET] = (hwStatsPtr->isSpOk) ? ST_RET_OK : ST_RET_ERROR; + } + // apply status and omit 2 bytes of overhead. + memcpy(sysbusRsp->data + WD_SP_FPGA_VOLT, &(hwStatsPtr->spFpgaVolt), ST_RET_INFO_LEN); + + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) + { + free(sysbusRsp); + DBG_ERROR("SystemBus::TX Queue overflowed!\n"); + return EQUEUE; + } + return SUCCESS; +} + +/** + * @brief Apply system configuration + */ +static int32_t SystemBus_SystemConfig(SYSBUS *instPtr, uint8_t *msg) +{ + ASSERT(instPtr != NULL); + ASSERT(msg != NULL); + PHY_INST *phyRef = linkInstPtr->config.phyInstPtr; + TMC_INST *tmcRef = linkInstPtr->config.tmcInstPtr; + bool reconfig = false; + + if (msg[WD_MODE_CMD] == MODE_CMD_HEAD) + { + // head node config + reconfig = (L2_NODE_HEAD != L2_GetNodeType(linkInstPtr)); + linkConfig.myType = L2_NODE_HEAD; + linkConfig.myId = 1; + } + + else if (msg[WD_MODE_CMD] == MODE_CMD_MEMBER) + { + // member node config + reconfig = (L2_NODE_MEMBER != L2_GetNodeType(linkInstPtr)); + linkConfig.myType = L2_NODE_MEMBER; + linkConfig.myId = 2; + } + else + { + // Ignore current command + DBG_ERROR("Unexpected config command 0x%02X:0x%02X", + WD_MODE_CMD, msg[WD_MODE_CMD]); + return EPARAM; + } + +// if (msg[WD_EN_CMD] == EN_CMD_ON_HIGH_POWER) +// { +// // full power config +// Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_FULL); +// if (reconfig || !L2_isStarted(linkInstPtr)) +// { +// Linklayer_Reconfig(linkInstPtr, &linkConfig); +// } +// Linklayer_Start(linkInstPtr); +// } +// else if (msg[WD_EN_CMD] == EN_CMD_ON_LOW_POWER) +// { +// // low power config +// Phy_AntConfigMode(phyRef, PHY_ANT_MODE_POWER_LOW); +// if (reconfig || !L2_isStarted(linkInstPtr)) +// { +// Linklayer_Reconfig(linkInstPtr, &linkConfig); +// } +// Linklayer_Start(linkInstPtr); +// } +// else if (msg[WD_EN_CMD] == EN_CMD_SILENT) +// { +// // silence config +// // TODO: better approach? +// Linklayer_Halt(linkInstPtr); +// Phy_AntConfigMode(phyRef, PHY_ANT_MODE_STANDBY); +// TIME_WORD pullTime = {0, 0}; +// pullTime.int_part = TimeCtrl_GetIntCnt(tmcRef) + 1; +// if (Phy_SetTimeWord(phyRef, &pullTime, PHY_TIME_WORD_POLL) != SUCCESS) +// { +// DBG_ERROR("Physical set pull time failed.\n"); +// } +// Phy_SetupNextSlot(phyRef, PHY_TOR_RX, L1_10KBPS_10MS_FRAME, NULL); +// } + // else + // { + // // Ignore current command + // DBG_ERROR("Unexpected config command 0x%02X:0x%02X", + // WD_EN_CMD, msg[WD_EN_CMD]); + // return EIGNORE; + // } + instPtr->sysbusLog.lastConfig[0] = msg[WD_MODE_CMD]; + instPtr->sysbusLog.lastConfig[1] = msg[WD_EN_CMD]; + return SUCCESS; +} + +/** + * @brief Echo System Bus frame + */ +static int32_t SystemBus_Echo(SYSBUS *instPtr, SYSBUS_UART_FRAME *frame) +{ + ASSERT(instPtr != NULL); + ASSERT(frame != NULL); + SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusRsp == NULL) + { + DBG_ERROR("Failed to allocate memory for DATA TEST A Response!\n"); + return ENOMEM; + } + sysbusRsp->len = frame->len; + memcpy(sysbusRsp->data, frame->data, sysbusRsp->len); + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) + { + free(sysbusRsp); + DBG_ERROR("SystemBus::TX Queue overflowed!\n"); + return EQUEUE; + } + return SUCCESS; +} + +/** + * @brief Generate System Bus poll call command response + */ +static int32_t SystemBus_GenPollRsp(SYSBUS *instPtr, uint8_t *msg) +{ + ASSERT(instPtr != NULL); + ASSERT(msg != NULL); + size_t dataLen; + uint8_t *payload; + SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusRsp == NULL) + { + DBG_ERROR("Failed to allocate memory for FLJ POLL Response!\n"); + return ENOMEM; + } + + if (msg[WD_CMD] == CMD_FLJ_POLL) + { + sysbusRsp->len = FLJ_POLL_RESP_LEN; + sysbusRsp->data[WD_CMD] = CMD_FLJ_POLL; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + dataLen = PAYLOAD_LEN_FLJ_RX; + payload = sysbusRsp->data + FLJ_DATA_OFFSET; + } + else if (msg[WD_CMD] == CMD_LJ_POLL) + { + sysbusRsp->len = LJ_POLL_RESP_LEN; + sysbusRsp->data[WD_CMD] = CMD_LJ_POLL; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + dataLen = PAYLOAD_LEN_LJ_RX; + payload = sysbusRsp->data + LJ_DATA_OFFSET; + } + else + { + DBG_ERROR("Unexpected command 0x%02X.\n", msg[WD_CMD]); + free(sysbusRsp); + return EUNEXP; + } + uint32_t dataId; + SysMonitor_GetRecvPayload(payload, &dataId, dataLen); // omit control info + if (dataId == DATA_ID_NONE) + { + free(sysbusRsp); + DBG_WARNING("SystemBus::no RX data!\n"); + return SUCCESS; + } + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) + { + free(sysbusRsp); + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + return EQUEUE; + } + instPtr->sysbusLog.pollCnt++; + return SUCCESS; +} + +/** + * @brief Generate System Bus remote test command response + */ +static int32_t SystemBus_GenRemoteTestRsp(SYSBUS *instPtr, uint8_t *msg) +{ + ASSERT(instPtr != NULL); + ASSERT(msg != NULL); + SYSBUS_UART_FRAME *sysbusRsp = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusRsp == NULL) + { + DBG_ERROR("Failed to allocate memory for LJ REMOTE TEST Response!\n"); + return ENOMEM; + } + + TIME_WORD tmWord; + uint64_t time; + TimeCtrl_GetCurrentTime(linkInstPtr->config.tmcInstPtr, &tmWord); + time = (uint64_t)tmWord.int_part * TIME_FRAC_MAX + tmWord.frac_part; + + if (msg[WD_CMD] == CMD_FLJ_RM_TEST) + { + sysbusRsp->len = FLJ_RM_TEST_RESP_LEN; + memset(sysbusRsp->data, 0x00, FLJ_RM_TEST_RESP_LEN); + sysbusRsp->data[WD_CMD] = CMD_FLJ_RM_TEST; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + + memcpy(sysbusRsp->data + WD_FLJ_TIME_STAMP, &time, WD_FLJ_TIME_STAMP_LEN); + SysMonitor_GetLinklayerLog(&(instPtr->linkLog)); + SysMonitor_GetPhysicalLayerLog(&(instPtr->phyLog)); + SysMonitor_GetHardwareStatus(&(instPtr->hwState)); + memcpy(sysbusRsp->data + WD_FLJ_SYSBUS_LOG, &(instPtr->sysbusLog), WD_FLJ_SYSBUS_LOG_LEN); + memcpy(sysbusRsp->data + WD_FLJ_LINK_LOG, &(instPtr->linkLog), WD_FLJ_LINK_LOG_LEN); + memcpy(sysbusRsp->data + WD_FLJ_PHY_LOG, &(instPtr->phyLog), WD_FLJ_PHY_LOG_LEN); + memcpy(sysbusRsp->data + WD_FLJ_HARDWARE_ST, &(instPtr->hwState.spFpgaVolt), WD_FLJ_HARDWARE_ST_LEN); + } + else if (msg[WD_CMD] == CMD_LJ_RM_TEST) + { + sysbusRsp->len = LJ_RM_TEST_RESP_LEN; + sysbusRsp->data[WD_CMD] = CMD_LJ_RM_TEST; + sysbusRsp->data[WD_PRD] = MY_PRD_ID; + + memcpy(sysbusRsp->data + WD_LJ_TIME_STAMP, &time, WD_LJ_TIME_STAMP_LEN); + SysMonitor_GetLinklayerLog(&(instPtr->linkLog)); + SysMonitor_GetPhysicalLayerLog(&(instPtr->phyLog)); + SysMonitor_GetHardwareStatus(&(instPtr->hwState)); + memcpy(sysbusRsp->data + WD_LJ_SYSBUS_LOG, &(instPtr->sysbusLog), WD_LJ_SYSBUS_LOG_LEN); + memcpy(sysbusRsp->data + WD_LJ_LINK_LOG, &(instPtr->linkLog), WD_LJ_LINK_LOG_LEN); + memcpy(sysbusRsp->data + WD_LJ_PHY_LOG, &(instPtr->phyLog), WD_LJ_PHY_LOG_LEN); + memcpy(sysbusRsp->data + WD_LJ_HARDWARE_ST, &(instPtr->hwState.spFpgaVolt), WD_LJ_HARDWARE_ST_LEN); + } + else + { + DBG_ERROR("Unexpected command 0x%02X.\n", msg[WD_CMD]); + free(sysbusRsp); + return EUNEXP; + } + + if (CircQueuePush(instPtr->txQueue, (void *)sysbusRsp) == false) + { + free(sysbusRsp); + DBG_WARNING("SystemBus::TX Queue overflowed!\n"); + return EQUEUE; + } + instPtr->sysbusLog.remoteCnt++; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief A handler function. This handler evaluate the message from system + * bus receive queue, and make appropriate response. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * + ******************************************************************************/ +int32_t SystemBus_HandleCmd(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + int32_t Status; + SYSBUS_UART_FRAME *sysbusReq; + uint8_t *msg; + if (CircQueuePop(instPtr->rxQueue, (void **)(&sysbusReq)) == false) + { + DBG_WARNING("SystemBus::Nothing to be handled.\n"); + return EIGNORE; + } + msg = sysbusReq->data; + if (msg[WD_PRD] != MY_PRD_ID && msg[WD_PRD] != PRD_ALL) + { + DBG_WARNING("SystemBus::Production code mismatch!\n"); + return EIGNORE; + } + + switch (msg[WD_CMD]) + { + case CMD_SELF_TEST: + { + Status = SystemBus_GenSelfTestRsp(instPtr); + break; + } + case CMD_DATA_TEST_A: + case CMD_DATA_TEST_B: + { + Status = SystemBus_Echo(instPtr, sysbusReq); + break; + } + case CMD_CONFIG: + { + Status = SystemBus_SystemConfig(instPtr, msg); + break; + } + case CMD_SYS_INFO: + { + SysMonitor_UpdateSysinfo((SYSINFO *)(msg + SYS_INFO_OFFSET)); + Status = SUCCESS; + break; + } + case CMD_FLJ_SEND: + { + SysMonitor_UpdateSendPayload(msg + FLJ_DATA_OFFSET, PAYLOAD_LEN_FLJ_TX); // omit control info + instPtr->sysbusLog.svcCnt++; + Status = SUCCESS; + break; + } + case CMD_LJ_SEND: + { + SysMonitor_UpdateSendPayload(msg + LJ_DATA_OFFSET, PAYLOAD_LEN_LJ_TX); // omit control info + instPtr->sysbusLog.svcCnt++; + Status = SUCCESS; + break; + } + case CMD_FLJ_POLL: + { + if (msg[WD_FLJ_POLL] != FLJ_POLL_CODE) + { + DBG_ERROR("SystemBus::Invalid roll call code!\n"); + Status = EIGNORE; + break; + } + Status = SystemBus_GenPollRsp(instPtr, msg); + break; + } + case CMD_LJ_POLL: + { + if (msg[WD_LJ_POLL] != LJ_POLL_CODE) + { + DBG_WARNING("SystemBus::Invalid roll call code!\n"); + Status = EIGNORE; + break; + } + Status = SystemBus_GenPollRsp(instPtr, msg); + break; + } + case CMD_FLJ_RM_TEST: + { + if (msg[WD_FLJ_RM_TEST] != FLJ_RM_TEST_CODE) + { + DBG_WARNING("SystemBus::Invalid remote test code!\n"); + Status = EIGNORE; + break; + } + Status = SystemBus_GenRemoteTestRsp(instPtr, msg); + break; + } + case CMD_LJ_RM_TEST: + { + if (msg[WD_LJ_RM_TEST] != LJ_RM_TEST_CODE) + { + DBG_WARNING("SystemBus::Invalid remote test code!\n"); + Status = EIGNORE; + break; + } + Status = SystemBus_GenRemoteTestRsp(instPtr, msg); + break; + } + default: + { + DBG_ERROR("SystemBus::Unknown command code!\n"); + Status = FAILURE; + break; + } + } + free(sysbusReq); + return Status; +} + +/*****************************************************************************/ +/** + * @brief This function send a repose frame from system bus tx queue. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * + ******************************************************************************/ +int32_t SystemBus_MakeResp(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + int32_t Status; + SYSBUS_UART_FRAME *sysbusRsp; + if (CircQueuePop(instPtr->txQueue, (void **)(&sysbusRsp)) == false) + { + DBG_WARNING("SystemBus::Nothing to be sent.\n"); + return EIGNORE; + } + instPtr->isTxDone = false; // A transmission procedure is started. + Status = SysbusUart_Send(instPtr->uartInst, sysbusRsp); + free(sysbusRsp); + return Status; +} + +/** @} */ + +/*****************************************************************************/ +/** + * @brief Initialize System Bus instance. + * + * @param InstPtr A double pointer to System Bus instance. + * @param config A pointer to System Bus configurations. + * + * @return Error code. + * + ******************************************************************************/ +int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config) +{ + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + SYSBUS_UART_CONFIG uartConfig; + int32_t Status; + (*instPtr) = malloc(sizeof(SYSBUS)); + if ((*instPtr) == NULL) + { + return ENOMEM; + } + (*instPtr)->rxQueue = NULL; + (*instPtr)->txQueue = NULL; + (*instPtr)->uartInst = NULL; + memcpy(&((*instPtr)->config), config, sizeof(SYSBUS_CONFIG)); + memset(&((*instPtr)->sysbusLog), 0x00, sizeof(SYSBUSLOG)); + memset(&((*instPtr)->linkLog), 0x00, sizeof(LINKLOG)); + memset(&((*instPtr)->phyLog), 0x00, sizeof(PHYLOG)); + memset(&((*instPtr)->hwState), 0x00, sizeof(HWSTATE)); + uartConfig.baseAddr = config->baseAddr; + Status = SysbusUart_Init(&((*instPtr)->uartInst), &uartConfig); + if (Status != SUCCESS) + { + SystemBus_Destroy(*instPtr); + return ENOMEM; + } + if (CircQueueCreate(&((*instPtr)->txQueue), (*instPtr)->config.txQueueMax) == false) + { + SystemBus_Destroy(*instPtr); + return ENOMEM; + } + if (CircQueueCreate(&((*instPtr)->rxQueue), (*instPtr)->config.rxQueueMax) == false) + { + SystemBus_Destroy(*instPtr); + return ENOMEM; + } + (*instPtr)->isRxDone = false; // nothing received. + (*instPtr)->isTxDone = true; // nothing to be sent. + return SUCCESS; +} + + +/*****************************************************************************/ +/** + * @brief Destroy System Bus instance. + * + * @param InstPtr A pointer to System Bus instance. + * + * @return None. + * + ******************************************************************************/ +void SystemBus_Destroy(SYSBUS *instPtr) +{ + if (instPtr == NULL) + { + return; + } + + free(instPtr->uartInst); + free(instPtr->txQueue); + free(instPtr->rxQueue); + free(instPtr); +} + +/*****************************************************************************/ +/** + * @brief This function handles the systembus tx irq events. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * + ******************************************************************************/ +int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + // nothing special... + instPtr->isTxDone = true; // A transmission procedure finished. + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief This function handles the systembus rx irq events. + * + * @param instPtr A pointer to System Bus instance. + * + * @return None + * + ******************************************************************************/ +int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr) +{ + ASSERT(instPtr != NULL); + instPtr->isRxDone = true; // whether reception successes or not, receiving procedure ended. + int32_t Status; + SYSBUS_UART_FRAME *sysbusReq = malloc(sizeof(SYSBUS_UART_FRAME)); + if (sysbusReq == NULL) + { + return ENOMEM; + } + Status = SysbusUart_Recv(instPtr->uartInst, sysbusReq); + if (Status != SUCCESS) + { + free(sysbusReq); + return Status; + } + if (CircQueuePush(instPtr->rxQueue, (void *)sysbusReq) == false) + { + DBG_ERROR("SystemBus::RX Queue overflowed!\n"); + free(sysbusReq); + return EQUEUE; + } + instPtr->isRxDone = false; // another reception is undergoing. + return SUCCESS; +} + +/** @} SystemBus*/ diff --git a/df_datalink_ge/src/systembus/systembus.h b/df_datalink_ge/src/systembus/systembus.h new file mode 100644 index 0000000..c0857a1 --- /dev/null +++ b/df_datalink_ge/src/systembus/systembus.h @@ -0,0 +1,84 @@ +/*****************************************************************************/ +/** + * @file systembus.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief System bus protocol header file. + * @version 0.1 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @defgroup SystemBus + * @{ + */ +#ifndef __SYSTEMBUS_H_ +#define __SYSTEMBUS_H_ + +/***************************** Include Files *********************************/ +#include +#include +#include "systembus_uart.h" // SystemBus UART driver +#include "circ_queue.h" +#include "../system_monitor.h" + +/************************** Constant Definitions *****************************/ +/************************** Data Type Definitions ****************************/ + +/** + * @struct SYSBUS_CONFIG + * @brief SystemBus Config struct holds SystemBus initialization parameters + */ +typedef struct +{ + uintptr_t baseAddr; ///< base address in memory + uint32_t txQueueMax; ///< maximum tx queue length + uint32_t rxQueueMax; ///< maximum rx queue length +} SYSBUS_CONFIG; + +/** + * @struct SYSBUS + * @brief SystemBus Instance struct + */ +typedef struct +{ + SYSBUS_CONFIG config; ///< SystemBus initialization parameters + SYSBUSLOG sysbusLog; ///< SystemBus log + LINKLOG linkLog; ///< Link layer log + PHYLOG phyLog; ///< Physical layer log + HWSTATE hwState; ///< Hardware status + SYSBUS_UART *uartInst; ///< physical uart controller instance + CIRC_QUEUE *txQueue; ///< tx queue + CIRC_QUEUE *rxQueue; ///< rx queue + bool isTxDone; ///< tx done indicator + bool isRxDone; ///< rx done indicator +} SYSBUS; + +/************************** Function Prototypes ******************************/ + +int32_t SystemBus_Init(SYSBUS **instPtr, SYSBUS_CONFIG *config); +void SystemBus_Destroy(SYSBUS *instPtr); + +/** + * @defgroup SystemBus_Protocol_Routine + * @{ + */ +int32_t SystemBus_HandleCmd(SYSBUS *instPtr); +int32_t SystemBus_MakeResp(SYSBUS *instPtr); +/** @} */ + +int32_t SystemBus_TxIntrHandler(SYSBUS *instPtr); +int32_t SystemBus_RxIntrHandler(SYSBUS *instPtr); + +bool SystemBus_IsReqPending(SYSBUS *instPtr); +bool SystemBus_IsRsqPending(SYSBUS *instPtr); + +bool SystemBus_IsTxBusy(SYSBUS *instPtr); +bool SystemBus_IsRxBusy(SYSBUS *instPtr); + +#endif //__SYSTEMBUS_H_ + +/** @} SystemBus*/ \ No newline at end of file diff --git a/df_datalink_ge/src/systembus/systembus_uart.c b/df_datalink_ge/src/systembus/systembus_uart.c new file mode 100644 index 0000000..e9bb943 --- /dev/null +++ b/df_datalink_ge/src/systembus/systembus_uart.c @@ -0,0 +1,265 @@ +/*****************************************************************************/ +/** + * @file systembus_uart.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief System bus uart driver implementation file. + * @version 0.1 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup SystemBus + * @{ + */ + +/** + * @addtogroup SystemBus_UART + * @{ + */ + + +#include +#include +#include +#include +#include "systembus_uart.h" +#include "common.h" + +/** + * @name SystemBus_UART_Driver_Constants + * @{ + */ +// Control and status register +#define MODULE_VERSION 0 +#define UART_STATUS 4 +#define UART_SEND_CMD 8 +#define UART_RECV_CNT 12 + +// Status code +#define UART_STATUS_TX_BUSY 0x00010000 +#define UART_STATUS_RX_BUSY 0x01000000 +// Data buffer register +#define UART_TXBUFF_OFFSET 1024 +#define UART_TXBUFF_MAX 1024 +#define UART_RXBUFF_OFFSET 2048 +#define UART_RXBUFF_MAX 1024 + +// Frame Data offsets +#define FRAME_HEAD_LOW 0x5A +#define FRAME_HEAD_HIGH 0x54 +#define FRAME_TAIL_LOW 0x5A +#define FRAME_TAIL_HIGH 0xFE + +#define FRAME_HEAD_LEN 2 +#define FRAME_TAIL_LEN 2 +#define FRAME_DUMMY_LEN 1 // Dummy +#define FRAME_CHECK_LEN 1 // CheckSum +#define FRAME_INFO_LEN 3 // CheckSum, Dummy and DataLen +#define FRAME_OVERHEAD_LEN 7 // CheckSum, Dummy and DataLen +/** @} SystemBus_UART_Driver_Constants*/ + +/*****************************************************************************/ +/** + * @brief Instance initial + * + * @param instPtr A pointer to frame uart instance structure. + * @param config Base address of frame uart, refer to "xparameters.h" + * + * @return None. + * + ******************************************************************************/ +int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config) +{ + ASSERT(instPtr != NULL); + ASSERT(config != NULL); + (*instPtr) = malloc(sizeof(SYSBUS_UART)); + if ((*instPtr) == NULL) + { + return FAILURE; + } + (*instPtr)->config.baseAddr = config->baseAddr; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Send a system bus frame. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * @param buff A pointer to send data buffer + * @param dLen A integer indicate the send data buffer length in byte. + * + * @return + * + ******************************************************************************/ +int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame) +{ + ASSERT(instPtr != NULL); + ASSERT(frame != NULL); + uint8_t dLen, checkSum; + uint8_t sendLen; + uint8_t *sendBuff; + if (frame->len > UART_TXBUFF_MAX || frame->len == 0) + { + return FAILURE; + } + sendBuff = malloc(sizeof(uint8_t) * UART_TXBUFF_MAX); + if (sendBuff == NULL) + { + return FAILURE; + } + sendBuff[0] = FRAME_HEAD_LOW; + sendBuff[1] = FRAME_HEAD_HIGH; + dLen = 0; + checkSum = 0; + for (int i = 0; i < frame->len - 1; i++) + { + if (frame->data[i] == FRAME_TAIL_LOW && frame->data[i + 1] == FRAME_TAIL_HIGH) + { + sendBuff[FRAME_HEAD_LEN + dLen] = 0x00; + dLen++; + } + sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[i]; + checkSum += sendBuff[FRAME_HEAD_LEN + dLen]; + dLen++; + } + // Last Byte + sendBuff[FRAME_HEAD_LEN + dLen] = frame->data[frame->len - 1]; + checkSum += sendBuff[FRAME_HEAD_LEN + dLen]; + dLen++; + // Dummy Byte + sendBuff[FRAME_HEAD_LEN + dLen] = 0x00; + // Check Sum + sendBuff[FRAME_HEAD_LEN + dLen + 1] = checkSum; + // Data Len + sendBuff[FRAME_HEAD_LEN + dLen + 2] = dLen; + // Frame Tail + sendBuff[FRAME_HEAD_LEN + dLen + 3] = FRAME_TAIL_LOW; + sendBuff[FRAME_HEAD_LEN + dLen + 4] = FRAME_TAIL_HIGH; + sendLen = dLen + FRAME_OVERHEAD_LEN; + if (sendLen > UART_TXBUFF_MAX) + { + free(sendBuff); + return FAILURE; + } + memcpy((void *)(instPtr->config.baseAddr + UART_TXBUFF_OFFSET), sendBuff, (sendLen + sizeof(uint32_t) - 1) / sizeof(uint32_t) * sizeof(uint32_t)); + free(sendBuff); + // Start Sending + SYSTEMBUS_UART_mWriteReg(instPtr->config.baseAddr, UART_SEND_CMD, sendLen); + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get last system bus frame. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * @param buff A pointer to receive data buffer. + * + * @return + * + ******************************************************************************/ +int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame) +{ + ASSERT(instPtr != NULL); + ASSERT(frame != NULL); + + uint8_t dLen, dWLen, plLen, checkSum, checkSumCal; + uint8_t *plBuff, *dBuff; + dLen = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_RECV_CNT); + if (dLen == 0 || dLen > UART_TXBUFF_MAX) + { + return EPARAM; + } + dWLen = (dLen + FRAME_HEAD_LEN + FRAME_INFO_LEN - 1) / 4 + 1; + + dBuff = malloc(sizeof(uint32_t) * dWLen); + if (dBuff == NULL) + { + return ENOMEM; + } + memcpy(dBuff, (void *)(instPtr->config.baseAddr + UART_RXBUFF_OFFSET), sizeof(uint32_t) * dWLen); + plBuff = dBuff + FRAME_HEAD_LEN; + checkSumCal = 0; + checkSum = plBuff[dLen + FRAME_DUMMY_LEN]; + plLen = 0; + for (int i = 0; i < dLen; i++) + { + if (plBuff[i + 1] == FRAME_TAIL_LOW && plBuff[i + 2] == FRAME_TAIL_HIGH) + { + continue; + } + checkSumCal += plBuff[i]; + frame->data[plLen] = plBuff[i]; + plLen++; + } + free(dBuff); + frame->len = plLen; + frame->checkSum = checkSumCal; + if (checkSumCal != checkSum) + { + frame->isValid = false; + return FAILURE; + } + frame->isValid = true; + return SUCCESS; +} + +/*****************************************************************************/ +/** + * @brief Get rx channel status. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * + * @return true - SYSBUS_UART rx channel is busy. + * false - SYSBUS_UART rx channel is idle. + * + ******************************************************************************/ +bool SysbusUart_IsRxBusy(SYSBUS_UART *instPtr) +{ + ASSERT(instPtr != NULL); + uint32_t Status; + Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS); + + if (Status & UART_STATUS_RX_BUSY) + { + return true; + } + else + { + return false; + } +} + +/*****************************************************************************/ +/** + * @brief Get tx channel status. + * + * @param instPtr A pointer to SYSBUS_UART instance structure. + * + * @return true - SYSBUS_UART tx channel is busy. + * false - SYSBUS_UART tx channel is idle. + * + ******************************************************************************/ +bool SysbusUart_IsTxBusy(SYSBUS_UART *instPtr) +{ + ASSERT(instPtr != NULL); + uint32_t Status; + Status = SYSTEMBUS_UART_mReadReg(instPtr->config.baseAddr, UART_STATUS); + if (Status & UART_STATUS_TX_BUSY) + { + return true; + } + else + { + return false; + } +} + +/** @} SystemBus_UART*/ + +/** @} SystemBus*/ \ No newline at end of file diff --git a/df_datalink_ge/src/systembus/systembus_uart.h b/df_datalink_ge/src/systembus/systembus_uart.h new file mode 100644 index 0000000..a86c290 --- /dev/null +++ b/df_datalink_ge/src/systembus/systembus_uart.h @@ -0,0 +1,122 @@ +/*****************************************************************************/ +/** + * @file systembus_uart.h + * @author FanHao (hao_fan_bit_ee@163.com) + * @brief System bus uart driver header file. + * @version 0.1 + * @date 2023-05-06 + * + * @copyright Copyright(c) 2024 Beijing Institute of Technology.\n + * Lab of Communication and Network + * + ******************************************************************************/ + +/** + * @addtogroup SystemBus + * @{ + */ + +/** + * @defgroup SystemBus_UART + * @{ + */ +#ifndef SYSTEMBUS_UART_H +#define SYSTEMBUS_UART_H + +/****************** Include Files ********************/ +#include +#include +#include "util.h" +/**************************** Type Definitions *****************************/ +/** + * + * Write a value to a SYSTEMBUS_UART register. A 32 bit write is performed. + * If the component is implemented in a smaller width, only the least + * significant data is written. + * + * @param baseAddr is the base address of the SYSTEMBUS_UARTdevice. + * @param offset is the register offset from the base to write to. + * @param data is the data written to the register. + * + * @return None. + * + * @note + * C-style signature: + * void SYSTEMBUS_UART_mWriteReg(uint32_t BaseAddress, unsigned RegOffset, uint32_t Data) + * + */ +#define SYSTEMBUS_UART_mWriteReg(baseAddr, offset, data) \ + IO_Out32((baseAddr) + (offset), (uint32_t)(data)) + +/** + * + * Read a value from a SYSTEMBUS_UART register. A 32 bit read is performed. + * If the component is implemented in a smaller width, only the least + * significant data is read from the register. The most significant data + * will be read as 0. + * + * @param baseAddr is the base address of the SYSTEMBUS_UART device. + * @param offset is the register offset from the base to write to. + * + * @return Data is the data from the register. + * + * @note + * C-style signature: + * uint32_t SYSTEMBUS_UART_mReadReg(uint32_t BaseAddress, unsigned RegOffset) + * + */ +#define SYSTEMBUS_UART_mReadReg(baseAddr, offset) \ + IO_In32((baseAddr) + (offset)) + +/************************** Data Type Definitions ****************************/ +/** + * @struct SYSBUS_UART_CONFIG + * @brief SystemBus UART driver initialization parameters + */ +typedef struct +{ + uintptr_t baseAddr; +} SYSBUS_UART_CONFIG; + +/** + * @struct SYSBUS_UART + * @brief SystemBus UART driver instance + */ +typedef struct +{ + SYSBUS_UART_CONFIG config; +} SYSBUS_UART; + +/** + * @struct SYSBUS_UART_FRAME + * @brief SystemBus UART frame definition + */ +typedef struct +{ + uint16_t len; + uint8_t checkSum; + uint8_t isValid; + uint8_t data[256]; +} SYSBUS_UART_FRAME; + +/************************** Function Prototypes ******************************/ +// Instance initial +int SysbusUart_Init(SYSBUS_UART **instPtr, SYSBUS_UART_CONFIG *config); + +// Send a system bus frame. +int SysbusUart_Send(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame); + +// Get last system bus frame. +int SysbusUart_Recv(SYSBUS_UART *instPtr, SYSBUS_UART_FRAME *frame); + +// Get system bus rx channel status. +bool SysbusUart_IsRxBusy(SYSBUS_UART *instPtr); + +// Get system bus tx channel status. +bool SysbusUart_IsTxBusy(SYSBUS_UART *instPtr); + +#endif // SYSTEMBUS_UART_H + +/** @} SystemBus_UART*/ + +/** @} SystemBus*/ \ No newline at end of file