add multirate qpsk transmitter, modify frequency hopping procedure

This commit is contained in:
2024-11-02 01:00:01 +08:00
parent 197ee19bef
commit 60e2dd6cb5
53 changed files with 15638 additions and 27959 deletions
@@ -1,8 +1,8 @@
{
"project_name": "zc706_cx9261a",
"version": "0.0.1",
"version": "0.0.2",
"hw_design": "../system_top.xsa",
"hw_version": "zc706_cx9261a_demo-HW-0.0.1",
"hw_version": "zc706_cx9261a_demo-HW-0.0.2",
"apps": {
"zc706_cx9261a_app": {
"sources": ["source_zc706_cx9261a/"],
@@ -48,7 +48,8 @@
#else // Zynq-7000
#define CPU_CLK_HZ XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ
#define APP_TIMER_CLK_HZ (CPU_CLK_HZ / 2)
#define FCLK_CLK0_HZ 100000000
#define FCLK_CLK0_HZ 50000000
#define FCLK_CLK1_HZ 200000000
#endif
/********* Zynq Platform Configs **********/
// APP Timer (for logging)
@@ -121,7 +122,7 @@
// #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_REF_CLK FCLK_CLK1_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
@@ -209,8 +210,8 @@ typedef enum
#define CX9261A_HOP_FLAG (CX9261A_GPIO_OFFSET+15)
// -- CX9261A SPI Engine Configuration
#define CX9261A_SPI_DEVICE_ID 0
#define CX9261A_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define CX9261A_SPI_ENGINE_MAX_SPEED 5000000
#define CX9261A_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define CX9261A_SPI_ENGINE_MAX_SPEED 50000000
#define CX9261A_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define CX9261A_SPI_ENGINE_DATA_WIDTH 8
#define CX9261A_SPI_ENGINE_CS_DELAY 3
@@ -227,7 +228,7 @@ typedef enum
#define HMC7044_GPIO_3 (HMC7044_GPIO_OFFSET + 5)
// -- HMC7044 SPI Engine Configuration
#define HMC7044_SPI_DEVICE_ID 0
#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define HMC7044_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define HMC7044_SPI_ENGINE_MAX_SPEED 5000000
#define HMC7044_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define HMC7044_SPI_ENGINE_DATA_WIDTH 8
@@ -243,7 +244,7 @@ typedef enum
#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_REF_CLK FCLK_CLK1_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
@@ -255,7 +256,7 @@ typedef enum
#define LMK04828_GPIO_OFFSET 54
// -- LMK04828 SPI Engine Configuration
#define LMK04828_SPI_DEVICE_ID 0
#define LMK04828_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define LMK04828_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define LMK04828_SPI_ENGINE_MAX_SPEED 5000000
#define LMK04828_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define LMK04828_SPI_ENGINE_DATA_WIDTH 8
@@ -267,7 +268,7 @@ typedef enum
#define LMX2594_ADC_GPIO_OFFSET 54
// -- LMX2594_ADC SPI Engine Configuration
#define LMX2594_ADC_SPI_DEVICE_ID 0
#define LMX2594_ADC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define LMX2594_ADC_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define LMX2594_ADC_SPI_ENGINE_MAX_SPEED 5000000
#define LMX2594_ADC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define LMX2594_ADC_SPI_ENGINE_DATA_WIDTH 8
@@ -279,7 +280,7 @@ typedef enum
#define LMX2594_DAC_GPIO_OFFSET 54
// -- LMX2594_DAC SPI Engine Configuration
#define LMX2594_DAC_SPI_DEVICE_ID 0
#define LMX2594_DAC_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define LMX2594_DAC_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define LMX2594_DAC_SPI_ENGINE_MAX_SPEED 5000000
#define LMX2594_DAC_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define LMX2594_DAC_SPI_ENGINE_DATA_WIDTH 8
@@ -292,7 +293,7 @@ typedef enum
#define AD9653_POWR_DOWN (AD9653_GPIO_OFFSET+0)
// -- AD9653 SPI Engine Configuration
#define AD9653_SPI_DEVICE_ID 0
#define AD9653_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define AD9653_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define AD9653_SPI_ENGINE_MAX_SPEED 5000000
#define AD9653_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define AD9653_SPI_ENGINE_DATA_WIDTH 8
@@ -304,7 +305,7 @@ typedef enum
#define AD9694_GPIO_OFFSET 54
// -- AD9694 SPI Engine Configuration
#define AD9694_SPI_DEVICE_ID 0
#define AD9694_SPI_ENGINE_REF_CLK FCLK_CLK0_HZ
#define AD9694_SPI_ENGINE_REF_CLK FCLK_CLK1_HZ
#define AD9694_SPI_ENGINE_MAX_SPEED 5000000
#define AD9694_SPI_ENGINE_BASEADDR XPAR_AXI_SPI_ENGINE_AXI_SPI_ENGINE_BASEADDR
#define AD9694_SPI_ENGINE_DATA_WIDTH 8
@@ -180,7 +180,7 @@ CX9261A_CX9261AConfiguration cx9261a_configuration = {
.tx1Source = CX9261A_LOSRC_Pll1,
.tx2Source = CX9261A_LOSRC_Pll2},
// 本振频率 注意:使用的所有PLL,频率必须设为正数
.pllFreq = {.pll1Freq = 121.88,
.pllFreq = {.pll1Freq = 500,
.pll2Freq = 5000,
.pll3Freq = 800,
.pll4Freq = 900,
@@ -215,7 +215,7 @@ CX9261A_CX9261AConfiguration cx9261a_configuration = {
.rx3CalibPll = CX9261A_LOSRC_Pll5,
.tx1CalibPll = 0,
.tx2CalibPll = 0,
.rxMethod = CX9261A_CALM_Tracking,
.rxMethod = CX9261A_CALM_TST,
.txMethod = CX9261A_CALM_Bisec,
.f0 = 4,
// .rxMultiPoints = {2200, 2400, 2600, 2800, 3000, 3200, 3400,
@@ -21,6 +21,7 @@
// Xilinx
#include "xgpiops.h"
#include "drivers/axi_core/spi_engine/spi_engine.h"
#include "sleep.h"
// App
#include "common.h"
#include "error.h"
@@ -53,6 +54,10 @@ XGpioPs Gpio;
XRFdc RFdc;
#endif
#define MIN_FREQ 121.88
#define MAX_FREQ 5000
#define FREQ_SEP 200
/*****************************************************************************/
/**
* @brief Hardware_SwitchFreq
@@ -330,10 +335,16 @@ int CX9261A_spiRead(int address)
return reg;
}
void CX9261A_udelay(double us)
{
usleep((uint32_t)us);
}
void CX9261A_mdelay(double ms)
{
mdelay((uint32_t)(ms));
usleep((uint32_t)(ms*1000));
}
void CX9261A_setPin(int pin, int value)
{
switch(pin){
@@ -389,19 +400,45 @@ void CX9261A_setPin(int pin, int value)
return;
}
void cx9261a_trx_ch_pll_config(u8 pll_index)
void replaceBits(uint8_t *reg, unsigned int start, unsigned int end, uint8_t after) {
// 生成掩码,用于清除目标位区间
uint8_t mask = ((1 << (start - end + 1)) - 1) << end;
// 清除 reg 中的指定位
*reg &= ~mask;
// 插入 after 的对应位到目标区间
*reg |= (after << end) & mask;
}
int CX9261A_afcPll1_pause(double delay_us)
{
u8 rx_data;
u8 recv_buf[3]={0};
u32 trx_ch_pll_data;
CX9261A_Log("PLL1 AFC PAUSE");
uint8_t r61D = (uint8_t)CX9261A_spiRead(0x61D);
int saved = r61D;
replaceBits(&r61D, 5, 4, 0b10);
CX9261A_spiWrite(0x61D, r61D);
CX9261A_spiWrite(0x617, 0x00);
CX9261A_spiWrite(0x617, 0x13);
// CX9261A_udelay(delay_us);
CX9261A_spiWrite(0x61D, saved);
int lock = CX9261A_spiRead(0x635);
return 0x10 & lock;
}
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);
int CX9261A_afcPll2_pause(double delay_us)
{
CX9261A_Log("PLL2 AFC PAUSE");
uint8_t r63F = (uint8_t)CX9261A_spiRead(0x63F);
int saved = r63F;
replaceBits(&r63F, 5, 4, 0b10);
CX9261A_spiWrite(0x63F, r63F);
CX9261A_spiWrite(0x639, 0x00);
CX9261A_spiWrite(0x639, 0x13);
// CX9261A_udelay(delay_us);
CX9261A_spiWrite(0x63F, saved);
int lock = CX9261A_spiRead(0x657);
return 0x10 & lock;
}
/*****************************************************************************/
@@ -762,6 +799,20 @@ int32_t Hardware_Init(void)
/**********************************************************/
cx9261a_init(&cx9261a_inst, &cx9261a_default_init_param);
double min_freq = 3000.0;
double max_freq = 5000.0;
int cal_freq_num = 21;
double freq_sep = (max_freq-min_freq)/(cal_freq_num-1);
for (int ii = 0; ii < cal_freq_num; ii++)
{
cx9261a_configuration.calib.rxMultiPoints[ii] = min_freq + ii*freq_sep;
cx9261a_configuration.calib.txMultiPoints[ii] = min_freq + ii*freq_sep;
}
cx9261a_configuration.calib.numRxPoint = cal_freq_num;
cx9261a_configuration.calib.numTxPoint = cal_freq_num;
// 绑定函数
CX9261A_setLoggingFunc(CX9261A_Log);
CX9261A_setWriteSpiFunc(CX9261A_spiWrite);
@@ -771,8 +822,6 @@ int32_t Hardware_Init(void)
// 开始配置芯片
CX9261A_initialChip(); // 最开始需要调用此函数
int reg;
reg = CX9261A_spiRead(0x000);
CX9261A_initialPowerConfig(&cx9261a_configuration);
// 配置温补
CX9261A_configTemperatureCompensation(cx9261a_configuration.tempComp);
@@ -825,77 +874,143 @@ int32_t Hardware_Init(void)
CX9261A_configADCCalib(cx9261a_configuration.clock.adc);
CX9261A_configFlashCalib();
CX9261A_configDcCalib(&(cx9261a_configuration.calib));
// CX9261A_configQecCalib(&cx9261a_configuration);
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);
int reg;
CX9261A_spiWrite(0x02E,0x03);
reg = CX9261A_spiRead(0x0AB);
CX9261A_spiWrite(0x02E,0x06);
// 跳频
uint8_t hop_flag = 0;
uint8_t hop_flag_new = 0;
double hop_freq;
// while (true)
// int hop_freq_num = 3*floor((cal_freq_num-1)/2); // 切换顺序为 0, 1, 2, 0, 3, 4, 0, 5, 6 ...
// double hop_freq[hop_freq_num];
// int next_pll_index = 1;
// double curr_freq;
// int freq_index = 0;
//
// for (int ii = 0; ii < hop_freq_num/3; ii++)
// {
// 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);
// }
// }
// hop_freq[3*ii] = cx9261a_configuration.calib.rxMultiPoints[0];
// hop_freq[3*ii+1] = cx9261a_configuration.calib.rxMultiPoints[2*ii+1];
// hop_freq[3*ii+2] = cx9261a_configuration.calib.rxMultiPoints[2*ii+2];
// }
//
// if (hop_freq[freq_index] != cx9261a_configuration.pllFreq.pll1Freq)
// {
// curr_freq = hop_freq[freq_index];
//
// CX9261A_configPllSource(&(cx9261a_configuration.pllSource));
// CX9261A_configPll1(hop_freq[freq_index], &(cx9261a_configuration.clock));
// CX9261A_afcPll1_pause(25);
// // set pll1 as default
// cx9261a_configuration.pllSource.rx1Source = CX9261A_LOSRC_Pll1;
// cx9261a_configuration.pllSource.tx1Source = CX9261A_LOSRC_Pll1;
// // // prepare next pll
// CX9261A_configPll2(hop_freq[freq_index+1], &(cx9261a_configuration.clock));
// CX9261A_afcPll2_pause(25);
// // index update
// next_pll_index = 2;
// }
static int hop_cnt = 0;
static int next_pll_index = 2;
static double curr_freq;
static double next_freq = MIN_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;
// 1st demo of frequency hopping
int unlock_pll1_cnt = 0, unlock_pll2_cnt = 0;
curr_freq = next_freq;
hop_cnt++;
if (hop_cnt % 3 == 2)
{
next_freq = MIN_FREQ;
}
else
{
next_freq = (curr_freq + FREQ_SEP > MAX_FREQ) ? MIN_FREQ : curr_freq + FREQ_SEP;
}
if (next_pll_index == 2)
{
// switch pll
CX9261A_spiWrite(0x77D,0x0C);
// prepare next pll
CX9261A_configPll1(next_freq, &(cx9261a_configuration.clock));
while (!CX9261A_afcPll1_pause(20))
{
unlock_pll1_cnt++;
}
// index update
next_pll_index = 1;
}
else
{
// switch pll
CX9261A_spiWrite(0x77D,0xCF);
// prepare next pll
CX9261A_configPll2(next_freq, &(cx9261a_configuration.clock));
while (!CX9261A_afcPll2_pause(20))
{
unlock_pll2_cnt++;
}
// index update
next_pll_index = 2;
}
if(unlock_pll2_cnt!=0 || unlock_pll1_cnt !=0){
xil_printf("pll1 unlock num: %d; pll2 unlock num: %d;.\n", unlock_pll1_cnt, unlock_pll2_cnt);
}
// 2nd demo of frequency hopping
// curr_freq = hop_freq[freq_index];
// hop_flag = hop_flag_new;
// freq_index = (freq_index == hop_freq_num - 1) ? 0 : freq_index + 1;
//
// if (next_pll_index == 2)
// {
// // switch pll
//// cx9261a_configuration.pllSource.rx1Source = CX9261A_LOSRC_Pll2;
//// cx9261a_configuration.pllSource.tx1Source = CX9261A_LOSRC_Pll2;
//// CX9261A_configPllSource(&(cx9261a_configuration.pllSource));
// CX9261A_spiWrite(0x77D,0x0C);
// // prepare next pll
// CX9261A_configPll1(hop_freq[freq_index], &(cx9261a_configuration.clock));
// CX9261A_afcPll1_pause(25);
// // index update
// next_pll_index = 1;
// }
// else if (next_pll_index == 1)
// {
// // switch pll
//// cx9261a_configuration.pllSource.rx1Source = CX9261A_LOSRC_Pll1;
//// cx9261a_configuration.pllSource.tx1Source = CX9261A_LOSRC_Pll1;
//// CX9261A_configPllSource(&(cx9261a_configuration.pllSource));
// CX9261A_spiWrite(0x77D,0xCF);
// // prepare next pll
// CX9261A_configPll2(hop_freq[freq_index], &(cx9261a_configuration.clock));
// CX9261A_afcPll2_pause(25);
// // index update
// next_pll_index = 2;
// }
}
}
#endif
DBG_INFO("HDWR: configuration Done.\n");
return SUCCESS;
}
@@ -90,4 +90,4 @@
void AppAssert(const char *file, int line);
#endif /* __COMMON_H_ */
/** @} */
/** @} */