feat: PL发端改为演示验证多符号速率QPSK,PS增加DEMO工程附带的CPP驱动程序

This commit is contained in:
2024-11-02 12:08:58 +08:00
parent 986109c2f7
commit 16bac8585d
146 changed files with 961054 additions and 168083 deletions
@@ -0,0 +1,32 @@
@echo off
set "platform=xilinx"
set "pltform_ver=2024.1"
set "work_dir=%~dp0build"
set "config=%~dp0config.json"
set "tools_dir=%~dp0..\..\scripts\platform\%platform%"
REM Set up enviroment
call "%tools_dir%\setenv.bat" "%pltform_ver%"
if "%ERRORLEVEL%" neq "0" (
echo Error: Failed to installize enviroment.
pause >nul
exit /b 1
)
REM Build project
call "%tools_dir%\build.bat" "%config%" "%work_dir%"
if "%ERRORLEVEL%" neq "0" (
echo Error: Failed to build project.
pause >nul
exit /b 1
)
REM Lauch SDK
call "%tools_dir%\launch.bat" "%pltform_ver%" "%work_dir%"
if "%ERRORLEVEL%" neq "0" (
echo Error: Failed to launch SDK.
pause >nul
exit /b 1
)
exit /b 0
@@ -4,8 +4,9 @@
"hw_design": "../CX9261A_ZC706.xsa",
"hw_version": "20241031",
"apps": {
"cx9261a_api_app": {
"sources": ["source_cx9261a_api_1_9_0/"],
"CX9261A_CPPV4": {
"sources": ["source_CX9261A_CPPV4/"],
"target_cpu": "ps7_cortexa9_0",
"os": "standalone",
"language": "C++",
@@ -14,28 +15,6 @@
"stack_size": "0x4000"
}
},
"cx9261a_api_lib_app": {
"sources": ["source_cx9261a_api_lib_c/"],
"target_cpu": "ps7_cortexa9_0",
"os": "standalone",
"language": "C",
"mem_layout" : {
"heap_size": "0x80000",
"stack_size": "0x4000"
},
"build_config": {
"debug": {
"include-path": ["source_cx9261a_api_lib_c/include"],
"libraries": ["cx9261a_c_dbg", "stdc++", "m"],
"library-search-path": ["source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib"]
},
"release": {
"include-path": ["source_cx9261a_api_lib_c/include"],
"libraries": ["cx9261a_c", "stdc++", "m"],
"library-search-path": ["source_cx9261a_api_lib_c/drivers/rf-transceiver/cx9261a/lib"]
}
}
},
"CX9261A_DEMO": {
"sources": ["source_CX9261A_DEMO/"],
"target_cpu": "ps7_cortexa9_0",
@@ -0,0 +1,444 @@
/**
* @file cx9261adriver.h
*/
#ifndef CX9261ADRIVER_CX9261ADRIVER_H
#define CX9261ADRIVER_CX9261ADRIVER_H
#include "defs.h"
namespace CX9261A {
/**
* @brief 需要实现的函数,实现SPI写入寄存器功能
* @param address 要写入的寄存器地址
* @param value 要写入的寄存器值
*/
void writeSpi(int address, int value);
/**
* @brief 需要实现的函数,实现SPI读取寄存器功能
* @param address 要读取的寄存器地址
* @return 返回的寄存器值
*/
int readSpi(int address);
/**
* @brief 需要实现的函数,实现等待功能
* @param ms 等待时间,单位毫秒
*/
void pause(double ms);
/**
* @brief 需要实现的函数,实现配置FPGA对应寄存器功能
* @param pin 寄存器地址
* @param value 寄存器值
*/
void setPin(int pin, int value);
/**
* @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数
*/
void initialPowerConfig(const CX9261AConfiguration& config);
/**
* @brief 初始化芯片状态,写入与具体配置无关的寄存器值
*/
void initialChip();
/**
* @brief 初始化BBPLL相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialBBPLL();
/**
* @brief 初始化PLL1相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialPLL1();
/**
* @brief 初始化PLL2相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialPLL2();
/**
* @brief 初始化PLL3相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialPLL3();
/**
* @brief 初始化PLL4相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialPLL4();
/**
* @brief 初始化PLL5相关寄存器,如果调用了initialChip,则无需单独调用此函数
*/
void initialPLL5();
/**
* @brief 配置AGC模式
* @param mode 模式0~13
*/
void configAGCMode(int mode);
/**
* @brief 配置AGC PDT
* @param pdt AGCPDT结构体
*/
void configAGCPDT(const AGCPDT& pdt);
/**
* @brief 配置AGC LMT
* @param lmt AGCLMT结构体
*/
void configAGCLMT(const AGCLMT& lmt);
/**
* @brief 配置AGC DIG
* @param dig AGCDIG结构体
*/
void configAGCDIG(const AGCDIG& dig);
/**
* @brief 配置AGC
* @param agc AGC结构体
*/
void configAGC(const AGC& agc);
/**
* @brief 配置时钟相关寄存器,包括ADC和BBPLL
* @param config CX9261A参数结构体
*/
void configBBPLL(const CX9261AConfiguration& config);
/**
* @brief BBPLL AFC
* @return 是否锁定
*/
bool afcBBPll();
/**
* @brief 配置PLL1频率
* @param lo 目标频率
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
*/
void configPll1(double lo, const Clock& clock);
/**
* @brief Pll1 AFC
* @return 是否锁定
*/
bool afcPll1();
/**
* @brief 配置PLL2频率
* @param lo 目标频率
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
*/
void configPll2(double lo, const Clock& clock);
/**
* @brief Pll2 AFC
* @return 是否锁定
*/
bool afcPll2();
/**
* @brief 配置PLL3频率
* @param lo 目标频率
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
*/
void configPll3(double lo, const Clock& clock);
/**
* @brief Pll3 AFC
* @return 是否锁定
*/
bool afcPll3();
/**
* @brief 配置PLL4频率
* @param lo 目标频率
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
*/
void configPll4(double lo, const Clock& clock);
/**
* @brief Pll4 AFC
* @return 是否锁定
*/
bool afcPll4();
/**
* @brief 配置PLL5频率
* @param lo 目标频率
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
*/
void configPll5(double lo, const Clock& clock);
/**
* @brief Pll5 AFC
* @return 是否锁定
*/
bool afcPll5();
/**
* @brief ADC校准
* @param adc ADC速率
*/
void configADCCalib(double adc);
/**
* @brief Flash校准
*/
void configFlashCalib();
/**
* @brief 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器
* @param on 开启/关闭
*/
void configRISCV(bool on);
/**
* @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复
* @return 包含寄存器地址和值的map
*/
std::map<int, int> beforeQecState();
/**
* @brief 恢复QEC校准过程中改变的寄存器
* @param state beforeQecState函数返回的map
*/
void restoreQecState(const std::map<int, int>& state);
/**
* @brief Rx窄带多点校准
* @param config CX9261A配置结构体
* @param points 校准点
*/
void configRxMultiPointsQec(const CX9261AConfiguration& config, const std::vector<double>& points);
/**
* @brief Qec校准顶层函数,内部根据配置选择使用RX TST窄带方法对接收通道校准,使用二分法对发射通道校准
* @param config CX9261A配置结构体
*/
void configQecCalib(const CX9261AConfiguration& config);
/**
* @brief Rx TST窄带校准
* @param config CX9261A配置结构体
* @param chan 要进行校准的通道
*/
void rxTSTCalib(const CX9261AConfiguration& config, RxChannel chan);
/**
* @brief 等待RxTST窄带校准结束,可重写
* @return 校准是否结束
*/
bool waitRxTSTFinished();
/**
* @brief Tx通道校准
* @param config CX9261A配置结构体
*/
void txCalib(const CX9261AConfiguration& config);
/**
* @brief TX二分法QEC校准
* @param f0 校准音频率
* @param fs adc频率
*/
void txBisectionQecCalib(double f0, double fs);
/**
* @brief TX二分法DC校准
* @param f0 校准音频率
* @param fs adc频率
*/
void txBisectionDcCalib(double f0, double fs);
/**
* @brief DC Tracking
* @param config CX9261A配置结构体
*/
void configDcCalib(const Calib& config);
/**
* @brief 配置TX NCO相关寄存器
* @param nco TX NCO配置结构体
* @param fs adc速率
*/
void configTxNco(const TxNCO& nco, double fs);
/**
* @brief 配置TX NCO BIST模式
* @param bist 开启/关闭BIST
*/
void configTxBIST(bool bist);
/**
* @brief 配置TX NCO频率
* @param freq 混频频率
* @param fs adc抽取后速率
*/
void configTxNcoFreq(double freq, double fs);
/**
* @brief 配置RX NCO相关寄存器
* @param nco RX NCO配置结构体
* @param fs adc速率
*/
void configRxNco(const RxNCO& nco, double fs);
/**
* @brief 配置Rx NCO模式
* @param mode NCO模式:Bypass/BIST/Up/Down
*/
void configRxNcoMode(NCOMode mode);
/**
* @brief 配置Rx NCO模式
* @param mode NCO模式:Master/Slaver
*/
void configRxNcoMS(NCOMode mode);
/**
* @brief 配置Rx NCO频率
* @param freq 混频频率
* @param fs adc速率
*/
void configRxNcoFreq(double freq, double fs);
/**
* @brief 配置接口相关寄存器
* @param interface Interface配置结构体
*/
void configInterface(const Interface& interface);
/**
* @brief 配置PLL来源
* @param pllSource PLlSource结构体
*/
void configPllSource(const PllSource& pllSource);
/**
* @brief 切换电源模式
* @param pm 电源模式
*/
void configPowerMode(PowerMode pm);
/**
* @brief 配置电源管理
* @param power 电源配置结构体
* @param pm 电源模式
*/
void configPowerPins(const Power& power, PowerMode pm);
/**
* @brief 配置参考倍频器
* @param doubler 倍频器开关
* @param ref 参考时钟频率,单位MHz
*/
void configRefDoubler(bool doubler, double ref);
/**
* @brief 初始化通道,调用initialChip函数会初始化RX1,RX2,RX3三个通道
* @param chan 通道 RX1/RX2/RX3
*/
void initialRxChannel(RxChannel chan);
/**
* @brief 配置Rx带宽
* @note 只改变Rx带宽会导致通道增益改变,建议使用configRxChannel函数进行带宽调整
* @param bandwidth 带宽,单位(MHz)
* @param chan 通道 Rx1/Rx2/Rx3
*/
void configRxBandwidth(double bandwidth, RxChannel chan);
/**
* @brief 配置Rx TIA
* @note 只改变TIA会导致通道带宽改变,建议使用configRxChannel函数进行TIA调整
* @param tia tia档位
* @param chan 通道 Rx1/Rx2/Rx3
*/
void configRxTIA(int tia, RxChannel chan);
/**
* @brief 配置Rx Mixer
* @param mixer mixer档位
*/
void configRxMixer(int mixer);
/**
* @brief 配置Rx通道,包含TIA,Mixer以及Bandwidth
* @param config RxConfig结构体
* @param chan Rx1/Rx2/Rx3
*/
void configRxChannel(const RxConfig& config, RxChannel chan);
/**
* @brief 配置Rx FIR滤波器抽取倍数
* @param fir 抽取倍数 0(Bypass)/1/2/3/4/8
*/
void configRxFIR(int fir);
/**
* @brief 配置Rx FIR滤波器系数
* @param coe 滤波器系数,长度为16的整倍数,最大128
*/
void configRxFIRCoe(const std::vector<double>& coe);
/**
* @brief 配置Rx HBF1滤波器抽取倍数
* @param hbf 抽取倍数 0(Bypass)/2
*/
void configRxHBF1(int hbf);
/**
* @brief 配置Rx HBF2滤波器抽取倍数
* @param hbf 抽取倍数 0(Bypass)/2
*/
void configRxHBF2(int hbf);
/**
* @brief 配置Rx HBF3滤波器抽取倍数
* @param hbf 抽取倍数 0(Bypass)/2/3
*/
void configRxHBF3(int hbf);
/**
* @brief 配置Rx CIC滤波器
* @param cic 抽取倍数 0(Bypass)/20
*/
void configRxCIC(int cic);
/**
* @brief 配置Rx滤波器
* @param filters Filters结构体
*/
void configRxFilters(const Filters& filters);
/**
* @brief 配置Tx带宽
* @param bandwidth 带宽,单位(MHz)
* @param chan 通道 TX1/TX2
*/
void configTxBandwidth(double bandwidth, TxChannel chan);
/**
* @brief 配置Tx Mixer
* @param mixer 混频器值
* @param chan TX1/TX2
*/
void configTxMixer(int mixer, TxChannel chan);
/**
* @brief 初始化Tx通道
* @param chan 通道 TX1/TX2
*/
void initialTxChannel(TxChannel chan);
/**
* @brief 根据Tx通道的本振频率,配置对应的参数
* @param lo 本振频率,单位(MHz)
* @param chan 通道(Tx1/Tx2)
*/
void configTxChannelFrequency(double lo, TxChannel chan);
/**
* @brief 配置Tx通道,Mixer以及Bandwidth
* @param config TxConfig结构体
* @param chan Tx1/Tx2
*/
void configTxChannel(const TxConfig& config, TxChannel chan);
/**
* @brief 配置Tx FIR滤波器插值倍数
* @param fir 插值倍数 0(Bypass)/1/2/3/4/8
*/
void configTxFIR(int fir);
/**
* @brief 配置Tx FIR滤波器系数
* @param coe 滤波器系数,长度为16的整倍数,最大128
*/
void configTxFIRCoe(const std::vector<double>& coe);
/**
* @brief 配置Tx HBF1滤波器插值倍数
* @param hbf 插值倍数 0(Bypass)/2
*/
void configTxHBF1(int hbf);
/**
* @brief 配置Tx HBF2滤波器插值倍数
* @param hbf 插值倍数 0(Bypass)/2
*/
void configTxHBF2(int hbf);
/**
* @brief 配置Tx HBF3滤波器插值倍数
* @param hbf 插值倍数 0(Bypass)/2/3
*/
void configTxHBF3(int hbf);
/**
* @brief 配置Tx CIC滤波器
* @param cic 插值倍数 0(Bypass)/8/20/32/80
*/
void configTxCIC(int cic);
/**
* @brief 配置Tx滤波器
* @param filters Filters结构体
*/
void configTxFilters(const Filters& filters);
/**
* @brief 读取当前Rx chan通道的校准值
* @param chan Rx通道
* @return Rx校准值结构体
*/
CalibPredis readRxCalibPredis(RxChannel chan);
/**
* @brief 储存校准值
* @param index 第index组校准值
* @param chan 接收通道
* @param predis 校准值
*/
void saveRxCalibPredis(unsigned char index, RxChannel chan, const CalibPredis& predis);
/**
* @brief 加载保存的校准值
* @param index 第index组校准值
*/
void loadRxCalibPredis(unsigned char index);
/**
* @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能
* @param interface Interface结构体
*/
void configFPGA(const Interface& interface);
} // namespace CX9261A
#endif // CX9261ADRIVER_CX9261ADRIVER_H
@@ -0,0 +1,352 @@
/**
* @file defs.h
*/
#ifndef CX9261ADRIVER_DEFS_H
#define CX9261ADRIVER_DEFS_H
#include <bitset>
#include <map>
#include <vector>
namespace CX9261A {
/**
* @brief 芯片工作模式
*/
enum class WorkMode { Rx, Tx, FDD };
/**
* @brief 收发数据通道数量
* @note 此模式并不代表使用几个通道进行收发
*/
enum class TrMode { R1T1, R2T2 };
/**
* @brief 收发接口通道数量
*/
enum class PortMode { Single, Dual };
/**
* @brief 接口模式:
* CMOS CMOS接口模式,
* LVDS_S LVDS顺序模式,
* LVDS_E LVDS奇偶模式
*/
enum class IOMode { CMOS, LVDS_S, LVDS_E };
/**
* @brief 本振来源
*/
enum class LoSource { Pll1, Pll2, Pll3, Pll4, Pll5, Off };
/**
* @brief 接收通道
*/
enum class RxChannel { Rx1 = 1, Rx2, Rx3 };
/**
* @brief 发射通道
*/
enum class TxChannel { Tx1 = 1, Tx2 };
/**
* @brief 电源模式
*/
enum class PowerMode { Shutdown = 0, Sleep, Alert, Calib, Receive, Transmit, Duplex, Obs };
/**
* @brief NCO模式
*/
enum class NCOMode { Bypass = 0, Up, Down, BIST, Master, Slaver };
/**
* @brief AFC等待延时,单位ms
*/
constexpr double delay = 100;
constexpr double delay_afc = 0.020;
/**
* @brief QEC等待延时,单位ms
*/
constexpr double qecDelay = 100;
/**
* @brief 接收通道本振来源映射表
*/
static const std::map<std::pair<LoSource, LoSource>, std::bitset<7>> rxSrcMap = {
{ { LoSource::Pll2, LoSource::Pll2 }, 0b0010000 }, { { LoSource::Pll1, LoSource::Pll1 }, 0b1101000 },
{ { LoSource::Pll2, LoSource::Pll1 }, 0b0100000 }, { { LoSource::Pll1, LoSource::Pll2 }, 0b1000000 },
{ { LoSource::Off, LoSource::Pll1 }, 0b0101010 }, { { LoSource::Off, LoSource::Pll2 }, 0b1010010 },
{ { LoSource::Pll1, LoSource::Off }, 0b1001001 }, { { LoSource::Pll2, LoSource::Off }, 0b0110001 },
{ { LoSource::Off, LoSource::Off }, 0b0011011 }
};
/**
* @brief 发射通道本振来源映射表
*/
static const std::map<std::pair<LoSource, LoSource>, std::bitset<11>> txSrcMap = {
{ { LoSource::Pll4, LoSource::Pll4 }, 16 }, { { LoSource::Pll3, LoSource::Pll3 }, 104 },
{ { LoSource::Pll4, LoSource::Pll3 }, 32 }, { { LoSource::Pll3, LoSource::Pll4 }, 64 },
{ { LoSource::Pll2, LoSource::Pll2 }, 1560 }, { { LoSource::Pll1, LoSource::Pll1 }, 1944 },
{ { LoSource::Pll2, LoSource::Pll1 }, 1688 }, { { LoSource::Pll1, LoSource::Pll2 }, 1816 },
{ { LoSource::Off, LoSource::Pll3 }, 42 }, { { LoSource::Off, LoSource::Pll4 }, 82 },
{ { LoSource::Off, LoSource::Pll2 }, 794 }, { { LoSource::Off, LoSource::Pll1 }, 666 },
{ { LoSource::Pll3, LoSource::Off }, 73 }, { { LoSource::Pll4, LoSource::Off }, 49 },
{ { LoSource::Pll2, LoSource::Off }, 1177 }, { { LoSource::Pll1, LoSource::Off }, 1305 },
{ { LoSource::Off, LoSource::Off }, 27 }, { { LoSource::Pll1, LoSource::Pll3 }, 1320 },
{ { LoSource::Pll1, LoSource::Pll4 }, 1360 }, { { LoSource::Pll2, LoSource::Pll3 }, 1064 },
{ { LoSource::Pll2, LoSource::Pll4 }, 1104 }, { { LoSource::Pll3, LoSource::Pll1 }, 712 },
{ { LoSource::Pll4, LoSource::Pll1 }, 688 }, { { LoSource::Pll3, LoSource::Pll2 }, 584 },
{ { LoSource::Pll4, LoSource::Pll2 }, 560 }
};
/**
* @brief 环路参数选择表
*/
static const std::vector<std::vector<std::vector<int>>> coreTable = {
{ { 0x0C, 0x30, 0x08 }, { 0x0B, 0x30, 0x09 }, { 0x0C, 0x30, 0x05 }, { 0x0D, 0x30, 0x08 } },
{ { 0x0C, 0x30, 0x0C }, { 0x0B, 0x30, 0x0E }, { 0x0C, 0x30, 0x08 }, { 0x0D, 0x30, 0x0B } },
{ { 0x0C, 0x20, 0x10 }, { 0x0B, 0x20, 0x10 }, { 0x0C, 0x20, 0x0A }, { 0x0D, 0x20, 0x0D } },
{ { 0x0C, 0x20, 0x11 }, { 0x0B, 0x20, 0x13 }, { 0x0C, 0x20, 0x0C }, { 0x0D, 0x20, 0x0F } },
{ { 0x0D, 0x30, 0x14 }, { 0x0D, 0x22, 0x14 }, { 0x0D, 0x20, 0x0D }, { 0x0D, 0x15, 0x0C } },
{ { 0x0E, 0x30, 0x18 }, { 0x0E, 0x25, 0x16 }, { 0x0E, 0x25, 0x0F }, { 0x0E, 0x18, 0x0F } },
{ { 0x0F, 0x38, 0x1A }, { 0x0F, 0x32, 0x1C }, { 0x0F, 0x18, 0x12 }, { 0x0F, 0x18, 0x12 } }
};
/**
* @brief AGC PDT模式的结构体
*/
struct AGCPDT
{
int pdtN;
int pdtM;
};
/**
* @brief AGC LMT模式的结构体
*/
struct AGCLMT
{
int count; /**< LMT统计次数阈值*/
int threshold1; /**< LMT阈值第一档*/
int threshold2; /**< LMT阈值第二档*/
int threshold3; /**< LMT阈值第三档*/
int threshold4; /**< LMT阈值第四档*/
};
/**
* @brief AGC DIG模式的结构体
*/
struct AGCDIG
{
int count; /**< DIG统计次数阈值*/
int threshold1; /**< DIG阈值第一档*/
int threshold2; /**< DIG阈值第二档*/
int threshold3; /**< DIG阈值第三档*/
int threshold4; /**< DIG阈值第四档*/
};
/**
* @brief AGC模式的结构体
*/
struct AGC
{
int mode; /**< AGC模式选择*/
AGCPDT pdt; /**< AGC PDT模式的结构体*/
AGCLMT lmt; /**< AGC LMT模式的结构体*/
AGCDIG dig; /**< AGC DIG模式的结构体*/
};
/**
* @brief 时钟相关参数结构体
*/
struct Clock
{
double ref; /**< 参考时钟频率,单位MHz*/
double adc; /**< ADC频率,单位MHz*/
int refDiv; /**< 参考时钟分频比*/
bool bbUseIntDiv; /**< 是否使用整数分频模式*/
bool refDoubler; /**< 是否使用参考时钟倍频器*/
};
/**
* @brief 校准相关参数结构体
*/
struct Calib
{
bool calibRx1; /**< 是否校准Rx1*/
bool calibRx2; /**< 是否校准Rx2*/
bool calibRx3; /**< 是否校准Rx3*/
bool calibTx1; /**< 是否校准Tx1*/
bool calibTx2; /**< 是否校准Tx1*/
bool calibDC; /**< 是否开启DC Tracking*/
int dcCalibLength; /**< DC Tracking长度*/
double f0; /**< 校准音频率*/
};
/**
* @brief 配置PLL来源相关参数结构体
*/
struct PllSource
{
bool rxUseExt; /**< 接收通道是否使用外本振*/
bool txUseExt; /**< 发射通道是否使用外本振*/
LoSource rx1Source; /**< Rx1通道本振来源*/
LoSource rx2Source; /**< Rx2通道本振来源*/
LoSource rx3Source; /**< Rx3通道本振来源*/
LoSource tx1Source; /**< Tx1通道本振来源*/
LoSource tx2Source; /**< Tx2通道本振来源*/
};
/**
* @brief 配置PLL频率相关参数结构体
*/
struct PllFreq
{
double pll1Freq; /**< PLL1本振时钟,单位MHz*/
double pll2Freq; /**< PLL2本振时钟,单位MHz*/
double pll3Freq; /**< PLL3本振时钟,单位MHz*/
double pll4Freq; /**< PLL4本振时钟,单位MHz*/
double pll5Freq; /**< PLL5本振时钟,单位MHz*/
double rxExtFreq; /**< 接收通道使用外本振时,外本振频率,单位MHz*/
double txExtFreq; /**< 发射通道使用外本振时,外本振频率,单位MHz*/
};
/**
* @brief 配置接口相关参数结构体
*/
struct Interface
{
WorkMode workMode; /**< 芯片工作模式*/
TrMode trMode; /**< 收发数据通道模式*/
PortMode portMode; /**< 收发接口通道模式*/
IOMode ioMode; /**< 接口电平模式*/
};
/**
* @brief 配置TX NCO相关参数结构体
*/
struct TxNCO
{
bool txUseBist; /**< 是否开启BIST模式*/
double txNCOFreq; /**< NCO频率*/
};
/**
* @brief 配置RX NCO相关参数结构体
*/
struct RxNCO
{
bool rxUseBist; /**< 是否开启BIST模式*/
bool rxNCOBypass; /**< 是否Bypass NCO*/
bool rxNCOUpward; /**< 开启上/下混频模式*/
bool rxNCOMaster; /**< 使用Master/Slaver模式*/
double rxNCOFreq; /**< NCO频率*/
};
/**
* @brief 配置接收通道相关参数结构体
*/
struct RxConfig
{
double bandwidth; /**< 接收通道1dB带宽,单位MHz*/
int tia; /**< 接收通道TIA增益配置,推荐配置6*/
int mixer; /**< 接收通道Mixer增益配置*/
};
/**
* @brief 配置发射通道相关参数结构体
*/
struct TxConfig
{
double bandwidth; /**< 发射通道1dB带宽,单位MHz*/
int mixer; /**< 发射通道Mixer增益配置*/
};
/**
* @brief 配置滤波器相关参数结构体,0代表bypass
*/
struct Filters
{
int fir; /**< FIR滤波器抽取/插值倍数*/
int hbf1; /**< HBF1滤波器抽取/插值倍数*/
int hbf2; /**< HBF2滤波器抽取/插值倍数*/
int hbf3; /**< HBF3滤波器抽取/插值倍数*/
int cic; /**< CIC滤波器抽取/插值倍数*/
};
/**
* @brief 配置电源模式结构体,1代表该模块上电
*/
struct Power
{
bool dig_tx2;
bool dig_tx1;
bool dig_rx3;
bool dig_rx2;
bool dig_rx1;
bool fref1_rx;
bool auxadc2;
bool auxadc1;
bool auxdac;
bool temp_sensor;
bool bgr;
bool exlo;
bool tx2;
bool tx1;
bool rx3;
bool rx2;
bool rx1;
bool pll5_ldo;
bool pll5;
bool pll4_ldo;
bool pll4;
bool pll3_ldo;
bool pll3;
bool pll2_ldo;
bool pll2;
bool pll1_ldo;
bool pll1;
bool bbpll;
};
/**
* @brief 配置电源模式管理,包含模式选择,断电模式,接收模式,发射模式,FDD模式
*/
struct PowerManagement
{
PowerMode powerMode;
Power shutdownPower;
Power rxPower;
Power txPower;
Power fddPower;
};
/**
* @brief 储存窄带校准结果的结构体
*/
struct CalibPredis {
int bHigh;
int bLow;
int cHigh;
int cLow;
int dciHigh;
int dciLow;
int dcqHigh;
int dcqLow;
};
/**
* @brief CX9261A结构体
*/
struct CX9261AConfiguration
{
AGC agc; /**< AGC结构体*/
Interface interface; /**< Interface结构体*/
Clock clock; /**< Clock结构体*/
PllSource pllSource; /**< PllSource结构体*/
Calib calib; /**< Calib结构体*/
PllFreq pllFreq; /**< PllFreq结构体*/
TxNCO txNco; /**< TxNCO结构体*/
RxNCO rxNco; /**< RxNCO结构体*/
RxConfig rx1Config; /**< RxConfig结构体*/
RxConfig rx2Config; /**< RxConfig结构体*/
RxConfig rx3Config; /**< RxConfig结构体*/
TxConfig tx1Config; /**< TxConfig结构体*/
TxConfig tx2Config; /**< TxConfig结构体*/
Filters rxFilters; /**< Filters结构体*/
Filters txFilters; /**< Filters结构体*/
PowerManagement powerManagement; /**< PowerManagement结构体*/
std::vector<double> rxFIRCoe; /**< Rx FIR滤波器系数*/
std::vector<double> txFIRCoe; /**< Tx FIR滤波器系数*/
};
} // namespace CX9261A
#endif // CX9261ADRIVER_DEFS_H
@@ -0,0 +1,67 @@
/*
* download_bin.c
*
* Created on: 2023年11月23日
* Author: cxlab
*/
#include "xilinx_io.h"
#include "sleep.h"
void download_bin(void){
int temp;
u8 rx_data;
u8 data[4];
u32 buf;
u8 addr[2];
int on = 1;
if (on) {
SpiPs_write_read1(0x079,0x00,&rx_data);//关闭CRC校验
SpiPs_write_read1(0x071,0x00,&rx_data);
SpiPs_write_read1(0x071,0x09,&rx_data);
// SpiPs_write_read1(0x236,0x0F,&rx_data);
// SpiPs_write_read1(0x20A,0x01,&rx_data);
for(int i=0;i<5507;i++){
addr[0]=(i>>8)&0xff;
addr[1]= i&0xff;
buf=rom_read((u8 *)&addr);
data[0]=buf>>24;
data[1]=(buf>>16)&0xff;
data[2]=(buf>>8)&0xff;
data[3]=buf&0xff;
for(int j=0;j<4;j++){
SpiPs_write_read1(0x070,data[j],&rx_data);
}
}
SpiPs_write_read1(0x071,0x1A,&rx_data);//开启CRC校验
SpiPs_write_read1(0x079,0x08,&rx_data);//开启CRC校验
usleep(1000);
SpiPs_write_read2(0x078,0x00,&rx_data);
temp=rx_data;
if (temp == 0x01) {
xil_printf("CRC successful");
}
else {
xil_printf("CRC unsuccessful");
}
SpiPs_write_read1(0x071,0x06,&rx_data);//处理器门控时钟使能
usleep(10000);
SpiPs_write_read2(0x0A7,0x00,&rx_data);//处理器运行成果标志
temp=rx_data;
if (temp == 0x11) {
xil_printf("core run successful");
}
else {
xil_printf("core run unsuccessful");
}
}
else {
SpiPs_write_read1(0x071,0x00,&rx_data);
}
}
@@ -0,0 +1,129 @@
/*
* frqhop_config.c
*
* Created on: 2023年11月24日
* Author: cxlab
*/
#include "xilinx_io.h"
#include "sleep.h"
#include "time.h"
#include "xtime_l.h"
#include "math.h"
#include "cx9261adriver.h"
#define MIN_FREQ 121.88
#define MAX_FREQ 5000
#define FREQ_SEP 200
//void frqhop_config(int hop_flag,CX9261A::Clock& clock){
void frqhop_config(int hop_flag){
// static XTime tCur;
// XTime_GetTime(&tCur);
// srand(tCur);
// static double hop_freq ;
// hop_freq = (rand()%(800-30))+30+(rand()%(101))/(double)100;//随机产生[30,800)double类型的数
// hop_freq = 3000;
// static double hop_freq1 = 121.88;
static int hop_cnt = 0;
static int next_pll_index = 2;
static double curr_freq;
static double next_freq = MIN_FREQ;
static int unlock_pll1_cnt = 0, unlock_pll2_cnt = 0;
if (hop_flag)
{
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
trx_ch_pll_config(2);
// prepare next pll
CX9261A::configPll1(next_freq, *ref_clock);
while (!CX9261A::afcPll1()) {
unlock_pll1_cnt++;
}
// index update
next_pll_index = 1;
}
else
{
// switch pll
trx_ch_pll_config(1);
// prepare next pll
CX9261A::configPll2(next_freq, *ref_clock);
while (!CX9261A::afcPll2()) {
unlock_pll1_cnt++;
}
// index update
next_pll_index = 2;
}
}
// const double pll1_hop_freq1 = 121.88;
// const double pll1_hop_freq2 = 500;
// const double pll2_hop_freq1 = 4500;
// const double pll2_hop_freq2 = 5000;
//
// static int pll_index=1;
// static int unlock_pll1_cnt=0,unlock_pll2_cnt=0;
// static double pll1_hop_freq = 121.88; // need to be same as initial configuration
// static double pll2_hop_freq = 5000; // need to be same as initial configuration
// static double last_freq;
//
// if(hop_flag == 1){
// if(pll_index == 1 || pll_index == 3){
// //切换至pll2来源
// trx_ch_pll_config(2);
// last_freq = pll2_hop_freq;
// if (pll1_hop_freq == pll1_hop_freq1) {
// pll1_hop_freq = pll1_hop_freq2;
// }
// else {
// pll1_hop_freq = pll1_hop_freq1;
// }
// //配置pll1参数
// CX9261A::configPll1(pll1_hop_freq,*ref_clock);
//// unlock_pll1_cnt=PLL_config(1,pll1_hop_freq,ref)-1;
// CX9261A::afcPll1();
//// while (!CX9261A::afcPll1()) {
//// unlock_pll1_cnt++;
//// }
// pll_index = 2;
// }
// else if(pll_index == 2 || pll_index == 4){
// //切换至pll1来源
// trx_ch_pll_config(1);
// last_freq = pll1_hop_freq;
// if (pll2_hop_freq == pll2_hop_freq1) {
// pll2_hop_freq = pll2_hop_freq2;
// }
// else {
// pll2_hop_freq = pll2_hop_freq1;
// }
// //配置pll2参数
// CX9261A::configPll2(pll2_hop_freq,*ref_clock);
//// unlock_pll2_cnt=PLL_config(2,hop_freq,ref)-1;
//// CX9261A::afcPll2();
//// while (!CX9261A::afcPll2()) {
//// unlock_pll2_cnt++;
//// }
// pll_index = 1;
// }
// }
// hop_freq1 = hop_freq;
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);
}
}
@@ -0,0 +1,197 @@
#include "cx9261adriver.h"
#include "defs.h"
#include "utils.h"
#include "xilinx_io.h"
int main() {
SpiPsInit(SPI_DEVICE_ID);
GpioInit(GPIO_DEVICE_ID);
/* cx9261a configuration */
peripheral_test();
download_bin();//多频点校准CX9261A处理器执行文件
AXIGpioInit();
XScuGicInit();
ConfigAXIGPIOIntr();
ExceptionInit();
/***********************配置参数定义*****************************/
// 芯片配置结构体
CX9261A::CX9261AConfiguration configuration;
// 电源管理 (与评估软件电源管理自定义电源里面勾选项相对应,先左再右,从上往下)
// 断电模式电源管理
configuration.powerManagement.shutdownPower = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// 接收模式电源管理
configuration.powerManagement.rxPower = {0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0,
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
// 发射模式电源管理
configuration.powerManagement.txPower = {1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
// FDD模式电源管理
configuration.powerManagement.fddPower = {1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1};
// 电源模式 即初始化配置结束后的电源模式
configuration.powerManagement.powerMode = CX9261A::PowerMode::Duplex;
// 接口模式
configuration.interface = {
.workMode = CX9261A::WorkMode::FDD,
.trMode = CX9261A::TrMode::R1T1,
.portMode = CX9261A::PortMode::Single,
.ioMode = CX9261A::IOMode::CMOS
};
// 时钟相关 (与评估软件参考配置和基带配置相对应)
configuration.clock = {
.ref = 100, .adc = 64, .refDiv = 1, .bbUseIntDiv = false, .refDoubler = false
};
// 本振相关
using LoSource = CX9261A::LoSource;
// 本振来源
configuration.pllSource = {.rxUseExt = false,
.txUseExt = false,
.rx1Source = LoSource::Pll1,
.rx2Source = LoSource::Pll2,
.rx3Source = LoSource::Off,
.tx1Source = LoSource::Pll1,
.tx2Source = LoSource::Off};
// 本振频率 注意:使用的所有PLL,频率必须设为正数
configuration.pllFreq = {
.pll1Freq = 121.88, .pll2Freq = 2000, .pll3Freq = 800, .pll4Freq = 900, .pll5Freq = 1000};
// Rx通道 注意:tia推荐配置为6 Mixer为三个通道共用同一个寄存器
configuration.rx1Config = {.bandwidth = 32, .tia = 6, .mixer = 31};
configuration.rx2Config = {.bandwidth = 32, .tia = 6, .mixer = 31};
configuration.rx3Config = {.bandwidth = 32, .tia = 6, .mixer = 31};
// Tx通道
configuration.tx1Config = {.bandwidth = 20, .mixer = 63};
configuration.tx2Config = {.bandwidth = 20, .mixer = 63};
// 接收滤波器
configuration.rxFilters = {.fir = 0, .hbf1 = 0, .hbf2 = 0, .hbf3 = 0, .cic = 0};
// 发射滤波器
configuration.txFilters = {.fir = 0, .hbf1 = 2, .hbf2 = 2, .hbf3 = 0, .cic = 0};
// Rx NCO
configuration.rxNco = {
.rxUseBist = false, .rxNCOBypass = true, .rxNCOUpward = true, .rxNCOMaster = true, .rxNCOFreq = 0};
// Tx NCO
configuration.txNco = {.txUseBist = false, .txNCOFreq = 1};
// AGC 注意:mode = 0表示关闭AGC,此时其他的参数可以不配置
configuration.agc = {.mode = 0};
configuration.agc.pdt = {.pdtN = 0,.pdtM = 2};
configuration.agc.lmt = {.count = 15,.threshold1 = 2,.threshold2 = 2,.threshold3 = 2,.threshold4 = 2};
configuration.agc.dig = {.count = 15,.threshold1 =-10,.threshold2 =-14,.threshold3 =-30,.threshold4 =-40};
// 校准
configuration.calib = {.calibRx1 = true,
.calibRx2 = true,
.calibRx3 = false,
.calibTx1 = true,
.calibTx2 = true,
.calibDC = true,
.dcCalibLength = 16384,
.f0 = 1.6};
ref_clock = &configuration.clock;
/***********************配置参数执行*****************************/
// 开始配置芯片
CX9261A::initialChip(); // 最开始需要调用此函数
CX9261A::initialPowerConfig(configuration);
using PowerMode = CX9261A::PowerMode;
// 不需要自定义电源管理时,这部分代码可以省略
CX9261A::configPowerPins(configuration.powerManagement.shutdownPower, PowerMode::Shutdown);
CX9261A::configPowerPins(configuration.powerManagement.rxPower, PowerMode::Receive);
CX9261A::configPowerPins(configuration.powerManagement.txPower, PowerMode::Transmit);
CX9261A::configPowerPins(configuration.powerManagement.fddPower, PowerMode::Duplex);
// 配置pll
CX9261A::configBBPLL(configuration);
CX9261A::configPllSource(configuration.pllSource);
CX9261A::configPll1(configuration.pllFreq.pll1Freq, configuration.clock);
CX9261A::configPll2(configuration.pllFreq.pll2Freq, configuration.clock);
// 配置Rx通道
CX9261A::configRxChannel(configuration.rx1Config, CX9261A::RxChannel::Rx1);
CX9261A::configRxChannel(configuration.rx2Config, CX9261A::RxChannel::Rx2);
CX9261A::configRxChannel(configuration.rx3Config, CX9261A::RxChannel::Rx3);
// 配置Tx通道
using TxChannel = CX9261A::TxChannel;
CX9261A::configTxChannelFrequency(configuration.pllFreq.pll1Freq, TxChannel::Tx1);
CX9261A::configTxChannelFrequency(configuration.pllFreq.pll2Freq, TxChannel::Tx2);
CX9261A::configTxChannel(configuration.tx1Config, TxChannel::Tx1);
CX9261A::configTxChannel(configuration.tx2Config, TxChannel::Tx2);
// 配置滤波器
CX9261A::configRxFilters(configuration.rxFilters);
CX9261A::configTxFilters(configuration.txFilters);
// 配置NCO
CX9261A::configRxNco(configuration.rxNco, configuration.clock.adc);
const int filters = std::max(configuration.rxFilters.fir, 1) * std::max(configuration.rxFilters.hbf3, 1) *
std::max(configuration.rxFilters.hbf2, 1) *
std::max(configuration.rxFilters.hbf1, 1) * std::max(configuration.rxFilters.cic, 1);
CX9261A::configTxNco(configuration.txNco, configuration.clock.adc / filters);
// 配置AGC
CX9261A::configAGC(configuration.agc);
// 切换到休眠模式
CX9261A::configPowerMode(PowerMode::Sleep);
CX9261A::pause(1000);
// 切换到校准模式
CX9261A::configPowerMode(PowerMode::Calib);
CX9261A::pause(100);
// 锁定BBPLL
while (!CX9261A::afcBBPll()) {
CX9261A::pause(100);
}
// 锁定PLL1 根据本振来源确定是否需要AFC
while (!CX9261A::afcPll1()) {
CX9261A::pause(100);
}
// 锁定PLL2 根据本振来源确定是否需要AFC
while (!CX9261A::afcPll2()) {
CX9261A::pause(100);
}
// 配置接口
CX9261A::configInterface(configuration.interface);
// 配置FPGA接口相关 此为示例,仅适用于Demo工程,用户应根据实际情况进行配置
CX9261A::configFPGA(configuration.interface);
// 配置校准
CX9261A::configDcCalib(configuration.calib);
CX9261A::configADCCalib(configuration.clock.adc);
CX9261A::configFlashCalib();
CX9261A::configQecCalib(configuration);
// 切换到工作模式
CX9261A::configPowerMode(configuration.powerManagement.powerMode);
//消除杂散信号
// CX9261A::writeSpi(0x75C, 0x83);
// CX9261A::writeSpi(0x766, 0x83);
/***********************多点校准*****************************/
/*
//跳频qec校准频点预设,最多256个频点。其中包含初始频点则加载初始频点校准值给三个通道
const std::vector<double> points = {200,300,400,500,600,700};
CX9261A::configRxMultiPointsQec(configuration, points);
CX9261A::setPin(43, 0);
CX9261A::setPin(43, 1);
// 加载第1组校准系数(300MHz)
configuration.pllFreq.pll1Freq = 300;
CX9261A::configPll1(configuration.pllFreq.pll1Freq, configuration.clock.ref);
CX9261A::afcPll1();
CX9261A::pause(10);
CX9261A::loadRxCalibPredis(1);
// 加载第2组校准系数(400MHz)
configuration.pllFreq.pll1Freq = 400;
CX9261A::configPll1(configuration.pllFreq.pll1Freq, configuration.clock.ref);
CX9261A::afcPll1();
CX9261A::pause(10);
CX9261A::loadRxCalibPredis(2);
// 加载第5组校准系数(700MHz)
configuration.pllFreq.pll1Freq = 700;
CX9261A::configPll1(configuration.pllFreq.pll1Freq, configuration.clock.ref);
CX9261A::afcPll1();
CX9261A::pause(10);
CX9261A::loadRxCalibPredis(5);
*/
/***********************PLL锁定和跳频测试*****************************/
// for(int i=0;i<20000;i++){
// PLL_scan(0);
// PLL_scan(1);
// }
frqhop_flag(1);
while(1);
return 0;
}
@@ -0,0 +1,99 @@
/**
* @file utils.h
*/
#ifndef CX9261ADRIVER_UTILS_H
#define CX9261ADRIVER_UTILS_H
#include <algorithm>
#include <bitset>
#include <cmath>
#include <string>
namespace CX9261A {
#if __cplusplus >= 201703L
template <typename T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return std::clamp(v, lo, hi);
}
#else
template <typename T>
constexpr const T& clamp(const T& v, const T& lo, const T& hi) {
return std::max(std::min(hi, v), lo);
}
#endif
template <typename Float>
int round(Float f) {
return static_cast<int>(std::round(f));
}
template <typename Float>
long long round64(Float f) {
return static_cast<long long>(std::round(f));
}
template <typename Float>
int floor(Float f) {
return static_cast<int>(std::floor(f));
}
template <typename Float>
long long floor64(Float f) {
return static_cast<long long>(std::floor(f));
}
template <typename Float>
int ceil(Float f) {
return static_cast<int>(std::ceil(f));
}
template <typename Float>
long long ceil64(Float f) {
return static_cast<long long>(std::ceil(f));
}
/**
* @brief Register类,提供方便的位操作函数
*/
class Register {
public:
template <typename T = int>
constexpr Register(const T value = 0) {
// static_assert(std::is_integral_v<T>, "Register value must be integral!");
m_value = static_cast<unsigned long long>(value);
}
/**
* 以十进制返回寄存器值
*/
unsigned char value() const { return static_cast<unsigned char>(m_value.to_ulong()); }
/**
* 对寄存器值进行部分值的替换操作
* 例:replace(7, 4, 0b1111); 使寄存器的高四位为1
* @param start 起始位
* @param end 中止位
* @param after 要替换的值
*/
void replace(const unsigned int start, const unsigned int end, unsigned char after) {
for (auto i = end; i <= start; ++i) {
m_value[i] = (after >> (i - end)) & 0b1;
}
}
auto operator[](const size_t position) { return m_value[position]; }
template <typename Type>
operator Type() const {
// static_assert(std::is_integral_v<Type>, "Type must be an integral");
return static_cast<Type>(m_value.to_ulong());
}
private:
std::bitset<8> m_value{};
};
template <int N>
std::string frac2bin(const double frac) {
const long double num = frac * (pow(2.0, N));
std::string ret = std::bitset<N>(std::floor(num)).to_string();
return ret;
}
} // namespace CX9261A
#endif // CX9261ADRIVER_UTILS_H
@@ -0,0 +1,677 @@
/*
* xilinx_io.cc
*
* Created on: 2024年3月5日
* Author: cxlab
*/
#include "sleep.h"
#include "math.h"
#include "xilinx_io.h" /* SPI device driver */
#include "cx9261adriver.h"
#include "utils.h"
#include <stdio.h>
CX9261A::Clock* ref_clock;
static XSpiPs SpiInstance;
XGpioPs Gpio; /* The driver instance for GPIO Device. */
XGpio axi_gpio_inst; //PL 端 AXI GPIO 驱动实例
XScuGic scugic_inst; //中断控制器 驱动实例
XScuGic_Config * scugic_cfg_ptr; //中断控制器 配置信息
int hop_flag,hop_intr_flag;
static int spi_select_value=0;
void AXIGpioInit(void){
XGpio_Initialize(&axi_gpio_inst, AXI_GPIO_ID);
//配置 PL AXI GPIO
XGpio_SetDataDirection(&axi_gpio_inst, 1, 1); //设置 AXI GPIO 通道 1 为输入
XGpio_InterruptEnable(&axi_gpio_inst, KEY_MASK); //使能通道 1 中断
XGpio_InterruptGlobalEnable(&axi_gpio_inst); //使能 AXI GPIO 全局中断
}
void ConfigAXIGPIOIntr(void){
//设置中断优先级和触发类型(高电平触发)
XScuGic_SetPriorityTriggerType(&scugic_inst, GPIO_INT_ID, 0xA0, 0x3);
//关联中断 ID 和中断处理函数
XScuGic_Connect(&scugic_inst, GPIO_INT_ID, axi_gpio_handler, &axi_gpio_inst);
//使能 AXI GPIO 中断
XScuGic_Enable(&scugic_inst, GPIO_INT_ID);
}
void axi_gpio_handler(void *CallbackRef){
XGpio *GpioPtr = (XGpio *)CallbackRef;
// print("Interrupt Detected!\n");
GpioWritePin(hop,0x01);
XGpio_InterruptDisable(GpioPtr, KEY_MASK); //关闭 AXI GPIO 中断使能
// frqhop_config(hop_flag, *ref_clock);
frqhop_config(hop_flag);
XGpio_InterruptClear(GpioPtr, KEY_MASK); //清除中断
XGpio_InterruptEnable(GpioPtr, KEY_MASK); //使能 AXI GPIO 中断
GpioWritePin(hop,0x00);
}
void frqhop_flag(int frqhop_flag){
u8 rx_data;
hop_flag = frqhop_flag;
GpioSetPinDir(hop,GPIO_DIR_OUTPUT);
GpioWritePin(hop,0x01);
SpiPs_write_read2(0x615,0x00,&rx_data);
GpioWritePin(hop,0x00);
}
void ExceptionInit(void){
//设置并打开中断异常处理功能
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, &scugic_inst);
Xil_ExceptionEnable();
}
void XScuGicInit(void){
scugic_cfg_ptr = XScuGic_LookupConfig(SCUGIC_ID);
XScuGic_CfgInitialize(&scugic_inst, scugic_cfg_ptr, scugic_cfg_ptr->CpuBaseAddress);
}
namespace CX9261A {
extern std::vector<int> configPllImpl(const double lo, const double ref);
}
int peripheral_test(void){
u8 spi_test;
u8 Gpio_test;
u8 BRAM_test;
u8 DDR_test;
// SPI TEST
u8 rx_data;
xil_printf("start spi test.\r\n");
u8 spi_wr_buff[3]={0x87,0x82,0x5A};
u8 spi_rd_buff[3]={0x07,0x82,0x00};
SpiPs_write_read(spi_wr_buff,&rx_data);
SpiPs_write_read(spi_rd_buff,&rx_data);
if(rx_data==spi_wr_buff[2])
{
xil_printf("spi test successful.\r\n");
spi_test = 1;
}else
{
xil_printf("spi test unsuccessful.\r\n");
spi_test = 0;
}
//BRAM TEST
xil_printf("start bram test.\r\n");
BRAM_test = 1;
for (int i=0;i<8192;i++){
Xil_Out32(XPAR_BRAM_0_BASEADDR + 4*i,i);
if(i != Xil_In32(XPAR_BRAM_0_BASEADDR + 4*i)){
// xil_printf("BRAM ERROR,ADDR %x DATA %d read back is %d.\r\n",XPAR_BRAM_0_BASEADDR + 4*i,i,Xil_In32(XPAR_BRAM_0_BASEADDR + 4*i));
BRAM_test = 0;
}
// else{
// xil_printf("BRAM PASS,ADDR %x DATA %d read back is %d.\r\n",XPAR_BRAM_0_BASEADDR + 4*i,i,Xil_In32(XPAR_BRAM_0_BASEADDR + 4*i));
// }
}
//MIG TEST
xil_printf("start mig test.\r\n");
DDR_test = 1;
for (int i=0;i<2048;i++){
Xil_Out32(TX_BUFFER_BASE + 4*i,i);
if(i != Xil_In32(TX_BUFFER_BASE + 4*i)){
// xil_printf("MIG ERROR,ADDR %x DATA %d read back is %d.\r\n",TX_BUFFER_BASE + 4*i,i,Xil_In32(TX_BUFFER_BASE + 4*i));
DDR_test = 0;
}
// else{
// xil_printf("BRAM11 PASS,ADDR %x DATA %d read back is %d.\r\n",TX_BUFFER_BASE + 4*i,i,Xil_In32(TX_BUFFER_BASE + 4*i));
// }
}
// GPIO TEST
int Gpio_data=1;
xil_printf("start gpio test.\r\n");
GpioSetPinDir(NRST,GPIO_DIR_OUTPUT);
GpioWritePin(NRST,0x00);
GpioWritePin(NRST,0x01);
GpioSetPinDir(rst,GPIO_DIR_OUTPUT);
GpioWritePin(rst,0x01);
GpioWritePin(rst,0x00);
GpioSetPinDir(aresetn_0,GPIO_DIR_OUTPUT);
GpioWritePin(aresetn_0,0x00);
GpioWritePin(aresetn_0,0x01);
GpioSetPinDir(aresetn_1,GPIO_DIR_OUTPUT);
GpioWritePin(aresetn_1,0x00);
GpioWritePin(aresetn_1,0x01);
GpioSetPinDir(aresetn_2,GPIO_DIR_OUTPUT);
GpioWritePin(aresetn_2,0x00);
GpioWritePin(aresetn_2,0x01);
GpioSetPinDir(debug_mode,GPIO_DIR_OUTPUT);
GpioWritePin(debug_mode,0x00);
GpioSetPinDir(cx3e04_rstn,GPIO_DIR_OUTPUT);
GpioWritePin(cx3e04_rstn,0x01);
GpioSetPinDir(spi_select,GPIO_DIR_OUTPUT);
GpioWritePin(spi_select,spi_select_value&0xff);
//GpioSetPinDir(test_temp,GPIO_DIR_INPUT);
Gpio_data=GpioReadPin(aresetn_1);
if(Gpio_data==1)
{
xil_printf("GPIO test successful.\r\n");
Gpio_test = 1;
}else
{
xil_printf("GPIO test unsuccessful.\r\n");
Gpio_test = 0;
}
//GpioSetPinDir(test_temp,GPIO_DIR_OUTPUT);
//GpioWritePin(test_temp,0x01);
if((spi_test==1)&&(Gpio_test==1)&&(BRAM_test==1)&&(DDR_test==1))
{
xil_printf("peripheral test successful.\r\n");
return 1;
}else
{
xil_printf("peripheral test unsuccessful.\r\n");
return 0;
}
}
int SpiPsInit(u16 SpiDeviceId){
int Status;
XSpiPs_Config *SpiConfig;
/*
* Initialize the SPI driver so that it's ready to use
*/
SpiConfig = XSpiPs_LookupConfig(SpiDeviceId);
if (NULL == SpiConfig) {
return XST_FAILURE;
}
Status = XSpiPs_CfgInitialize((&SpiInstance), SpiConfig,
SpiConfig->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* Perform a self-test to check hardware build
*/
Status = XSpiPs_SelfTest((&SpiInstance));
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
/*
* The SPI device is a slave by default and the clock phase
* have to be set according to its master. In this example, CPOL is set
* to quiescent high and CPHA is set to 1.
*/
XSpiPs_SetOptions((&SpiInstance), (XSPIPS_CR_CPHA_MASK) |
XSPIPS_MASTER_OPTION |
XSPIPS_FORCE_SSELECT_OPTION);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
XSpiPs_SetClkPrescaler((&SpiInstance), XSPIPS_CLK_PRESCALE_8);
/*
* Set the Rx FIFO Threshold to the Max Data
*/
// XSpiPs_SetRXWatermark((&SpiInstance),MAX_DATA);
/*
* Enable the device.
*/
XSpiPs_Enable((&SpiInstance));
return XST_SUCCESS;
}
int cx9261a_write(int addr , int value)
{
Xil_Out32(AXI4_LITE1_SPI_BASEADDR+addr*4,value);
return 1;
}
int cx9261a_read(int addr)
{
return Xil_In32(AXI4_LITE1_SPI_BASEADDR+addr*4);
}
//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data){
int SpiPs_write_read(u8 * data,u8 * rx_data){
int Status;
u8 rx_buffer[3];
if(spi_select_value == 0){
rx_buffer[0]= *data;
rx_buffer[1]= *(data+1);
rx_buffer[2]= *(data+2);
if(rx_buffer[0] >= 128){
cx9261a_write((rx_buffer[0]-128)*256+rx_buffer[1],rx_buffer[2]);
}else{
*rx_data=cx9261a_read(rx_buffer[0]*256+rx_buffer[1]);
}
}else{
XSpiPs_SetSlaveSelect((&SpiInstance),0x00);
Status = XSpiPs_PolledTransfer((&SpiInstance),data,rx_buffer,3);
*rx_data = rx_buffer[2];
}
return 0;
}
int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data){
u8 rx_data1;
u16 temp;
u8 rx_buffer[3];
temp= addr&0x00ff;
rx_buffer[0]= temp/256+128;
rx_buffer[1]= addr&0x00ff;
rx_buffer[2]= data;
if(spi_select_value == 0){
cx9261a_write(addr,data);
}else{
SpiPs_write_read((u8 *)&rx_buffer,&rx_data1);
*rx_data = rx_data1;
}
return 0;
}
int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data){
u8 rx_data1;
u16 temp;
u8 rx_buffer[3];
temp= addr&0x00ff;
rx_buffer[0]= temp/256;
rx_buffer[1]= addr&0x00ff;
rx_buffer[2]= data;
if(spi_select_value == 0){
*rx_data=cx9261a_read(addr);
}else{
SpiPs_write_read((u8 *)&rx_buffer,&rx_data1);
*rx_data = rx_data1;
}
return 0;
}
int GpioInit(u16 DeviceId)
{
int Status;
XGpioPs_Config *ConfigPtr;
/* Initialize the GPIO driver. */
ConfigPtr = XGpioPs_LookupConfig(DeviceId);
Status = XGpioPs_CfgInitialize(&Gpio, ConfigPtr,
ConfigPtr->BaseAddr);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
int GpioSetPinDir(u32 Pin,u32 Direction){
XGpioPs_SetDirectionPin((&Gpio),GPIO_EMIO_OFFSET + Pin,Direction);
return 0;
}
int GpioWritePin(u32 Pin,u32 data){
XGpioPs_SetOutputEnablePin(&Gpio, GPIO_EMIO_OFFSET + Pin, 1);
XGpioPs_WritePin((&Gpio),GPIO_EMIO_OFFSET + Pin,data);
return 0;
}
int GpioReadPin(u32 Pin){
return XGpioPs_ReadPin((&Gpio),GPIO_EMIO_OFFSET + Pin);
}
int rom_read(u8 * data)
{
int addr ;
addr = *(data + 0)*256+ *(data + 1);
return Xil_In32(BROM_BASEADDR+addr*4);
}
void 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;
}
recv_buf[0] =(trx_ch_pll_data>>16 & 0xff)|0x80 ;
recv_buf[1] = trx_ch_pll_data>>8 & 0xff;
recv_buf[2] = trx_ch_pll_data & 0xff;
SpiPs_write_read(recv_buf,&rx_data);
}
u16 pll1_config_addr[] ={0x0620,0x061D,0x0B06,0x0B07,0x0B08,0x0B09,0x0B0A,0x061A,0x061B,0x061C,0x062A};
u16 pll2_config_addr[] ={0x0642,0x063F,0x0B14,0x0B15,0x0B16,0x0B17,0x0B18,0x063C,0x063D,0x063E,0x064C};
u16 pll3_config_addr[] ={0x0664,0x0661,0x0B22,0x0B23,0x0B24,0x0B25,0x0B26,0x065E,0x065F,0x0660,0x066E};
u16 pll4_config_addr[] ={0x0686,0x0683,0x0B30,0x0B31,0x0B32,0x0B33,0x0B34,0x0680,0x0681,0x0682,0x0690};
int PLL_config(u8 pll_index,double pll_frq,double ref)
{
int i = 0,afc_cnt=0;
u16 pll_config_addr[11];
u16 afc_addr,lock_addr;
// double ref=200;
u8 pllreg_buf[11];
u8 recv_buf[3];
u8 rx_data,pll_div;
u16 div_addr;
switch(pll_index){
case 1:for (i = 0; i < 11; i++){pll_config_addr[i] = pll1_config_addr[i];} afc_addr=0x0617;lock_addr=0x0635;break;
case 2:for (i = 0; i < 11; i++){pll_config_addr[i] = pll2_config_addr[i];} afc_addr=0x0639;lock_addr=0x0657;break;
case 3:for (i = 0; i < 11; i++){pll_config_addr[i] = pll3_config_addr[i];} afc_addr=0x065B;lock_addr=0x0679;break;
case 4:for (i = 0; i < 11; i++){pll_config_addr[i] = pll4_config_addr[i];} afc_addr=0x067D;lock_addr=0x069B;break;
default :;
}
//caculate pll frequence word
pll_frq_caculation_new(ref,pll_frq,(u8 *)&pllreg_buf);
for (i = 0; i < 11; i++)
{
recv_buf[0] = (pll_config_addr[i]>>8 & 0xff)|0x80 ;
recv_buf[1] = pll_config_addr[i] & 0xff;
recv_buf[2] = pllreg_buf[i] & 0xff;
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
}
//afc pll
pll_div = pllreg_buf[1];
div_addr = pll_config_addr[1];
recv_buf[0] = lock_addr>>8 & 0xff ;
recv_buf[1] = lock_addr & 0xff;
recv_buf[2] = 0x00;
rx_data = 0;
while(rx_data!=48){
PLL_afc(afc_addr,div_addr,pll_div);
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
afc_cnt++;
}
return afc_cnt;
//xil_printf("afc lock count: %d.\r\n",afc_cnt);
}
void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div){
u8 recv_buf[3];
u8 rx_data;
if(pll_div>=48){
recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ;
recv_buf[1] = div_addr & 0xff;
recv_buf[2] = pll_div & 0x2f;
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
}
recv_buf[0] = (afc_addr>>8 & 0xff)|0x80 ;
recv_buf[1] = afc_addr & 0xff;
recv_buf[2] = 0x00;
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
recv_buf[2] = 0x03;
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
usleep(30);
if(pll_div>=48){
recv_buf[0] = (div_addr>>8 & 0xff)|0x80 ;
recv_buf[1] = div_addr & 0xff;
recv_buf[2] = pll_div & 0xff;
SpiPs_write_read((u8 *)&recv_buf[0],&rx_data);
}
}
int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data){
u8 row,column;
double vco = pll_frq;
int div = 1;
while(vco < 6701){
vco = vco*2;
div = div*2;
}
char coreTable[7][4][3] = {{{0x0C,0x30,0x08},{0x0B,0x30,0x09},{0x0C,0x30,0x05},{0x0D,0x30,0x08}},
{{0x0C,0x30,0x0C},{0x0B,0x30,0x0E},{0x0C,0x30,0x08},{0x0D,0x30,0x0B}},
{{0x0C,0x20,0x10},{0x0B,0x20,0x10},{0x0C,0x20,0x0A},{0x0D,0x20,0x0D}},
{{0x0C,0x20,0x11},{0x0B,0x20,0x13},{0x0C,0x20,0x0C},{0x0D,0x20,0x0F}},
{{0x0D,0x30,0x14},{0x0D,0x22,0x14},{0x0D,0x20,0x0D},{0x0D,0x15,0x0C}},
{{0x0E,0x30,0x18},{0x0E,0x25,0x16},{0x0E,0x25,0x0F},{0x0E,0x18,0x0F}},
{{0x0F,0x38,0x1A},{0x0F,0x32,0x1C},{0x0F,0x18,0x12},{0x0F,0x18,0x12}}};
if (ref >= 28 && ref < 40){
row = 0;
}else if (ref >= 40 && ref < 60){
row = 1;
}else if (ref >= 60 && ref < 90){
row = 2;
}else if (ref >= 90 && ref < 110){
row = 3;
}else if (ref >= 110 && ref < 140){
row = 4;
}else if (ref >= 140 && ref < 180){
row = 5;
}else if (ref >= 180 && ref <= 240){
row = 6;
}
if (vco < 8400){
column = 0;
}else if (vco >= 8400 && vco < 10150){
column = 1;
}else if (vco >= 10150 && vco < 12000){
column = 2;
}else if (vco >= 12000 ){
column = 3;
}
char cp = coreTable[row][column][0];
char c1r3 = coreTable[row][column][1];
char r1 = coreTable[row][column][2];
char dither,nHigh,nLow,fHigh,fMiddle,fLow,outputDiv,core = 0x81;
if(vco > 10150){
core = core + 0x10;
}
if (div == 2){
outputDiv = 0+7;
}else if (div == 4){
outputDiv = 32+7;
}else{
outputDiv = 48 + divBin(div);
}
double nf = 1.0*vco / ref;
int n = nf;
double f = nf - n;
if(f > 1e-10){
dither = 11;
}else{
dither = 0;
}
if(n >= 256){
nHigh = 1;
}else{
nHigh = 0;
}
nLow = n & 0xff;
int f1 = f * pow(2,24);
fHigh = f1>>16 & 0xff;
fMiddle = f1>>8 & 0xff;
fLow = f1 & 0xff;
reg_data[0]=core;
reg_data[1]=outputDiv;
reg_data[2]=nHigh;
reg_data[3]=nLow;
reg_data[4]=fHigh;
reg_data[5]=fMiddle;
reg_data[6]=fLow;
reg_data[7]=cp;
reg_data[8]=c1r3;
reg_data[9]=r1;
reg_data[10]=dither;
return 0;
}
char divBin(u16 div){
switch(div){
case 8:return 7;break;
case 16:return 6;break;
case 32:return 5;break;
case 64:return 4;break;
case 128:return 3;break;
case 256:return 2;break;
default :return 2;
}
}
void hop_configPll1(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap)
{
writeSpi(0x620, pllMap["core"]);
writeSpi(0x61D, pllMap["outputDiv"]);
writeSpi(0xB06, pllMap["nHigh"]);
writeSpi(0xB07, pllMap["nLow"]);
writeSpi(0xB08, pllMap["fHigh"]);
writeSpi(0xB09, pllMap["fMiddle"]);
writeSpi(0xB0A, pllMap["fLow"]);
}
void hop_configPll2(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap)
{
writeSpi(0x642, pllMap["core"]);
writeSpi(0x63F, pllMap["outputDiv"]);
writeSpi(0xB14, pllMap["nHigh"]);
writeSpi(0xB15, pllMap["nLow"]);
writeSpi(0xB16, pllMap["fHigh"]);
writeSpi(0xB17, pllMap["fMiddle"]);
writeSpi(0xB18, pllMap["fLow"]);
}
void hop_configPll3(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap)
{
writeSpi(0x664, pllMap["core"]);
writeSpi(0x661, pllMap["outputDiv"]);
writeSpi(0xB22, pllMap["nHigh"]);
writeSpi(0xB23, pllMap["nLow"]);
writeSpi(0xB24, pllMap["fHigh"]);
writeSpi(0xB25, pllMap["fMiddle"]);
writeSpi(0xB26, pllMap["fLow"]);
}
void hop_configPll4(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap)
{
writeSpi(0x686, pllMap["core"]);
writeSpi(0x683, pllMap["outputDiv"]);
writeSpi(0xB30, pllMap["nHigh"]);
writeSpi(0xB31, pllMap["nLow"]);
writeSpi(0xB32, pllMap["fHigh"]);
writeSpi(0xB33, pllMap["fMiddle"]);
writeSpi(0xB34, pllMap["fLow"]);
}
void hop_configPll5(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap)
{
writeSpi(0x6A8, pllMap["core"]);
writeSpi(0x6A5, pllMap["outputDiv"]);
writeSpi(0xB3E, pllMap["nHigh"]);
writeSpi(0xB3F, pllMap["nLow"]);
writeSpi(0xB40, pllMap["fHigh"]);
writeSpi(0xB41, pllMap["fMiddle"]);
writeSpi(0xB42, pllMap["fLow"]);
}
void PLL_scan(int pllx)
{
double i = 30.0;
xil_printf("PLL scan start -%d-\r\n",pllx);
//扫频30MHz~800MHz 步进1MHz cx9261初始化默认收状态,如果默认是发状态需要切换到收状态
for(i=30.0;i<=800.0;i+=0.025)
// for(i=40.000;i<=40.625;i+=0.025)
{
cx9261a_pll_src_config(i, pllx);
// CX9261A::pause(CX9261A::delay_afc);
}
CX9261A::writeSpi(0x10a, 0x71); // 扫频完得到每个频率IQ直流校准值后关闭直流校准
xil_printf("PLL scan end -%d-\r\n",pllx);
}
void cx9261a_pll_src_config(double freq, int pll_num)
{
int temp = 0;
// auto pll1Map=CX9261A::configPllImpl(freq,200);
// auto pll2Map=CX9261A::configPllImpl(freq,200);
if((freq < 30) || (freq > 1000))
{
printf("The configured frequency[%lf MHz] is out of range.\r\n", freq);
}
switch(pll_num)
{
case 0:
// hop_configPll1(freq, 200,pll1Map);
CX9261A::configPll1(freq, *ref_clock);
CX9261A::writeSpi(0x62A,0x00);
temp = 0;
while (!CX9261A::afcPll1()) {
temp++;
// int reg_626=CX9261A::readSpi(0x626);
int reg_635=CX9261A::readSpi(0x635);
reg_635=CX9261A::readSpi(0x635);
reg_635=CX9261A::readSpi(0x635);
int reg_61D=CX9261A::readSpi(0x61D);
int reg_637=CX9261A::readSpi(0x637);
if(3 == temp)
{
printf("afcPll1 error h:%fMhz.\r\n", freq);
break;
}
}
break;
case 1:
// hop_configPll2(freq, 200,pll2Map);
CX9261A::configPll2(freq, *ref_clock);
CX9261A::writeSpi(0x64C,0x00);
temp = 0;
while (!CX9261A::afcPll2()) {
temp++;
if(3 == temp)
{
printf("afcPll2 error h:%lfMhz .\r\n", freq);
break;
}
}
break;
case 2:
CX9261A::configPll3(freq, *ref_clock);
temp = 0;
while (!CX9261A::afcPll3()) {
temp++;
if(4 == temp)
{
break;
}
}
break;
case 3:
CX9261A::configPll4(freq, *ref_clock);
temp = 0;
while (!CX9261A::afcPll4()) {
temp++;
if(4 == temp)
{
break;
}
}
break;
default:
xil_printf("config PLL source error.\r\n");
break;
}
}
@@ -0,0 +1,167 @@
/*
* xilinx_io.h
*
* Created on: 2021年9月6日
* Author: cxlab
*/
#ifndef SRC_XILINX_IO_H_
#define SRC_XILINX_IO_H_
#endif /* SRC_XILINX_IO_H_ */
#include "xspips.h" /* SPI device driver */
#include "xgpiops.h"
#include "xgpio.h"
#include "xaxidma.h"
#include "xparameters.h"
#include "utils.h"
#include <map>
#include "xscugic.h"
#include "xil_exception.h"
#include "defs.h"
extern CX9261A::Clock* ref_clock;
//#define DBGLOG
#define MAX_DATA 100
#define SPI_WRITE 0x80
#define SPI_READ 0x00
#define GPIO_DIR_INPUT 0x00
#define GPIO_DIR_OUTPUT 0x01
#define GPIO_EMIO_OFFSET 54
#define TX_EN 0x08
#define RX_EN 0x07
#define GPIO_1 0x06
#define GPIO_0 0x05
#define NRST 0
#define ENABLE_TRX1 1
#define ENABLE_TRX2 2
#define ENABLE_TRX3 3
#define TXNRX_TRX1 4
#define TXNRX_TRX2 5
#define TXNRX_RX3 6
#define aresetn_0 33
#define rst 34
#define tr_sel 35
#define tdd_fdd_sel 36
#define r1t1_r2t2_sel 37
#define sp_dp_sel 38
#define aresetn_1 39
#define aresetn_2 40
#define hop 41
#define cx3e04_rstn 42
#define spi_select 46
#define debug_mode 63
#define INTER_SIG3 0x03//dma_axis_rx_rstn
#define INTER_SIG2 0x02//frame_pattern
#define INTER_SIG1 0x01//mode_sel_async
#define INTER_SIG0 0x00//rst_async
#define SPI_DEVICE_ID XPAR_XQSPIPS_0_DEVICE_ID
#define GPIO_DEVICE_ID XPAR_PS7_GPIO_0_DEVICE_ID
#define AXI_DMA_DEVCIE_ID0 XPAR_AXI_DMA_0_DEVICE_ID
#define AXI_DMA_DEVCIE_ID1 XPAR_AXI_DMA_1_DEVICE_ID
#define AXI_DMA_DEVCIE_ID2 XPAR_AXI_DMA_2_DEVICE_ID
#define BROM_BASEADDR XPAR_M08_AXI_0_BASEADDR
#define AXI4_LITE0_SPI_BASEADDR XPAR_AXI4_LITE_SPI_0_BASEADDR
#define AXI4_LITE1_SPI_BASEADDR XPAR_AXI4_LITE_SPI_1_BASEADDR
#define BRAM_BASEADDR XPAR_AXI_BRAM_CTRL_0_S_AXI_BASEADDR
#define BRAM_BASEADDR_1 XPAR_AXI_BRAM_CTRL_1_S_AXI_BASEADDR
#define PACKER_BASEADDR0 XPAR_AXIS_ADC_DATA_PACKER_0_S00_AXI_BASEADDR
#define PACKER_BASEADDR1 XPAR_AXIS_ADC_DATA_PACKER_1_S00_AXI_BASEADDR
#define PACKER_BASEADDR2 XPAR_AXIS_ADC_DATA_PACKER_2_S00_AXI_BASEADDR
#define WAVELENGTH 8192
#define TX_BUFFER_BASE XPAR_MIG_7SERIES_0_BASEADDR +0x2000
#define WAVE_LENGTH 8192*4
#define GPIO_INT_ID XPAR_FABRIC_GPIO_0_VEC_ID //PL 端 AXI GPIO 中断 ID
#define AXI_GPIO_ID XPAR_AXI_GPIO_0_DEVICE_ID //PL 端 AXI GPIO 器件 ID
#define SCUGIC_ID XPAR_SCUGIC_0_DEVICE_ID //中断控制器 ID
#define KEY_MASK XGPIO_IR_CH1_MASK //通道 1 的位定义
void AXIGpioInit(void);
void ConfigAXIGPIOIntr(void);
void axi_gpio_handler(void *CallbackRef);
void XScuGicInit(void);
void ExceptionInit(void);
int cx3e04_write(int addr , int value);
int cx3e04_read(int addr);
int cx9261a_write(int addr , int value);
int cx9261a_read(int addr);
void cx3e04_config(void);
int SpiPsInit(u16 SpiDeviceId);
//int SpiPs_write_read(u8 cmd, u16 addr,u8 data,u8 * rx_data);
int SpiPs_write_read(u8 * data,u8 * rx_data);
int SpiPs_write_read1(u16 addr,u8 data,u8 * rx_data);
int SpiPs_write_read2(u16 addr,u8 data,u8 * rx_data);
int GpioInit(u16 DeviceId);
int GpioSetPinDir(u32 Pin,u32 Direction);
int GpioWritePin(u32 Pin,u32 data);
int GpioReadPin(u32 Pin);
void DeviceRst(void);
//校准
void cx9261a_151_config(void);
void cx9261a_076_config(void);
void rxFFTCalib(int lo, int fs,int ref, int firLength,int chan);
void configTxNcoFreq(int freq, int fs);
void configRxNcoFreq(int freq, int fs);
void configDcCalib(int dcCalibEnable,int dcCalibLength);
void txBisectionQecCalib(int f0, int fs);
void txBisectionDcCalib(int f0, int fs);
extern XAxiDma* xAxiDma0Get(void);
extern XAxiDma* xAxiDma1Get(void);
extern XAxiDma* xAxiDma2Get(void);
int XAxiDma_Init(XAxiDma* AxiDma,u16 DeviceId);
int XAxiDmaCapture(XAxiDma* AxiDma,u32 data_length);
int XAxiDmaCapture2(XAxiDma* AxiDma,u32 data_length);
int DownloadWave(u8 * data);
int SetPacketSize(XAxiDma* AxiDma,u32 length);
void dbg_printf( const char8 *ctrl1, ...);
void PackerRst(void);
int peripheral_test(void);
#define SPI_STACK_LENGTH 65536
struct spi_stack {
int spi_write_num;
u8 recv_buf[SPI_STACK_LENGTH*3];
};
int spi_stack_in(u8 * data,struct spi_stack * spistack);
void spi_stack_out(struct spi_stack * spistack);
int rom_read(u8 * data);
void download_bin(void);
//跳频
void hop_configPll1(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap);
void hop_configPll2(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap);
void hop_configPll3(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap);
void hop_configPll4(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap);
void hop_configPll5(const double lo, const double ref, std::map<std::string, CX9261A::Register>& pllMap);
//跳频
//void frqhop_config(int hop_flag,CX9261A::Clock& clock);
void frqhop_config(int hop_flag);
void frqhop_flag(int frqhop_flag);
int PLL_config(u8 pll_index,double pll_frq,double ref);
void trx_ch_pll_config(u8 pll_index);
int pll_frq_caculation(double ref,double pll_frq,u8 *reg_data);
int pll_frq_caculation_new(double ref,double pll_frq,u8 *reg_data);
void PLL_afc(u16 afc_addr,u16 div_addr,u8 pll_div);
char divBin(u16 div);
void PLL_scan(int pllx);
void cx9261a_pll_src_config(double freq, int pll_num);