Author SHA1 Message Date
josh 0c5fc1ec2b feat: 根据HJSL硬件修改相关profile 2025-05-13 15:45:59 +08:00
14 changed files with 1360 additions and 956 deletions
+62 -63
View File
@@ -23,7 +23,7 @@
#include "xparameters.h"
/******** Software Version ********/
#define _APP_VER 0x00010008
#define _APP_VER 0x00010000
#define _APP_VER_MAIN ((_APP_VER & 0xFF000000) >> 24)
#define _APP_VER_MINOR ((_APP_VER & 0x00FF0000) >> 16)
@@ -92,16 +92,6 @@
#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 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_SPI_CS_AD9361_1 0x01
#define AD9361_SPI_CS_AD9361_2 0x02
#define AD9361_TIMEOUT_TH 2000
// AD9361 GPIO Configurations
#define AD9361_GPIO_DEVICE_ID 0
#define AD9361_GPIO_OFFSET 54
@@ -109,57 +99,50 @@
#define AD9361_GPIO_OUTPUT 1
#define AD9361_GPIO_DISABLE 0
#define AD9361_GPIO_ENABLE 1
// -- AD9361-1
#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
#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;
// -- AD9361 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
// -- AD9361-1 GPIO
#define AD9361_1_TXNRX (AD9361_GPIO_OFFSET + 4)
#define AD9361_1_ENABLE (AD9361_GPIO_OFFSET + 5)
#define AD9361_1_EN_AGC (AD9361_GPIO_OFFSET + 6)
#define AD9361_1_RESET_B (AD9361_GPIO_OFFSET + 7)
#define AD9361_1_CTRL_OUT0 (AD9361_GPIO_OFFSET + 8)
#define AD9361_1_CTRL_OUT1 (AD9361_GPIO_OFFSET + 9)
#define AD9361_1_CTRL_OUT2 (AD9361_GPIO_OFFSET + 10)
#define AD9361_1_CTRL_OUT3 (AD9361_GPIO_OFFSET + 11)
#define AD9361_1_CTRL_OUT4 (AD9361_GPIO_OFFSET + 12)
#define AD9361_1_CTRL_OUT5 (AD9361_GPIO_OFFSET + 13)
#define AD9361_1_CTRL_OUT6 (AD9361_GPIO_OFFSET + 14)
#define AD9361_1_CTRL_OUT7 (AD9361_GPIO_OFFSET + 15)
#define AD9361_1_CTRL_IN0 (AD9361_GPIO_OFFSET + 16)
#define AD9361_1_CTRL_IN1 (AD9361_GPIO_OFFSET + 17)
#define AD9361_1_CTRL_IN2 (AD9361_GPIO_OFFSET + 18)
#define AD9361_1_CTRL_IN3 (AD9361_GPIO_OFFSET + 19)
// -- AD9361-2 GPIO
#define AD9361_2_TXNRX (AD9361_GPIO_OFFSET + 20)
#define AD9361_2_ENABLE (AD9361_GPIO_OFFSET + 21)
#define AD9361_2_EN_AGC (AD9361_GPIO_OFFSET + 22)
#define AD9361_2_RESET_B (AD9361_GPIO_OFFSET + 23)
#define AD9361_2_CTRL_OUT0 (AD9361_GPIO_OFFSET + 24)
#define AD9361_2_CTRL_OUT1 (AD9361_GPIO_OFFSET + 25)
#define AD9361_2_CTRL_OUT2 (AD9361_GPIO_OFFSET + 26)
#define AD9361_2_CTRL_OUT3 (AD9361_GPIO_OFFSET + 27)
#define AD9361_2_CTRL_OUT4 (AD9361_GPIO_OFFSET + 28)
#define AD9361_2_CTRL_OUT5 (AD9361_GPIO_OFFSET + 29)
#define AD9361_2_CTRL_OUT6 (AD9361_GPIO_OFFSET + 30)
#define AD9361_2_CTRL_OUT7 (AD9361_GPIO_OFFSET + 31)
#define AD9361_2_CTRL_IN0 (AD9361_GPIO_OFFSET + 32)
#define AD9361_2_CTRL_IN1 (AD9361_GPIO_OFFSET + 33)
#define AD9361_2_CTRL_IN2 (AD9361_GPIO_OFFSET + 34)
#define AD9361_2_CTRL_IN3 (AD9361_GPIO_OFFSET + 35)
// HMC7044 Configurations
#define HMC7044_GPIO_DEVICE_ID 0
@@ -177,7 +160,23 @@ typedef enum
#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
#define HMC7044_SPI_CS 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
// Configuration Check
#if defined(PHY_BEAM_SET_PRESET) && !defined(PHY_BEAM_FORMING_ENABLE)
@@ -273,7 +273,7 @@ AD9361_InitParam ad9361_default_init_param = {
{
.device_id = AD9361_SPI_DEVICE_ID,
.mode = SPI_MODE_1,
.chip_select = AD9361_SPI_CS_AD9361_1,
.chip_select = AD9361_1_SPI_CS,
.platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param
},
@@ -25,7 +25,7 @@ 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_SPI_CS_AD9361_1,
.chip_select = AD9361_1_SPI_CS,
.platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param
};
@@ -35,6 +35,7 @@ static struct gpio_init_param ad9361_1_reg_gpio_resetb_init = {
.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,
@@ -46,7 +47,7 @@ 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_SPI_CS_AD9361_2,
.chip_select = AD9361_2_SPI_CS,
.platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param
};
@@ -56,6 +57,7 @@ static struct gpio_init_param ad9361_2_reg_gpio_resetb_init = {
.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,
@@ -72,7 +74,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
// generated using the AD9361 Customer software Version 2.1.3
//************************************************************
// Profile: Custom
// REFCLK_IN: 25.000 MHz
// REFCLK_IN: 40.000 MHz
status = ad9361_reg_write(dev, 0x03DF, 0x01); // Required for proper operation
@@ -87,527 +89,40 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
// 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, 0x03); // Set BBPLL Loop Filter Charge Pump current
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, 0x66); // BBPLL Freq Word (Fractional[7:0])
status = ad9361_reg_write(dev, 0x0042, 0x46); // BBPLL Freq Word (Fractional[15:8])
status = ad9361_reg_write(dev, 0x0041, 0x01); // BBPLL Freq Word (Fractional[23:16])
status = ad9361_reg_write(dev, 0x0044, 0x17); // BBPLL Freq Word (Integer[7:0])
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: 276.480 us (Done when 0x05E[7]==1)
// 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 <= AD9361_TIMEOUT_TH);
} 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, 0xE5); // Setup Rx 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
//************************************************************
// Program Rx FIR: C:\Users\josh\Desktop\Config\rx64.txt
//************************************************************
status = ad9361_reg_write(dev, 0x00F5, 0x9A); // Enable clock to Rx FIR Filter
status = ad9361_reg_write(dev, 0x00F6, 0x02); // Write Filter Gain setting
status = ad9361_reg_write(dev, 0x00F0, 0x00); // Write FIR coefficient address
status = ad9361_reg_write(dev, 0x00F1, 0x00); // Write FIR coefficient data[7:0]
status = ad9361_reg_write(dev, 0x00F2, 0x00); // Write FIR coefficient data[15:8]
status = ad9361_reg_write(dev, 0x00F5, 0x9E); // Set Write EN to push data into FIR filter register map
status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us
status = ad9361_reg_write(dev, 0x00F4, 0x00); // Dummy Write to Read only register to delay ~1us
status = ad9361_reg_write(dev, 0x00F0, 0x01);
status = ad9361_reg_write(dev, 0x00F1, 0xB6);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x02);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x03);
status = ad9361_reg_write(dev, 0x00F1, 0xEA);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x04);
status = ad9361_reg_write(dev, 0x00F1, 0x61);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x05);
status = ad9361_reg_write(dev, 0x00F1, 0xA3);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x06);
status = ad9361_reg_write(dev, 0x00F1, 0x4D);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x07);
status = ad9361_reg_write(dev, 0x00F1, 0x77);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x08);
status = ad9361_reg_write(dev, 0x00F1, 0xD5);
status = ad9361_reg_write(dev, 0x00F2, 0xFE);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x09);
status = ad9361_reg_write(dev, 0x00F1, 0x38);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0A);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0B);
status = ad9361_reg_write(dev, 0x00F1, 0xF8);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0C);
status = ad9361_reg_write(dev, 0x00F1, 0xAD);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0D);
status = ad9361_reg_write(dev, 0x00F1, 0x75);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0E);
status = ad9361_reg_write(dev, 0x00F1, 0xFD);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x0F);
status = ad9361_reg_write(dev, 0x00F1, 0xD8);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x10);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x11);
status = ad9361_reg_write(dev, 0x00F1, 0x3A);
status = ad9361_reg_write(dev, 0x00F2, 0x04);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x12);
status = ad9361_reg_write(dev, 0x00F1, 0x6B);
status = ad9361_reg_write(dev, 0x00F2, 0x05);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x13);
status = ad9361_reg_write(dev, 0x00F1, 0x51);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x14);
status = ad9361_reg_write(dev, 0x00F1, 0x80);
status = ad9361_reg_write(dev, 0x00F2, 0xFA);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x15);
status = ad9361_reg_write(dev, 0x00F1, 0x34);
status = ad9361_reg_write(dev, 0x00F2, 0xF7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x16);
status = ad9361_reg_write(dev, 0x00F1, 0x08);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x17);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x06);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x18);
status = ad9361_reg_write(dev, 0x00F1, 0x1A);
status = ad9361_reg_write(dev, 0x00F2, 0x0E);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x19);
status = ad9361_reg_write(dev, 0x00F1, 0x44);
status = ad9361_reg_write(dev, 0x00F2, 0x09);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1A);
status = ad9361_reg_write(dev, 0x00F1, 0x54);
status = ad9361_reg_write(dev, 0x00F2, 0xF8);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1B);
status = ad9361_reg_write(dev, 0x00F1, 0xD1);
status = ad9361_reg_write(dev, 0x00F2, 0xE7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1C);
status = ad9361_reg_write(dev, 0x00F1, 0xC2);
status = ad9361_reg_write(dev, 0x00F2, 0xE9);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1D);
status = ad9361_reg_write(dev, 0x00F1, 0x4F);
status = ad9361_reg_write(dev, 0x00F2, 0x08);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1E);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x3B);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x1F);
status = ad9361_reg_write(dev, 0x00F1, 0x2A);
status = ad9361_reg_write(dev, 0x00F2, 0x6C);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x20);
status = ad9361_reg_write(dev, 0x00F1, 0xFF);
status = ad9361_reg_write(dev, 0x00F2, 0x7F);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x21);
status = ad9361_reg_write(dev, 0x00F1, 0x2A);
status = ad9361_reg_write(dev, 0x00F2, 0x6C);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x22);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x3B);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x23);
status = ad9361_reg_write(dev, 0x00F1, 0x4F);
status = ad9361_reg_write(dev, 0x00F2, 0x08);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x24);
status = ad9361_reg_write(dev, 0x00F1, 0xC2);
status = ad9361_reg_write(dev, 0x00F2, 0xE9);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x25);
status = ad9361_reg_write(dev, 0x00F1, 0xD1);
status = ad9361_reg_write(dev, 0x00F2, 0xE7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x26);
status = ad9361_reg_write(dev, 0x00F1, 0x54);
status = ad9361_reg_write(dev, 0x00F2, 0xF8);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x27);
status = ad9361_reg_write(dev, 0x00F1, 0x44);
status = ad9361_reg_write(dev, 0x00F2, 0x09);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x28);
status = ad9361_reg_write(dev, 0x00F1, 0x1A);
status = ad9361_reg_write(dev, 0x00F2, 0x0E);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x29);
status = ad9361_reg_write(dev, 0x00F1, 0xB2);
status = ad9361_reg_write(dev, 0x00F2, 0x06);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2A);
status = ad9361_reg_write(dev, 0x00F1, 0x08);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2B);
status = ad9361_reg_write(dev, 0x00F1, 0x34);
status = ad9361_reg_write(dev, 0x00F2, 0xF7);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2C);
status = ad9361_reg_write(dev, 0x00F1, 0x80);
status = ad9361_reg_write(dev, 0x00F2, 0xFA);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2D);
status = ad9361_reg_write(dev, 0x00F1, 0x51);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2E);
status = ad9361_reg_write(dev, 0x00F1, 0x6B);
status = ad9361_reg_write(dev, 0x00F2, 0x05);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x2F);
status = ad9361_reg_write(dev, 0x00F1, 0x3A);
status = ad9361_reg_write(dev, 0x00F2, 0x04);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x30);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x31);
status = ad9361_reg_write(dev, 0x00F1, 0xD8);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x32);
status = ad9361_reg_write(dev, 0x00F1, 0xFD);
status = ad9361_reg_write(dev, 0x00F2, 0xFC);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x33);
status = ad9361_reg_write(dev, 0x00F1, 0x75);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x34);
status = ad9361_reg_write(dev, 0x00F1, 0xAD);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x35);
status = ad9361_reg_write(dev, 0x00F1, 0xF8);
status = ad9361_reg_write(dev, 0x00F2, 0x01);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x36);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x37);
status = ad9361_reg_write(dev, 0x00F1, 0x38);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x38);
status = ad9361_reg_write(dev, 0x00F1, 0xD5);
status = ad9361_reg_write(dev, 0x00F2, 0xFE);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x39);
status = ad9361_reg_write(dev, 0x00F1, 0x77);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3A);
status = ad9361_reg_write(dev, 0x00F1, 0x4D);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3B);
status = ad9361_reg_write(dev, 0x00F1, 0xA3);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3C);
status = ad9361_reg_write(dev, 0x00F1, 0x61);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3D);
status = ad9361_reg_write(dev, 0x00F1, 0xEA);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3E);
status = ad9361_reg_write(dev, 0x00F1, 0xA5);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x3F);
status = ad9361_reg_write(dev, 0x00F1, 0xB6);
status = ad9361_reg_write(dev, 0x00F2, 0xFF);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x40);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x41);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x42);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x43);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x44);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x45);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x46);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x47);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x48);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x49);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4A);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4B);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4C);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4D);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4E);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F0, 0x4F);
status = ad9361_reg_write(dev, 0x00F1, 0x00);
status = ad9361_reg_write(dev, 0x00F2, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x9E);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F4, 0x00);
status = ad9361_reg_write(dev, 0x00F5, 0x98); // Disable clock to Rx Filter
//************************************************************
// Setup the Parallel Port (Digital Data Interface)
//************************************************************
status = ad9361_reg_write(dev, 0x0010, 0xC8); // 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, 0x0010, 0xCC); // 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)
@@ -646,7 +161,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
//************************************************************
// Setup GPO
//************************************************************
status = ad9361_reg_write(dev, 0x003A, 0x18); // Set number of REFCLK cycles for 1us delay timer
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
@@ -683,74 +198,74 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x023D, 0x04); // Start RX CP cal
// Wait for CP cal to complete, Max RXCP Cal time: 737.280 (us)(Done when 0x244[7]==1)
// 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 <= AD9361_TIMEOUT_TH);
} 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: 737.280 (us)(Done when 0x284[7]==1)
// 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 <= AD9361_TIMEOUT_TH);
} 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: 125.000000,4125.000000 MHz
// FDD RX,TX Synth Frequency: 1268.250000,1268.250000 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, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0242, 0x0E); // 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, 0x0239, 0xC0); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0242, 0x0D); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0238, 0x70); // 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, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0251, 0x09); // 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, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x023B, 0x8F); // 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, 0x0A); // Set Synth Loop Filter R3
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, 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, 0x0279, 0xC0); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0D); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x70); // 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, 0x0291, 0x09); // 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, 0x027B, 0x8F); // 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, 0x0A); // Set Synth Loop Filter R3
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, 0x0233, 0x8D); // Write Rx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0234, 0x99); // Write Rx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0235, 0x69); // 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, 0xA0); // Write Rx Synth Integer Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0005, 0x05); // 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, 0x0231, 0x7E); // Write Rx Synth Integer Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0005, 0x22); // Set LO divider setting
status = ad9361_reg_write(dev, 0x0273, 0x8D); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x99); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x69); // 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, 0x05); // Set LO divider setting
status = ad9361_reg_write(dev, 0x0271, 0x7E); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x22); // Set LO divider setting
//************************************************************
// Program Mixer GM Sub-table
@@ -1542,12 +1057,12 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
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: 7.500000 MHz) 3dB Filter
// Corner @ 10.500000 MHz)
// RX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter
// Corner @ 28.000000 MHz)
//************************************************************
status = ad9361_reg_write(dev, 0x01FB, 0x07); // RX Freq Corner (MHz)
status = ad9361_reg_write(dev, 0x01FC, 0x40); // RX Freq Corner (Khz)
status = ad9361_reg_write(dev, 0x01F8, 0x0D); // Rx BBF Tune Divider[7:0]
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
@@ -1556,56 +1071,56 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
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: 6.884 us (Done when 0x016[7]==0)
// 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 <= AD9361_TIMEOUT_TH);
} 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: 7.500000 MHz) 3dB Filter
// Corner @ 12.000000 MHz)
// TX Baseband Filter Tuning (Real BW: 20.000000 MHz) 3dB Filter
// Corner @ 32.000000 MHz)
//************************************************************
status = ad9361_reg_write(dev, 0x00D6, 0x0B); // TX BBF Tune Divider[7:0]
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: 3.390 us (Done when 0x016[6]==0)
// 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 <= AD9361_TIMEOUT_TH);
} 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, 0x60); // Set TIA selcc[2:0]
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, 0x72); // Set RX TIA1 C LSB[5:0]
status = ad9361_reg_write(dev, 0x01DE, 0x72); // Set RX TIA2 C LSB[5: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
// 7.500000MHz, 3dB Corner @ 37.500000MHz
// 20.000000MHz, 3dB Corner @ 100.000000MHz
//************************************************************
status = ad9361_reg_write(dev, 0x00D2, 0x1E); // TX Secondary Filter PDF Cap cal[5:0]
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, 0x56); // Pdampbias
status = ad9361_reg_write(dev, 0x00D0, 0x57); // Pdampbias
//************************************************************
// ADC Setup: Tune ADC Performance based on RX analog filter tune
// corner. Real Bandwidth: 6.982753 MHz, ADC Clock Frequency:
// 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.
//************************************************************
@@ -1617,23 +1132,23 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
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, 0x7C);
status = ad9361_reg_write(dev, 0x0208, 0x46);
status = ad9361_reg_write(dev, 0x0209, 0x3C);
status = ad9361_reg_write(dev, 0x020A, 0x4C);
status = ad9361_reg_write(dev, 0x020B, 0x2C);
status = ad9361_reg_write(dev, 0x020C, 0x4F);
status = ad9361_reg_write(dev, 0x020D, 0x2A);
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, 0x7F);
status = ad9361_reg_write(dev, 0x0210, 0x7F);
status = ad9361_reg_write(dev, 0x0211, 0x7F);
status = ad9361_reg_write(dev, 0x0212, 0x4A);
status = ad9361_reg_write(dev, 0x0213, 0x4A);
status = ad9361_reg_write(dev, 0x0214, 0x4A);
status = ad9361_reg_write(dev, 0x0215, 0x4D);
status = ad9361_reg_write(dev, 0x0216, 0x4D);
status = ad9361_reg_write(dev, 0x0217, 0x4D);
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);
@@ -1664,7 +1179,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms
time_out_cnt++;
} while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
} 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]
@@ -1680,21 +1195,21 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms
time_out_cnt++;
} while((value & 0x01) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
} while((value & 0x01) != 0x00 && time_out_cnt <= TIMEOUT_TH);
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x15); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0x00); // Set TxQuadcal NCO frequency (Only update bits [7:6])
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, 0x28); // Set Tx Quad Cal Gain Table index
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, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used
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
@@ -1705,7 +1220,7 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1);// Wait 1ms
time_out_cnt++;
} while((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
} 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
@@ -1736,11 +1251,5 @@ uint32_t ad9361_reg_config(struct ad9361_reg_dev *dev){
status = ad9361_reg_write(dev, 0x0158, 0x0D); // RSSI Mode Select
status = ad9361_reg_write(dev, 0x015C, 0x67); // Power Measurement Duration
//************************************************************
// Enable External LO & External VCO Buffer
//************************************************************
status |= ad9361_reg_write(dev, 0x0005, 0x07);
status |= ad9361_reg_write(dev, 0x0057, 0x1C);
return status;
}
@@ -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,8,5,5,
5,5,10,5
},
.outFrequency_Hz = {
200e6, 40e6, 40e6, 200e6, 200e6,
200e6, 200e6, 125e6, 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
};
@@ -6,6 +6,7 @@
#include "../drivers/rf-transceiver/ad9361/ad9361_api.h"
#include "../drivers/rf-transceiver/ad9361_reg/ad9361_reg.h"
#include "../drivers/frequency/hmc7044/hmc7044.h"
#include "../drivers/frequency/ad9528/ad9528.h"
#include "../drivers/adc/ad9694/ad9694.h"
#include "../config/app_config.h"
@@ -17,6 +18,9 @@ extern struct global_timer_init_param globaltimer_init_param;
// HMC7044
extern struct hmc7044_init_param hmc7044_default_init_param;
// AD9528
extern ad9528Init_t ad9528_default_init_param;
// AD9361
extern AD9361_InitParam ad9361_default_init_param;
extern AD9361_RXFIRConfig rx_fir_config;
@@ -23,7 +23,7 @@ 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,
.chip_select = HMC7044_SPI_CS,
.platform_ops = &spi_eng_platform_ops,
.extra = &spi_engine_param
};
@@ -42,9 +42,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false,
.output_control0_rb4_enable = true,
.force_mute_enable = false,
.driver_mode = CML,
.driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV
.out_mux_mode = HMC7044_CHANNEL_DIV
},
/* FPGA_DAC_LOGIC_CLK */
{
@@ -58,9 +58,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false,
.output_control0_rb4_enable = true,
.force_mute_enable = false,
.driver_mode = CML,
.driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV
.out_mux_mode = HMC7044_CHANNEL_DIV
},
/* B_AD9361_XTAL */
{
@@ -74,9 +74,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false,
.output_control0_rb4_enable = true,
.force_mute_enable = false,
.driver_mode = CML,
.driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV
.out_mux_mode = HMC7044_CHANNEL_DIV
},
/* AD9361_RX_EXT_LO */
{
@@ -90,9 +90,9 @@ struct hmc7044_chan_spec hmc7044_chan_spec[4] = {
.dynamic_driver_enable = false,
.output_control0_rb4_enable = true,
.force_mute_enable = false,
.driver_mode = CML,
.driver_mode = HMC7044_CML,
.driver_impedance = INTERNAL_100OHM_PER_PIN,
.out_mux_mode = CHANNEL_DIV
.out_mux_mode = HMC7044_CHANNEL_DIV
},
};
@@ -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 <stdlib.h>
#include <stdio.h>
#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
*
* <B>Dependencies</B>
* - 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.
*
* <B>Dependencies</B>
* - 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.
*
* <B>Dependencies</B>
* - 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
*
* <B>Dependencies</B>
* - 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, &reg508);
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.
* <B>Dependencies</B>
* - 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.
*
* <B>Dependencies</B>
* - 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, &reg403);
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;
}
@@ -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 <stdint.h>
#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
@@ -75,10 +75,10 @@ typedef enum
// 0x0148, 0x0152)
typedef enum
{
CML = 0,
LVPECL = 1,
LVDS = 2,
CMOS = 3
HMC7044_CML = 0,
HMC7044_LVPECL = 1,
HMC7044_LVDS = 2,
HMC7044_CMOS = 3
} hmc7044DriverMode_t;
// Enum to select the GPIx functionality. (0x0046, 0x0047, 0x0048, 0x0049)
@@ -154,7 +154,7 @@ typedef enum
// 0x0101, 0x010B, 0x0115, 0x011F, 0x0129, 0x0133, 0x013D, 0x0147, 0x0151
typedef enum
{
CHANNEL_DIV = 0,
HMC7044_CHANNEL_DIV = 0,
ANALOG_DELAY = 1,
OTHER_CHANNEL = 2,
VCO_CLOCK = 3
+17 -286
View File
@@ -34,7 +34,7 @@
/************************** Function Prototypes ******************************/
/*********************** Driver Instance Definitions **************************/
static struct hmc7044_dev *hmc7044_inst = NULL;
ad9528Device_t *ad9528_inst = NULL;
static struct ad9361_reg_dev *ad9361_1_reg_inst = NULL;
static struct ad9361_reg_dev *ad9361_2_reg_inst = NULL;
// static struct ad9361_rf_phy *ad9361_phy;
@@ -62,12 +62,17 @@ int32_t Hardware_Init(void)
}
/**********************************************************/
/****************** HMC7044 Configuration *****************/
/****************** AD9528 Configuration ******************/
/**********************************************************/
Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param);
if (Status != SUCCESS)
{
DBG_ERROR("hmc7044_init() error: %" PRId32 "\n", Status);
Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param);
if (Status != SUCCESS) {
DBG_ERROR("AD9528_init() error: %" PRId32 "\n", Status);
return FAILURE;
}
Status = AD9528_config(ad9528_inst);
if (Status != SUCCESS) {
DBG_ERROR("AD9528_config() error: %" PRId32 "\n", Status);
return FAILURE;
}
@@ -110,110 +115,6 @@ int32_t Hardware_Init(void)
// 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, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x010C, 0x00); // Rx Gain
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0109, 0x00); // Rx Gain
@@ -224,176 +125,6 @@ int32_t Hardware_Init(void)
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.
@@ -453,22 +184,22 @@ uint8_t Hardware_GetAD9361LockStatus(void)
return ret;
}
// @ Determine HMC7044 lock state
// @ Determine AD9528 lock state
/**
* Read corresponding register to determine clock lock state.
*/
uint8_t Hardware_GetHMC7044LockStatus(void)
uint8_t Hardware_GetAD9528LockStatus(void)
{
uint8_t ret = 0;
uint8_t regVal;
// pll1
hmc7044_read(hmc7044_inst, 0x007C, &regVal); // [D5] is lock indicator
ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0;
AD9528_spiReadByte(ad9528_inst, AD9528_ADDR_STATUS_READBACK0, &regVal); // [D0] is lock indicator
ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0;
// pll2
hmc7044_read(hmc7044_inst, 0x007D, &regVal); // [D0] is lock indicator
ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0;
AD9528_spiReadByte(ad9528_inst, AD9528_ADDR_STATUS_READBACK0, &regVal); // [D1] is lock indicator
ret |= ((regVal & 0x02) == 0x02) ? CLK_SP_PLL2_LOCK : 0;
return ret;
}
+1 -2
View File
@@ -24,10 +24,9 @@
/************************** 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);
uint8_t Hardware_GetAD9528LockStatus(void);
#endif // HWCONFIG_H_
+1 -1
View File
@@ -98,7 +98,7 @@ static PHY_CONFIG phyConfig = {
.txBramId = PHY_TXBUFF_BRAM_DEVICE_ID,
.rxBramId = PHY_RXBUFF_BRAM_DEVICE_ID,
.hwXadcId = PHY_HW_XADC_DEVICE_ID,
.get_clk_state = Hardware_GetHMC7044LockStatus,
.get_clk_state = Hardware_GetAD9528LockStatus,
.get_ad_lock_state = Hardware_GetAD9361LockStatus,
.get_ad0_temp = Hardware_GetAD9361Temp_1,
.get_ad1_temp = Hardware_GetAD9361Temp_2
@@ -1116,7 +1116,7 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
? INT8_MAX
: ((evalData < TEMPERATURE_MIN) ? INT8_MIN : (int8_t)round(evalData / TEMPERATURE_LSB));
instPtr->hwSate.isSpOk = (instPtr->hwSate.spFpgaVolt == (VOLT_PS_OK | VOLT_PSAUX_OK | VOLT_DDR_OK | VOLT_PL_OK | VOLT_PLAUX_OK | VOLT_BRAM_OK))
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL0_LOCK | CLK_SP_PLL1_LOCK))
&& (instPtr->hwSate.spClkState == (CLK_SP_PLL1_LOCK | CLK_SP_PLL2_LOCK))
&& (instPtr->hwSate.spAdLockState == (CLK_AD0_BBPLL_LOCK | CLK_AD0_RFPLL_LOCK | CLK_AD1_BBPLL_LOCK | CLK_AD1_RFPLL_LOCK));
#else
instPtr->hwSate.isSpOk = true;
@@ -1142,8 +1142,8 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
// [2] - PLLA lock status
// [4] - PLLB lock status
instPtr->hwSate.antPll = ((rawData & ANT_RF_STATUS_BBLOCK_MASK) == ANT_RF_STATUS_BBLOCK_OK) ? CLK_ANT_BBPLL_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLA_MASK) == ANT_RF_STATUS_PLLA_OK) ? CLK_ANT_RFPLL0_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLB_MASK) == ANT_RF_STATUS_PLLB_OK) ? CLK_ANT_RFPLL1_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLA_MASK) == ANT_RF_STATUS_PLLA_OK) ? CLK_ANT_RFPLL1_LOCK : 0x00;
instPtr->hwSate.antPll |= ((rawData & ANT_RF_STATUS_PLLB_MASK) == ANT_RF_STATUS_PLLB_OK) ? CLK_ANT_RFPLL2_LOCK : 0x00;
/*** MGCs ***/
rawData = PhyRead(instPtr, ANT_RF_MGC);
@@ -1159,7 +1159,7 @@ void Phy_RefreshHwSate(PHY_INST *instPtr)
// Determin if antenna is ok.
instPtr->hwSate.isAntOk = (instPtr->hwSate.antVolt == (VOLT_ANT_PROC_OK | VOLT_ANT_RF_OK | VOLT_ANT_NIL_OK | ANT_STATE_OK))
&& (instPtr->hwSate.antPll == (CLK_ANT_BBPLL_LOCK | CLK_ANT_RFPLL0_LOCK | CLK_ANT_RFPLL1_LOCK));
&& (instPtr->hwSate.antPll == (CLK_ANT_BBPLL_LOCK | CLK_ANT_RFPLL1_LOCK | CLK_ANT_RFPLL2_LOCK));
instPtr->hwSate.phyId = instPtr->phyCofig.devId;
+4 -4
View File
@@ -61,8 +61,8 @@
#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_PLL0_LOCK BIT(0)
#define CLK_SP_PLL1_LOCK BIT(2)
#define CLK_SP_PLL1_LOCK BIT(0)
#define CLK_SP_PLL2_LOCK BIT(2)
#define CLK_AD0_BBPLL_LOCK BIT(0)
#define CLK_AD0_RFPLL_LOCK BIT(2)
@@ -70,8 +70,8 @@
#define CLK_AD1_RFPLL_LOCK BIT(6)
#define CLK_ANT_BBPLL_LOCK BIT(0)
#define CLK_ANT_RFPLL0_LOCK BIT(2)
#define CLK_ANT_RFPLL1_LOCK BIT(4)
#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