Initial commit

This commit is contained in:
Gatsby Van
2024-10-27 21:53:10 +08:00
commit 626f4db6f3
10 changed files with 47157 additions and 0 deletions
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+544
View File
@@ -0,0 +1,544 @@
/**
* @file cx9261adriver.h
*/
#ifndef CX9261ADRIVER_CX9261ADRIVER_H
#define CX9261ADRIVER_CX9261ADRIVER_H
#define VERSION 1.9.0
#include "defs.h"
#ifdef USE_LOGGING
# define LOGGING(x) logging(x);
#else
# define LOGGING(x)
#endif
namespace CX9261A {
#ifdef USE_LOGGING
/**
* @brief 输出日志的函数
* @param msg 要输出的内容
*/
void logging(const std::string& msg);
#endif
/**
* @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 initialChip();
/**
* @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数
*/
void initialPowerConfig(const CX9261AConfiguration& config);
/**
* @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 配置受参考时钟频率影响的寄存器
* @param ref 参考时钟频率,单位MHz
*/
void configRef(double ref);
/**
* @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 配置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 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器
* @param on 开启/关闭
*/
void configRISCV(bool on);
/**
* @brief 配置温补
* @param mode 温补模式 DAC/Band
*/
void configTemperatureCompensation(TemperatureComp mode);
/**
* @brief ADC校准
* @param adc ADC速率
*/
void configADCCalib(double adc);
/**
* @brief Flash校准
*/
void configFlashCalib();
/**
* @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复
* @return 包含寄存器地址和值的map
*/
std::map<int, int> beforeQecState();
/**
* @brief 恢复QEC校准过程中改变的寄存器
* @param state beforeQecState函数返回的map
*/
void restoreQecState(const std::map<int, int>& state);
/**
* @brief 根据pll来源配置校准模式下的电源管理
* @param pllSource PllSource结构体
*/
void preparePowerForRxCalib(const PllSource& pllSource);
/**
* @brief 调整校准时Pll的配置
* @param config CX9261A配置结构体
* @param chan 要进行校准的通道
*/
void preparePllForRxCalib(const CX9261AConfiguration& config, RxChannel chan);
/**
* @brief 等待RxTST窄带校准结束,可重写
* @return 校准是否结束
*/
bool waitRxTSTFinished();
/**
* @brief RX时域统计校准
* @param chan 校准的RX通道
*/
void rxTSTCalib(RxChannel chan);
/**
* @brief RX延时线校准
* @param fs ADC采样率
* @param chan 校准的RX通道
*/
void rxDelayCalib(double fs, RxChannel chan);
/**
* @brief DC Tracking
* @param config CX9261A配置结构体
*/
void configDcCalib(const Calib& config);
void configDcCalibMethod(DCCalibMethod method);
void configDcTrackingLength(int length);
void configDcHighPassFactor(int factor);
/**
* @brief Rx校准
* @param config CX9261A配置结构体
* @param chan 要进行校准的通道
*/
void rxCalib(const CX9261AConfiguration& config, RxChannel chan);
/**
* @brief 选择校准方法
* @param calib 校准结构体
*/
void configCalibMethod(const Calib& calib);
/**
* @brief 读取当前Rx chan通道的校准值
* @param chan Rx通道
* @return 校准值结构体
*/
CalibPredis readRxCalibPredis(RxChannel chan);
/**
* @brief 储存校准值
* @param index 第index组校准值
* @param chan 接收通道
* @param pll 使用的PLL
*/
void saveRxCalibPredis(unsigned char index, RxChannel chan, LoSource pll);
/**
* @brief 加载保存的校准值
* @param index 第index组校准值
* @param chan 指定加载校准值的通道
* @param pll 使用的PLL
*/
void loadRxCalibPredis(unsigned char index, RxChannel chan, LoSource pll);
/**
* @brief Rx窄带多点校准
* @param config CX9261A配置结构体
* @param points 校准点
* @param chan 接收通道
*/
void configRxMultiPointsQec(const CX9261AConfiguration& config, const std::vector<double>& points, RxChannel chan);
/**
* @brief 根据pll来源配置校准模式下的电源管理
* @param pllSource PllSource结构体
*/
void preparePowerForTxCalib(const PllSource& pllSource);
/**
* @brief 调整校准时Pll的配置
* @param config CX9261A配置结构体
*/
void preparePllForTxCalib(const CX9261AConfiguration& config);
/**
* @brief TX二分法QEC校准
* @param f0 校准音频率
* @param fs adc频率
*/
void txBisectionQecCalib(double f0, double fs);
/**
* @brief TX时域统计法校准
* @param config CX9261A配置结构体
* @param chan 要校准的通道
*/
void txTSTCalib(const CX9261AConfiguration& config, TxChannel chan);
/**
* @brief TX二分法DC校准
* @param f0 校准音频率
* @param fs adc频率
*/
void txBisectionDcCalib(double f0, double fs);
/**
* @brief Tx多点校准
* @param config CX9261A配置结构体
* @param points 校准点
*/
void configTxMultiPointsQec(const CX9261AConfiguration& config, const std::vector<double>& points);
/**
* @brief Tx通道校准
* @param config CX9261A配置结构体
*/
void txCalib(const CX9261AConfiguration& config);
/**
* @brief 储存校准值
* @param index 第index组校准值
* @param chan 发射通道
* @param pll pll
*/
void saveTxCalibPredis(unsigned char index, TxChannel chan, LoSource pll);
/**
* @brief 加载保存的校准值
* @param index 第index组校准值
* @param chan 指定加载校准值的通道
* @param pll 指定加载校准值对应的PLL
*/
void loadTxCalibPredis(unsigned char index, TxChannel chan, LoSource pll);
/**
* @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准
* @param config CX9261A配置结构体
*/
void configQecCalib(const CX9261AConfiguration& 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 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 配置Rx FIR滤波器系数
* @param coe 滤波器系数,长度为16的整倍数,最大128
*/
void configRxFIRCoe(const std::vector<double>& coe);
/**
* @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 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 配置Tx FIR滤波器系数
* @param coe 滤波器系数,长度为16的整倍数,最大128
*/
void configTxFIRCoe(const std::vector<double>& coe);
/**
* @brief 读取当前Tx chan通道的校准值
* @param chan Tx通道
* @return 校准值结构体
*/
CalibPredis readTxCalibPredis(TxChannel chan);
/**
* @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能
* @param interface Interface结构体
*/
void configFPGA(const Interface& interface);
} // namespace CX9261A
#endif // CX9261ADRIVER_CX9261ADRIVER_H
+425
View File
@@ -0,0 +1,425 @@
/**
* @file defs.h
*/
#ifndef CX9261ADRIVER_DEFS_H
#define CX9261ADRIVER_DEFS_H
#include <bitset>
#include <map>
#include <vector>
#include <cstdint>
#ifdef interface
# undef interface
#endif
namespace CX9261A {
/**
* @brief 芯片工作模式
*/
enum class WorkMode : std::uint8_t { Rx, Tx, FDD };
/**
* @brief 收发数据通道数量
* @note 此模式并不代表使用几个通道进行收发
*/
enum class TrMode : std::uint8_t { R1T1, R2T2 };
/**
* @brief 收发接口通道数量
*/
enum class PortMode : std::uint8_t { Single, Dual };
/**
* @brief 接口模式:
* CMOS CMOS接口模式,
* LVDS_S LVDS顺序模式,
* LVDS_E LVDS奇偶模式
*/
enum class IOMode : std::uint8_t { CMOS, LVDS_S, LVDS_E };
/**
* @brief 本振来源
*/
enum class LoSource : std::uint8_t {
Pll1 = 0b00001,
Pll2 = 0b00010,
Pll3 = 0b00100,
Pll4 = 0b01000,
Pll5 = 0b10000,
Off = 0
};
inline std::string toString(const LoSource source)
{
switch (source) {
case LoSource::Pll1:
return "Pll1";
case LoSource::Pll2:
return "Pll2";
case LoSource::Pll3:
return "Pll3";
case LoSource::Pll4:
return "Pll4";
case LoSource::Pll5:
return "Pll5";
default:
return "Off";
}
}
/**
* @brief 接收通道
*/
enum class RxChannel : std::uint8_t { Rx1 = 1, Rx2, Rx3 };
inline std::string toString(const RxChannel chan)
{
switch (chan) {
case RxChannel::Rx1:
return "Rx1";
case RxChannel::Rx2:
return "Rx2";
case RxChannel::Rx3:
return "Rx3";
default:
return "Unknown Channel";
}
}
/**
* @brief 发射通道
*/
enum class TxChannel : std::uint8_t { Tx1 = 1, Tx2 };
inline std::string toString(const TxChannel chan)
{
switch (chan) {
case TxChannel::Tx1:
return "Tx1";
case TxChannel::Tx2:
return "Tx2";
default:
return "Unknown Channel";
}
}
/**
* @brief 电源模式
*/
enum class PowerMode : std::uint8_t { Shutdown = 0, Sleep, Alert, Calib, Receive, Transmit, Duplex, Obs };
/**
* @brief NCO模式
*/
enum class NCOMode : std::uint8_t { Bypass = 0, Up, Down, BIST, Master, Slaver };
/**
* @brief 温补模式 DAC: DAC模式 Band: 跳子带模式
*/
enum class TemperatureComp : std::uint8_t { DAC = 0, Band };
/**
* @brief 校准方法 TST: 时域统计 Rx通道使用, Bisec: 二分法 Tx通道使用, MultiPoints: 多点校准
*/
enum class CalibMethod : std::uint8_t { TST = 0, Bisec, MultiPoints, Tracking };
/**
* @brief DC校准方法 Tracking: 跟踪校准 HighPass: 高通滤波器滤掉直流
*/
enum class DCCalibMethod : std::uint8_t { Tracking = 0, HighPass };
/**
* @brief AFC等待延时,单位ms
*/
constexpr double delay = 100;
/**
* @brief QEC等待延时,单位ms
*/
constexpr double qecDelay = 500;
/**
* @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 calibDC; /**< 是否开启DC Tracking*/
DCCalibMethod dcCalibMethod;
int dcTrackingLength; /**< DC Tracking长度*/
int dcHighPassFactor; /**< DC高通滤波系数,越大代表滤波器阶数越高,滤波范围越窄*/
std::uint8_t rx1CalibPll; /**< rx1校准的pll选择,Pll1 | Pll2*/
std::uint8_t rx2CalibPll; /**< rx2校准的pll选择,Pll1 | Pll2*/
std::uint8_t rx3CalibPll; /**< rx3校准的pll选择,Pll5*/
std::uint8_t tx1CalibPll; /**< tx1校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
std::uint8_t tx2CalibPll; /**< tx2校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
CalibMethod rxMethod;
CalibMethod txMethod;
double f0; /**< 校准音频率*/
std::vector<double> rxMultiPoints; /**< Rx多点校准的频率*/
std::vector<double> txMultiPoints; /**< Tx多点校准的频率*/
};
/**
* @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 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
{
TemperatureComp tempComp; /**< 温度补偿*/
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
+99
View File
@@ -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