Files
brd_cx9261a/zc706_cx9261a_demo/vitis_classic_autobuild/source/hwconfig.c
T

902 lines
34 KiB
C

/*****************************************************************************/
/**
* Description: hwconfig.h
*
* Date: 2024-02-20 13:19
* Last Edit Time: [2024-02-20 13:19]
*
* Revisions: Rev 0.0
* History:
* [2023-05-07]: Initial edition.
*
* Copyright(c) 2024 Beijing Institute of Technology.
*
******************************************************************************/
/***************************** Include Files *********************************/
// Standard
#include <stdint.h>
#include <stdbool.h>
// Xilinx
#include "xgpiops.h"
#include "drivers/axi_core/spi_engine/spi_engine.h"
// App
#include "common.h"
#include "error.h"
#include "delay.h"
#include "system_monitor.h"
#include "hwconfig.h"
#include "config/app_config.h"
#include "dev_profile/dev_profile.h"
#ifdef RFSOC
#include "xrfdc.h"
#endif
/************************** Function Prototypes ******************************/
/*********************** Driver Instance Definitions **************************/
static struct hmc7044_dev *hmc7044_inst;
ad9528Device_t *ad9528_inst;
static struct lmk04828_dev *lmk04828_inst;
static struct lmx2594_dev *lmx2594_adc_inst;
static struct lmx2594_dev *lmx2594_dac_inst;
static struct ad9361_reg_dev *ad9361_1_reg_inst;
static struct ad9361_reg_dev *ad9361_2_reg_inst;
static struct cx9261a_dev *cx9261a_inst;
static struct ad9361_rf_phy *ad9361_phy;
static struct ad9653_dev *ad9653_inst;
static struct ad9694_dev *ad9694_inst;
XGpioPs Gpio;
#ifdef RFSOC
XRFdc RFdc;
#endif
/*****************************************************************************/
/**
* @brief Hardware_SwitchFreq
*
* @param devSysMonitor_UpdateHardwareStatus(newHwState);
* @param freq
*
* @return None.
*
******************************************************************************/
int32_t Hardware_SwitchFreq(struct ad9361_reg_dev *dev, ad9361TxFreq freq)
{
int32_t status = 0;
uint8_t value = 0;
int32_t time_out_cnt = 0;
switch (freq)
{
case TX_FREQ_125:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x94); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Tx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA0); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
case TX_FREQ_126:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Tx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x06); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0xD7); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x23); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA1); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x57); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x22); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x00); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
case TX_FREQ_4125:
{
//************************************************************
// Setup Tx Frequency-Dependent Syntheisizer Registers
//************************************************************
status = ad9361_reg_write(dev, 0x027A, 0x4A); // Set VCO Output level[3:0]
status = ad9361_reg_write(dev, 0x0279, 0xC1); // Set Init ALC Value[3:0] and VCO Varactor[3:0]
status = ad9361_reg_write(dev, 0x0282, 0x0E); // Set VCO Bias Tcf[1:0] and VCO Bias Ref[2:0]
status = ad9361_reg_write(dev, 0x0278, 0x78); // Set VCO Cal Offset[3:0]
status = ad9361_reg_write(dev, 0x0285, 0x00); // Set VCO Cal Ref Tcf[2:0]
status = ad9361_reg_write(dev, 0x0291, 0x0B); // Set VCO Varactor Reference[3:0]
status = ad9361_reg_write(dev, 0x0290, 0x70); // Set VCO Varactor Ref Tcf[2:0] and VCO Varactor Offset[3:0]
status = ad9361_reg_write(dev, 0x027B, 0x93); // Set Synth Loop Filter charge pump current (Icp)
status = ad9361_reg_write(dev, 0x027E, 0xF4); // Set Synth Loop Filter C2 and C1
status = ad9361_reg_write(dev, 0x027F, 0xDF); // Set Synth Loop Filter R1 and C3
status = ad9361_reg_write(dev, 0x0280, 0x0A); // Set Synth Loop Filter R3
//************************************************************
// Write Rx Frequency Words
//************************************************************
status = ad9361_reg_write(dev, 0x0273, 0x00); // Write Tx Synth Fractional Freq Word[7:0]
status = ad9361_reg_write(dev, 0x0274, 0x00); // Write Tx Synth Fractional Freq Word[15:8]
status = ad9361_reg_write(dev, 0x0275, 0x00); // Write Tx Synth Fractional Freq Word[22:16]
status = ad9361_reg_write(dev, 0x0272, 0x00); // Write Tx Synth Integer Freq Word[10:8]
status = ad9361_reg_write(dev, 0x0271, 0xA5); // Write Tx Synth Integer Freq Word[7:0] (starts VCO cal)
status = ad9361_reg_write(dev, 0x0005, 0x07); // Set LO divider setting
//************************************************************
// Tx Quadrature Calibration Settings
//************************************************************
status = ad9361_reg_write(dev, 0x00A0, 0x75); // Set TxQuadcal NCO frequency
status = ad9361_reg_write(dev, 0x00A3, 0xC0); // Set TxQuadcal NCO frequency (Only update bits [7:6])
status = ad9361_reg_write(dev, 0x00A1, 0x7B); // Tx Quad Cal Configuration, Phase and Gain Cal Enable
status = ad9361_reg_write(dev, 0x00A9, 0xFF); // Set Tx Quad Cal Count
status = ad9361_reg_write(dev, 0x00A2, 0x7F); // Set Tx Quad Cal Kexp
status = ad9361_reg_write(dev, 0x00A5, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00A6, 0x01); // Set Tx Quad Cal Magnitude Threshhold
status = ad9361_reg_write(dev, 0x00AA, 0x28); // Set Tx Quad Cal Gain Table index
status = ad9361_reg_write(dev, 0x00A4, 0xF0); // Set Tx Quad Cal Settle Count
status = ad9361_reg_write(dev, 0x00AE, 0x04); // Set Tx Quad Cal LPF Gain index incase Split table mode used
status = ad9361_reg_write(dev, 0x0169, 0xC0); // Disable Rx Quadrature Calibration before Running Tx Quadrature Calibration
status = ad9361_reg_write(dev, 0x0016, 0x10); // Start Tx Quad cal
break;
}
// Wait for cal to complete (Done when 0x016[4]==0)
time_out_cnt = 0;
do
{
status |= ad9361_reg_read(dev, 0x0016, &value);
mdelay(1); // Wait 1ms
time_out_cnt++;
} while ((value & 0x10) != 0x00 && time_out_cnt <= AD9361_TIMEOUT_TH);
}
return status;
}
// @ Get AD9361 - 1 temperature (Celsius Degree)
/**
* Read corresponding register to get AD9361 - 1 current temperature.
*/
int8_t Hardware_GetAD9361Temp_1(void)
{
int8_t scaleTemp;
double temp;
ad9361_reg_write(ad9361_1_reg_inst, 0x000B, -64);
ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x01); // disable aux adc
ad9361_reg_read(ad9361_1_reg_inst, 0x000E, (uint8_t*)&scaleTemp);
ad9361_reg_write(ad9361_1_reg_inst, 0x001D, 0x00); // enable aux adc
temp = ((double)scaleTemp + 64)/1.16;
return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp);
}
// @ Get AD9361 - 2 temperature (Celsius Degree)
/**
* Read corresponding register to get AD9361 - 2 current temperature.
*/
int8_t Hardware_GetAD9361Temp_2(void)
{
int8_t scaleTemp;
double temp;
ad9361_reg_write(ad9361_2_reg_inst, 0x000B, -64);
ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x01); // disable aux adc
ad9361_reg_read(ad9361_2_reg_inst, 0x000E, (uint8_t*)&scaleTemp);
ad9361_reg_write(ad9361_2_reg_inst, 0x001D, 0x00); // enable aux adc
temp = ((double)scaleTemp + 64)/1.16;
return ((temp > INT8_MAX) ? INT8_MAX : (int8_t)temp);
}
// @ Determine AD9361 lock state
/**
* Read corresponding register to determine AD9361(both) lock state.
*/
uint8_t Hardware_GetAD9361LockStatus(void)
{
uint8_t ret = 0;
uint8_t regVal;
// bbpll
ad9361_reg_read(ad9361_1_reg_inst, 0x005E, &regVal); // [D7] is lock indicator
ret |= ((regVal & 0x80) == 0x80) ? CLK_AD0_BBPLL_LOCK : 0;
ad9361_reg_read(ad9361_2_reg_inst, 0x005E, &regVal); // [D7] is lock indicator
ret |= ((regVal & 0x80) == 0x80) ? CLK_AD1_BBPLL_LOCK : 0;
// rfpll
ad9361_reg_read(ad9361_1_reg_inst, 0x0287, &regVal); // [D1] is lock indicator
ret |= ((regVal & 0x02) == 0x02) ? CLK_AD0_RFPLL_LOCK : 0;
ad9361_reg_read(ad9361_2_reg_inst, 0x0287, &regVal); // [D1] is lock indicator
ret |= ((regVal & 0x02) == 0x02) ? CLK_AD1_RFPLL_LOCK : 0;
return ret;
}
// @ Determine HMC7044 lock state
/**
* Read corresponding register to determine clock lock state.
*/
uint8_t Hardware_GetHMC7044LockStatus(void)
{
uint8_t ret = 0;
uint8_t regVal;
// pll1
hmc7044_read(hmc7044_inst, 0x007C, &regVal); // [D5] is lock indicator
ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0;
// pll2
hmc7044_read(hmc7044_inst, 0x007D, &regVal); // [D0] is lock indicator
ret |= ((regVal & 0x01) == 0x01) ? CLK_SP_PLL1_LOCK : 0;
return ret;
}
void CX9261A_Log(const char *msg)
{
DBG_INFO("[CX9261A] %s\n", msg);
}
void CX9261A_spiWrite(int address, int value)
{
int32_t Status;
Status = cx9261a_write(cx9261a_inst,address,value);
if (Status != SUCCESS)
{
DBG_ERROR("HW: CX9261A_spiWrite() failed!");
}
}
int CX9261A_spiRead(int address)
{
int32_t Status;
uint8_t reg = 0;
Status = cx9261a_read(cx9261a_inst,address,&reg);
if (Status != SUCCESS)
{
DBG_ERROR("HW: CX9261A_spiRead() failed!");
}
return reg;
}
void CX9261A_mdelay(double ms)
{
mdelay((uint32_t)(ms));
}
void CX9261A_setPin(int pin, int value)
{
switch(pin){
case 0:
gpio_set_value(cx9261a_inst->gpio_desc_nrst, value);
break;
case 1:
gpio_set_value(cx9261a_inst->gpio_desc_enable_trx1, value);
break;
case 2:
gpio_set_value(cx9261a_inst->gpio_desc_enable_trx2, value);
break;
case 3:
gpio_set_value(cx9261a_inst->gpio_desc_enable_rxfb, value);
break;
case 4:
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx1, value);
break;
case 5:
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_trx2, value);
break;
case 6:
gpio_set_value(cx9261a_inst->gpio_desc_txnrx_rxfb, value);
break;
case 34:
gpio_set_value(cx9261a_inst->gpio_desc_pl_rst, value);
break;
case 35:
gpio_set_value(cx9261a_inst->gpio_desc_tr_sel, value);
break;
case 36:
gpio_set_value(cx9261a_inst->gpio_desc_tdd_fdd_sel, value);
break;
case 37:
gpio_set_value(cx9261a_inst->gpio_desc_r1t1_r2t2_sel, value);
break;
case 38:
gpio_set_value(cx9261a_inst->gpio_desc_sp_dp_sel, value);
break;
case 43:
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl0, value);
break;
case 44:
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl1, value);
break;
case 45:
gpio_set_value(cx9261a_inst->gpio_desc_mclk_delay_ctrl2, value);
break;
default:
break;
}
return;
}
void cx9261a_trx_ch_pll_config(u8 pll_index)
{
u8 rx_data;
u8 recv_buf[3]={0};
u32 trx_ch_pll_data;
if(pll_index==1){
trx_ch_pll_data = 0x00077DCF;
}else if(pll_index==2){
trx_ch_pll_data = 0x00077D0C;
}
cx9261a_write(cx9261a_inst,trx_ch_pll_data >> 8, trx_ch_pll_data);
}
/*****************************************************************************/
/**
* @brief Hardware_Init
*
* @param none.
*
* @return None.
*
******************************************************************************/
int32_t Hardware_Init(void)
{
int32_t Status;
// gpio initialization
XGpioPs_Config *ConfigPtr;
ConfigPtr = XGpioPs_LookupConfig(AD9361_GPIO_DEVICE_ID);
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr, ConfigPtr->BaseAddr);
if (Status != SUCCESS)
{
return FAILURE;
}
#ifdef RFSOC
/**********************************************************/
/************* RF Data Converter Configuration ************/
/**********************************************************/
// rf data converter initialization
XRFdc_Config *RFdc_ConfigPtr;
RFdc_ConfigPtr = XRFdc_LookupConfig(RFDC_DEVICE_ID);
Status = XRFdc_CfgInitialize(&RFdc, RFdc_ConfigPtr);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
#endif
#ifdef HMC7044
/**********************************************************/
/****************** HMC7044 Configuration *****************/
/**********************************************************/
Status = hmc7044_init(&hmc7044_inst, &hmc7044_default_init_param);
if (Status != SUCCESS)
{
DBG_ERROR("HDWR: hmc7044_init() error: %" PRId32 "\n", Status);
return FAILURE;
}
#endif
#ifdef AD9528
/**********************************************************/
/****************** AD9528 Configuration ******************/
/**********************************************************/
Status = AD9528_init(&ad9528_inst, &ad9528_default_init_param);
if (Status != SUCCESS) {
DBG_ERROR("HDWR: AD9528_init() error: %" PRId32 "\n", Status);
return FAILURE;
}
Status = AD9528_config(ad9528_inst);
if (Status != SUCCESS) {
return FAILURE;
DBG_ERROR("HDWR: AD9528_config() error: %" PRId32 "\n", Status);
}
#endif
#ifdef LMK04828
/**********************************************************/
/***************** LMK04828 Configuration *****************/
/**********************************************************/
Status = lmk04828_init(&lmk04828_inst, &lmk04828_default_init_param);
for(int i = 0; i < lmk04828_default_config_len; i++)
{
Status = lmk04828_write(lmk04828_inst,
lmk04828_default_config[i].addr, lmk04828_default_config[i].value);
if (lmk04828_default_config[i].addr == 0x0000)
{
mdelay(500);
}
}
uint8_t Lmk04828Read;
// check pll1 lock status
Status = lmk04828_read(lmk04828_inst, 0x0182, &Lmk04828Read);
if ((Lmk04828Read & 0x02) == 0x02) {
DBG_INFO("HDWR: [LMK04828] PLL1 Locked.\r\n");
}
else {
DBG_ERROR("HDWR: [LMK04828] PLL1 NOT lock. It takes a while "
"for PLL1 to lock. Lock status is shown on LED.\r\n");
}
// check pll2 lock status
Status = lmk04828_read(lmk04828_inst, 0x0183, &Lmk04828Read);
if ((Lmk04828Read & 0x02) == 0x02) {
DBG_INFO("HDWR: [LMK04828] PLL2 Locked.\r\n");
}
else {
DBG_INFO("HDWR: [LMK04828] PLL2 NOT lock!\r\n");
}
#endif
#ifdef LMX2594_ADC
/**********************************************************/
/************* LMX2594 for ADC Configuration **************/
/**********************************************************/
Status = lmx2594_init(&lmx2594_adc_inst, &lmx2594_adc_init_param);
for(int i = 0; i < lmx2594_default_config_len; i++)
{
Status = lmx2594_write(lmx2594_adc_inst,
lmx2594_default_config[i].addr, lmx2594_default_config[i].value);
if (lmx2594_default_config[i].addr == 0)
{
mdelay(500);
}
}
uint16_t Lmx2594AdcRead;
// check vco lock status
Status = lmx2594_read(lmx2594_adc_inst, 110, &Lmx2594AdcRead);
if (((Lmx2594AdcRead >> 9) & 0x0003) == 0x0002) {
DBG_INFO("HDWR: [ADC LMX2594] Config Done.\r\n");
}
else {
DBG_INFO("HDWR: [ADC LMX2594] not lock!\r\n");
}
// set mux out to lock status
Status = lmx2594_write(lmx2594_adc_inst, 0x00, 0x259C);
DBG_INFO("HDWR: [ADC LMX2594] SPI readback disabled, "
"lock status is shown on LED.\r\n");
#endif
#ifdef LMX2594_DAC
/**********************************************************/
/************* LMX2594 for DAC Configuration **************/
/**********************************************************/
Status = lmx2594_init(&lmx2594_dac_inst, &lmx2594_dac_init_param);
for(int i = 0; i < lmx2594_default_config_len; i++)
{
Status = lmx2594_write(lmx2594_dac_inst,
lmx2594_default_config[i].addr, lmx2594_default_config[i].value);
if (lmx2594_default_config[i].addr == 0)
{
mdelay(500);
}
}
uint16_t Lmx2594DacRead;
// check vco lock status
Status = lmx2594_read(lmx2594_dac_inst, 110, &Lmx2594DacRead);
if (((Lmx2594DacRead >> 9) & 0x0003) == 0x0002) {
DBG_INFO("HDWR: [DAC LMX2594] Config Done.\r\n");
}
else {
DBG_INFO("HDWR: [DAC LMX2594] not lock!\r\n");
}
// set mux out to lock status
Status = lmx2594_write(lmx2594_dac_inst, 0x00, 0x259C);
DBG_INFO("HDWR: [DAC LMX2594] SPI readback disabled, "
"lock status is shown on LED.\r\n");
#endif
#if defined(AD9361_API) || defined(AD9361_REG)
/**********************************************************/
/***************** AD9361-1 Configuration *****************/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_TXNRX, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_ENABLE, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_EN_AGC, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_RESET_B, AD9361_GPIO_OUTPUT);
#ifdef AD9361_REG
ad9361_reg_init(&ad9361_1_reg_inst, &ad9361_1_reg_default_init_param);
XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 0);
ad9361_reg_config(ad9361_1_reg_inst);
XGpioPs_WritePin(&Gpio, AD9361_1_ENABLE, 1);
#endif
#ifdef AD9361_API
Status = ad9361_init(&ad9361_phy, &ad9361_default_init_param);
if (Status != XST_SUCCESS){
DBG_ERROR("HDWR: ad9361_init() error: %" PRId32 "\n", Status);
return XST_FAILURE;
}
ad9361_set_tx_fir_config(ad9361_phy, tx_fir_config);
ad9361_set_rx_fir_config(ad9361_phy, rx_fir_config);
#endif
/**********************************************************/
/***************** AD9361-2 Configuration *****************/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_TXNRX, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_ENABLE, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_EN_AGC, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_RESET_B, AD9361_GPIO_OUTPUT);
ad9361_reg_init(&ad9361_2_reg_inst, &ad9361_2_reg_default_init_param);
XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 0);
ad9361_reg_config(ad9361_2_reg_inst);
XGpioPs_WritePin(&Gpio, AD9361_2_ENABLE, 1);
// uint8_t rd_back;
// Status = ad9361_reg_read(ad9361_1_reg_inst, 0x0002, &rd_back);
// Status = ad9361_reg_read(ad9361_2_reg_inst, 0x0002, &rd_back);
/**********************************************************/
/******* AD9361 Baseband Multichip Synchronization ********/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_SYNC, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_RX_FIFO_RST, AD9361_GPIO_OUTPUT);
// SYNC BBPLL and DIGITAL SAMPLING CLOCKS
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0D); // MCS RF Enable; MCS BBPLL Enable; MCS BB Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0D);
ad9361_reg_write(ad9361_1_reg_inst, 0x0047, 0x80); // MCS refclk Scale Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0047, 0x80);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input a rising-edge pulse to the SYNC_IN pin
mdelay(500);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
mdelay(2000);
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x0B); // MCS RF Enable; MCS Digital CLK Enable ; MCS BB Enable
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x0B);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 1); // Input another rising-edge pulse to the SYNC_IN pin
mdelay(500);
XGpioPs_WritePin(&Gpio, AD9361_SYNC, 0);
ad9361_reg_write(ad9361_1_reg_inst, 0x0001, 0x08); // clear MCS bits
ad9361_reg_write(ad9361_2_reg_inst, 0x0001, 0x08);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 1);
mdelay(20);
XGpioPs_WritePin(&Gpio, AD9361_RX_FIFO_RST, 0);
/**********************************************************/
/********* AD9361 Multichip Rx Phase Calibration **********/
/**********************************************************/
XGpioPs_SetDirectionPin(&Gpio, AD9361_TX_SWITCH, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_START, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_1_CAL_DONE, AD9361_GPIO_INPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_START, AD9361_GPIO_OUTPUT);
XGpioPs_SetDirectionPin(&Gpio, AD9361_2_CAL_DONE, AD9361_GPIO_INPUT);
// switch to lower frequency
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_126);
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 1);
mdelay(20);
// switch rx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x30);
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x30);
// enable dual ad9361 tx channels
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xE4); // Setup Tx Digital Filters/ Channels
// switch ad9361 tx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x70); // Select Rx input pin(A,B,C)/ Tx out pin (A,B)
mdelay(20);
// begin to calibrate the 1st ad9361
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 1);
mdelay(1);
XGpioPs_WritePin(&Gpio, AD9361_1_CAL_START, 0);
// read calibration status
int32_t time_out_cnt = 0;
do
{
mdelay(1); // Wait 1ms
time_out_cnt++;
} while (((XGpioPs_ReadPin(&Gpio, AD9361_1_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
if (time_out_cnt == AD9361_TIMEOUT_TH)
{
return FAILURE;
}
// begin to calibrate the 2nd ad9361
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 1);
mdelay(1);
XGpioPs_WritePin(&Gpio, AD9361_2_CAL_START, 0);
// read calibration status
time_out_cnt = 0;
do
{
mdelay(1); // Wait 1ms
time_out_cnt++;
} while (((XGpioPs_ReadPin(&Gpio, AD9361_2_CAL_DONE) == 0) && time_out_cnt <= AD9361_TIMEOUT_TH));
if (time_out_cnt == AD9361_TIMEOUT_TH)
{
return FAILURE;
}
// enable single ad9361 tx channels
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0002, 0xA4); // Setup Tx Digital Filters/ Channels
// switch ad9361 tx & rx channel
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0004, 0x03);
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x0004, 0x03);
// switch to higher frequency
Status = Hardware_SwitchFreq(ad9361_1_reg_inst, TX_FREQ_4125);
XGpioPs_WritePin(&Gpio, AD9361_TX_SWITCH, 0);
Status = ad9361_reg_write(ad9361_1_reg_inst, 0x0109, 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
Status = ad9361_reg_write(ad9361_2_reg_inst, 0x010C, 0x00); // Rx Gain
#endif
#ifdef AD9653
/**********************************************************/
/****************** AD9653 Configuration ******************/
/**********************************************************/
Status = ad9653_init(&ad9653_inst, &ad9653_default_init_param);
for(int i = 0; i < ad9653_default_config_len; i++){
Status = ad9653_write(ad9653_inst, ad9653_default_config[i].addr,
ad9653_default_config[i].value);
if (ad9653_default_config[i].addr == 0x0000){
mdelay(500);
}
}
#endif
#ifdef AD9694
/**********************************************************/
/****************** AD9694 Configuration ******************/
/**********************************************************/
Status = ad9694_init(&ad9694_inst, &ad9694_default_init_param);
for(int i = 0; i < ad9694_default_config_len; i++){
Status = ad9694_write(ad9694_inst, ad9694_default_config[i].addr, ad9694_default_config[i].value);
if (ad9694_default_config[i].addr == 0x0000){
mdelay(500);
}
}
// uint8_t reg0008;
// uint8_t reg056F;
// uint8_t reg0571;
//
// ad9694_read(ad9694_inst,0x008,&reg0008);
// ad9694_read(ad9694_inst,0x56F,&reg056F);
// ad9694_read(ad9694_inst,0x571,&reg0571);
#endif
#ifdef CX9261A
/**********************************************************/
/***************** CX9261A Configuration ******************/
/**********************************************************/
cx9261a_init(&cx9261a_inst, &cx9261a_default_init_param);
// 绑定函数
CX9261A_setLoggingFunc(CX9261A_Log);
CX9261A_setWriteSpiFunc(CX9261A_spiWrite);
CX9261A_setReadSpiFunc(CX9261A_spiRead);
CX9261A_setPauseFunc(CX9261A_mdelay);
CX9261A_setSetPinFunc(CX9261A_setPin);
// 开始配置芯片
CX9261A_initialChip(); // 最开始需要调用此函数
int reg;
reg = CX9261A_spiRead(0x000);
CX9261A_initialPowerConfig(&cx9261a_configuration);
// 配置温补
CX9261A_configTemperatureCompensation(cx9261a_configuration.tempComp);
// 不需要自定义电源管理时,这部分代码可以省略
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.rxPower), CX9261A_PWM_Receive);
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.txPower), CX9261A_PWM_Transmit);
CX9261A_configPowerPins(&(cx9261a_configuration.powerManagement.fddPower), CX9261A_PWM_Duplex);
// 配置pll
CX9261A_configBBPLL(&cx9261a_configuration);
CX9261A_configPllSource(&(cx9261a_configuration.pllSource));
CX9261A_configPll1(cx9261a_configuration.pllFreq.pll1Freq, &(cx9261a_configuration.clock));
CX9261A_configPll2(cx9261a_configuration.pllFreq.pll2Freq, &(cx9261a_configuration.clock));
// 配置Rx通道
CX9261A_configRxChannel(&(cx9261a_configuration.rx1Config), CX9261A_RXCH_Rx1);
CX9261A_configRxChannel(&(cx9261a_configuration.rx2Config), CX9261A_RXCH_Rx2);
CX9261A_configRxChannel(&(cx9261a_configuration.rx3Config), CX9261A_RXCH_Rx3);
// 配置Tx通道
CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll1Freq, CX9261A_TXCH_Tx1);
CX9261A_configTxChannelFrequency(cx9261a_configuration.pllFreq.pll2Freq, CX9261A_TXCH_Tx2);
CX9261A_configTxChannel(&(cx9261a_configuration.tx1Config), CX9261A_TXCH_Tx1);
CX9261A_configTxChannel(&(cx9261a_configuration.tx2Config), CX9261A_TXCH_Tx2);
// 配置滤波器
CX9261A_configRxFilters(&(cx9261a_configuration.rxFilters));
CX9261A_configTxFilters(&(cx9261a_configuration.txFilters));
// 配置NCO
CX9261A_configRxNco(&(cx9261a_configuration.rxNco), cx9261a_configuration.clock.adc);
int filters = max(cx9261a_configuration.rxFilters.fir, 1) * max(cx9261a_configuration.rxFilters.hbf3, 1) *
max(cx9261a_configuration.rxFilters.hbf2, 1) *
max(cx9261a_configuration.rxFilters.hbf1, 1) * max(cx9261a_configuration.rxFilters.cic, 1);
CX9261A_configTxNco(&(cx9261a_configuration.txNco), cx9261a_configuration.clock.adc / filters);
// 配置AGC
CX9261A_configAGC(&(cx9261a_configuration.agc));
// 切换到休眠模式
CX9261A_configPowerMode(CX9261A_PWM_Sleep);
CX9261A_mdelay(1000);
// 切换到校准模式
CX9261A_configPowerMode(CX9261A_PWM_Calib);
CX9261A_mdelay(100);
// 锁定BBPLL
while (!CX9261A_afcBBPll());
// 锁定PLL1
while(!CX9261A_afcPll1());
// 锁定PLL2
while(!CX9261A_afcPll2());
// 配置接口
CX9261A_configInterface(&(cx9261a_configuration.interface));
// 配置FPGA接口相关 此为示例,仅适用于Demo工程,用户应根据实际情况进行配置
CX9261A_configFPGA(&(cx9261a_configuration.interface));
// 配置校准
CX9261A_configADCCalib(cx9261a_configuration.clock.adc);
CX9261A_configFlashCalib();
CX9261A_configDcCalib(&(cx9261a_configuration.calib));
// CX9261A_configQecCalib(&cx9261a_configuration);
// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx1, CX9261A_LOSRC_Pll1);
// CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx2, CX9261A_LOSRC_Pll1);
// 切换到工作模式
CX9261A_configPowerMode(cx9261a_configuration.powerManagement.powerMode);
// 跳频
uint8_t hop_flag = 0;
uint8_t hop_flag_new = 0;
double hop_freq;
// while (true)
// {
// gpio_get_value(cx9261a_inst->gpio_desc_hop_flag, &hop_flag_new);
// if (hop_flag != hop_flag_new)
// {
// hop_flag = hop_flag_new;
//
// double hop_freq;
// double hop_freq1 = 800.25;
// int pll_index=1;
// int unlock_pll1_cnt=0,unlock_pll2_cnt=0;
//
// hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100;
//
// if(hop_freq == hop_freq1){
// if(pll_index == 2){
// pll_index = 4;
// }
// else if(pll_index == 1){
// pll_index = 3;
// }
// }
//
// if(hop_flag_new == 1)
// {
// if(pll_index == 1 || pll_index == 3)
// {
// //切换至pll2来源
// cx9261a_trx_ch_pll_config(2);
// //配置pll1参数
// CX9261A_configPll1(hop_freq,&(cx9261a_configuration.clock));
// // unlock_pll1_cnt=PLL_config(1,hop_freq,ref)-1;
// while (!CX9261A_afcPll1()) {
// unlock_pll1_cnt++;
// }
// pll_index = 2;
// }
// else if(pll_index == 2 || pll_index == 4)
// {
// //切换至pll1来源
// cx9261a_trx_ch_pll_config(1);
// //配置pll2参数
// CX9261A_configPll2(hop_freq,&(cx9261a_configuration.clock));
// // unlock_pll2_cnt=PLL_config(2,hop_freq,ref)-1;
// while (!CX9261A_afcPll2()) {
// unlock_pll2_cnt++;
// }
// pll_index = 1;
// }
// }
// hop_freq1 = hop_freq;
// if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){
// DBG_ERROR("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt);
// }
// }
// }
#endif
DBG_INFO("HDWR: configuration Done.\n");
return SUCCESS;
}