/*****************************************************************************/ /** * Description: hwconfig.h * * Date: 2024-02-20 13:19 * Last Edit Time: [2024-02-20 13:19] * * Revisions: Rev 0.0 * History: * [2023-05-07]: Initial edition. * * Copyright(c) 2024 Beijing Institute of Technology. * ******************************************************************************/ /***************************** Include Files *********************************/ // Standard #include #include // Xilinx #include "xgpiops.h" #include "drivers/axi_core/spi_engine/spi_engine.h" // App #include "common.h" #include "error.h" #include "delay.h" #include "system_monitor.h" #include "hwconfig.h" #include "config/app_config.h" #include "dev_profile/dev_profile.h" #ifdef RFSOC #include "xrfdc.h" #endif /************************** Function Prototypes ******************************/ /*********************** Driver Instance Definitions **************************/ static struct hmc7044_dev *hmc7044_inst; ad9528Device_t *ad9528_inst; static struct lmk04828_dev *lmk04828_inst; static struct lmx2594_dev *lmx2594_adc_inst; static struct lmx2594_dev *lmx2594_dac_inst; static struct ad9361_reg_dev *ad9361_1_reg_inst; static struct ad9361_reg_dev *ad9361_2_reg_inst; static struct 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, ®Val); // [D7] is lock indicator ret |= ((regVal & 0x80) == 0x80) ? CLK_AD0_BBPLL_LOCK : 0; ad9361_reg_read(ad9361_2_reg_inst, 0x005E, ®Val); // [D7] is lock indicator ret |= ((regVal & 0x80) == 0x80) ? CLK_AD1_BBPLL_LOCK : 0; // rfpll ad9361_reg_read(ad9361_1_reg_inst, 0x0287, ®Val); // [D1] is lock indicator ret |= ((regVal & 0x02) == 0x02) ? CLK_AD0_RFPLL_LOCK : 0; ad9361_reg_read(ad9361_2_reg_inst, 0x0287, ®Val); // [D1] is lock indicator ret |= ((regVal & 0x02) == 0x02) ? CLK_AD1_RFPLL_LOCK : 0; return ret; } // @ Determine HMC7044 lock state /** * Read corresponding register to determine clock lock state. */ uint8_t Hardware_GetHMC7044LockStatus(void) { uint8_t ret = 0; uint8_t regVal; // pll1 hmc7044_read(hmc7044_inst, 0x007C, ®Val); // [D5] is lock indicator ret |= ((regVal & 0xE0) != 0x00) ? CLK_SP_PLL0_LOCK : 0; // pll2 hmc7044_read(hmc7044_inst, 0x007D, ®Val); // [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,®); 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,®0008); // ad9694_read(ad9694_inst,0x56F,®056F); // ad9694_read(ad9694_inst,0x571,®0571); #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; }