Initial commit
This commit is contained in:
+24
@@ -0,0 +1,24 @@
|
||||
# Buid files
|
||||
build/
|
||||
*.tar.gz
|
||||
|
||||
# System generated files
|
||||
# -- macOS
|
||||
.DS_Store
|
||||
.AppleDouble
|
||||
.LSOverride
|
||||
._*
|
||||
|
||||
# -- Windows
|
||||
Thumbs.db
|
||||
ehthumbs.db
|
||||
Desktop.ini
|
||||
|
||||
# -- Linux
|
||||
*~
|
||||
|
||||
# IDEs and editors' files
|
||||
*.idea
|
||||
*.vscode
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
@@ -0,0 +1,76 @@
|
||||
# Variables
|
||||
PROJECT_NAME := cx9261a
|
||||
BUILD_DIR := build
|
||||
OUTPUT_DIR := output
|
||||
ARCHS := cortex-r5 cortex-a9 cortex-a53
|
||||
VERSIONS := debug release
|
||||
|
||||
# Compiler and options
|
||||
CC := arm-none-eabi-gcc
|
||||
CXX := arm-none-eabi-g++
|
||||
AR := arm-none-eabi-ar
|
||||
CXXFLAGS := -static -static-libstdc++ -std=c++17 -fPIC -Wl,--as-needed \
|
||||
-Wall -Wextra \
|
||||
-fmessage-length=0 -mfpu=vfpv3 -mfloat-abi=hard \
|
||||
-I. -I./cx9261A_api
|
||||
CFLAGS := -std=c17 -Wall -Wextra \
|
||||
-fmessage-length=0 -mfpu=vfpv3 -mfloat-abi=hard \
|
||||
-I.
|
||||
DEBUG_FLAGS := -g -O0 -DUSE_LOGGING
|
||||
RELEASE_FLAGS := -O3
|
||||
CXXFLAGS_DEBUG := $(CXXFLAGS) $(DEBUG_FLAGS)
|
||||
CXXFLAGS_RELEASE := $(CXXFLAGS) $(RELEASE_FLAGS)
|
||||
CFLAGS_DEBUG := $(CFLAGS) $(DEBUG_FLAGS)
|
||||
CFLAGS_RELEASE := $(CFLAGS) $(RELEASE_FLAGS)
|
||||
|
||||
# Collect source files
|
||||
SRCS := cx9261adriver_c.cpp cx9261A_api/cx9261adriver.cpp
|
||||
TEST_SRC := ld_test.c
|
||||
PACKAGE_HEADERS := ./cx9261adriver_c.h
|
||||
|
||||
# Default target
|
||||
all: $(foreach arch, $(ARCHS), $(BUILD_DIR)/$(arch)/lib$(PROJECT_NAME)_dbg.a $(BUILD_DIR)/$(arch)/lib$(PROJECT_NAME).a)
|
||||
|
||||
# Rule to create debug libraries for different architectures
|
||||
$(BUILD_DIR)/%/lib$(PROJECT_NAME)_dbg.a: $(SRCS)
|
||||
@mkdir -p $(BUILD_DIR)/$*/debug
|
||||
$(foreach src, $(SRCS), $(CXX) $(CXXFLAGS_DEBUG) -mcpu=$* -c $(src) -o $(BUILD_DIR)/$*/debug/$(notdir $(src:.cpp=_dbg.o));)
|
||||
$(AR) rcs $@ $(BUILD_DIR)/$*/debug/*_dbg.o
|
||||
|
||||
# Rule to create release libraries for different architectures
|
||||
$(BUILD_DIR)/%/lib$(PROJECT_NAME).a: $(SRCS)
|
||||
@mkdir -p $(BUILD_DIR)/$*/release
|
||||
$(foreach src, $(SRCS), $(CXX) $(CXXFLAGS_RELEASE) -mcpu=$* -c $(src) -o $(BUILD_DIR)/$*/release/$(notdir $(src:.cpp=.o));)
|
||||
$(AR) rcs $@ $(BUILD_DIR)/$*/release/*.o
|
||||
|
||||
# Clean up
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) *.tar.gz
|
||||
|
||||
# Run link tests
|
||||
test: all $(foreach arch, $(ARCHS), $(BUILD_DIR)/$(arch)/ld_test $(BUILD_DIR)/$(arch)/ld_test_dbg)
|
||||
@echo "Link test success!"
|
||||
|
||||
# Debug link tests
|
||||
$(BUILD_DIR)/%/ld_test_dbg: $(SRCS) $(TEST_SRC)
|
||||
@$(CC) $(CFLAGS_DEBUG) -mcpu=$* ld_test.c -o $@ -L$(BUILD_DIR)/$* -l$(PROJECT_NAME)_dbg -lstdc++ -lm -specs=nosys.specs
|
||||
|
||||
# Release link tests
|
||||
$(BUILD_DIR)/%/ld_test: $(SRCS) $(TEST_SRC)
|
||||
@$(CC) $(CFLAGS_RELEASE) -mcpu=$* ld_test.c -o $@ -L$(BUILD_DIR)/$* -l$(PROJECT_NAME) -lstdc++ -lm -specs=nosys.specs
|
||||
|
||||
# Package for release - bundle debug and release versions for each architecture separately
|
||||
package: all
|
||||
@echo "Packaging for release..."
|
||||
@$(foreach arch, $(ARCHS), \
|
||||
mkdir -p release_$(arch)/lib; \
|
||||
mkdir -p release_$(arch)/include; \
|
||||
cp $(BUILD_DIR)/$(arch)/lib$(PROJECT_NAME)_dbg.a release_$(arch)/lib/; \
|
||||
cp $(BUILD_DIR)/$(arch)/lib$(PROJECT_NAME).a release_$(arch)/lib/; \
|
||||
cp $(PACKAGE_HEADERS) release_$(arch)/include/; \
|
||||
tar -czvf release_$(arch).tar.gz -C release_$(arch) .; \
|
||||
rm -rf release_$(arch); \
|
||||
)
|
||||
@echo "Packaging completed."
|
||||
|
||||
.PHONY: all clean test release
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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
|
||||
@@ -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,549 @@
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include "defs.h"
|
||||
#include "cx9261adriver.h"
|
||||
#include "cx9261adriver_c.h"
|
||||
|
||||
using namespace CX9261A;
|
||||
|
||||
// Macro for convert enumerate
|
||||
#define DEFINE_ENUM_CONVERTER(enum_type) \
|
||||
static inline enum_type convertToCxx(CX9261A_##enum_type value) { \
|
||||
return static_cast<enum_type>(value); \
|
||||
}
|
||||
|
||||
// Macro for functions without parameters
|
||||
#define DEFINE_SIMPLE_C_WRAPPER(func_name, return_type) \
|
||||
return_type CX9261A_##func_name() { \
|
||||
return func_name(); \
|
||||
}
|
||||
|
||||
// Macro for functions with one passthrough parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PASS(func_name, param_type, return_type) \
|
||||
return_type CX9261A_##func_name(param_type param) { \
|
||||
return func_name(param); \
|
||||
}
|
||||
|
||||
// Macro for functions with two passthrough parameter
|
||||
#define DEFINE_C_WRAPPER_TWO_PASS(func_name, param0_type, param1_type, return_type) \
|
||||
return_type CX9261A_##func_name(param0_type param0, param1_type param1) { return func_name(param0, param1); }
|
||||
|
||||
// Macro for functions with one convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PTR_CONVERT(func_name, param_type, return_type) \
|
||||
return_type CX9261A_##func_name(const CX9261A_##param_type *param) { \
|
||||
return func_name(convertToCxx(*param)); \
|
||||
}
|
||||
|
||||
// Macro for functions with one convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_CONVERT(func_name, param_type, return_type) \
|
||||
return_type CX9261A_##func_name(const CX9261A_##param_type param) { \
|
||||
return func_name(convertToCxx(param)); \
|
||||
}
|
||||
|
||||
// Macro for functions with one convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(func_name, param0_type, param1_type, return_type) \
|
||||
return_type CX9261A_##func_name(const CX9261A_##param0_type *param0, const CX9261A_##param1_type param1) { \
|
||||
return func_name(convertToCxx(*param0), convertToCxx(param1)); \
|
||||
}
|
||||
|
||||
// Macro for functions with one pass one convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(func_name, param0_type, param1_type, return_type) \
|
||||
return_type CX9261A_##func_name(param0_type param0, const CX9261A_##param1_type param1) { \
|
||||
return func_name(param0, convertToCxx(param1)); \
|
||||
}
|
||||
|
||||
// Macro for functions with one pass one convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(func_name, param0_type, param1_type, return_type) \
|
||||
return_type CX9261A_##func_name(param0_type param0, const CX9261A_##param1_type *param1) { \
|
||||
return func_name(param0, convertToCxx(*param1)); \
|
||||
}
|
||||
|
||||
// Macro for functions with one convert one pass parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_PASS(func_name, param0_type, param1_type, return_type) \
|
||||
return_type CX9261A_##func_name(const CX9261A_##param0_type *param0, param1_type param1) { \
|
||||
return func_name(convertToCxx(*param0), param1); \
|
||||
}
|
||||
|
||||
// Macro for functions with one pass two convert parameter
|
||||
#define DEFINE_C_WRAPPER_ONE_PASS_TWO_CONVERT(func_name, param0_type, param1_type, param2_type, return_type) \
|
||||
return_type CX9261A_##func_name(param0_type param0, const CX9261A_##param1_type param1, const CX9261A_##param2_type param2) { \
|
||||
return func_name(param0, convertToCxx(param1), convertToCxx(param2)); \
|
||||
}
|
||||
|
||||
|
||||
DEFINE_ENUM_CONVERTER(WorkMode)
|
||||
DEFINE_ENUM_CONVERTER(TrMode)
|
||||
DEFINE_ENUM_CONVERTER(PortMode)
|
||||
DEFINE_ENUM_CONVERTER(IOMode)
|
||||
DEFINE_ENUM_CONVERTER(LoSource)
|
||||
DEFINE_ENUM_CONVERTER(RxChannel)
|
||||
DEFINE_ENUM_CONVERTER(TxChannel)
|
||||
DEFINE_ENUM_CONVERTER(PowerMode)
|
||||
DEFINE_ENUM_CONVERTER(NCOMode)
|
||||
DEFINE_ENUM_CONVERTER(TemperatureComp)
|
||||
DEFINE_ENUM_CONVERTER(CalibMethod)
|
||||
DEFINE_ENUM_CONVERTER(DCCalibMethod)
|
||||
|
||||
// Convert AGCPDT from C to C++
|
||||
static inline AGCPDT convertToCxx(const CX9261A_AGCPDT& pdt) {
|
||||
AGCPDT result;
|
||||
result.pdtN = pdt.pdtN;
|
||||
result.pdtM = pdt.pdtM;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert AGCLMT from C to C++
|
||||
static inline AGCLMT convertToCxx(const CX9261A_AGCLMT& lmt) {
|
||||
AGCLMT result;
|
||||
result.count = lmt.count;
|
||||
result.threshold1 = lmt.threshold1;
|
||||
result.threshold2 = lmt.threshold2;
|
||||
result.threshold3 = lmt.threshold3;
|
||||
result.threshold4 = lmt.threshold4;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert AGCDIG from C to C++
|
||||
static inline AGCDIG convertToCxx(const CX9261A_AGCDIG& dig) {
|
||||
AGCDIG result;
|
||||
result.count = dig.count;
|
||||
result.threshold1 = dig.threshold1;
|
||||
result.threshold2 = dig.threshold2;
|
||||
result.threshold3 = dig.threshold3;
|
||||
result.threshold4 = dig.threshold4;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert AGC from C to C++
|
||||
static AGC convertToCxx(const CX9261A_AGC& agc) {
|
||||
AGC result;
|
||||
result.mode = agc.mode;
|
||||
result.pdt = convertToCxx(agc.pdt);
|
||||
result.lmt = convertToCxx(agc.lmt);
|
||||
result.dig = convertToCxx(agc.dig);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert Clock from C to C++
|
||||
static Clock convertToCxx(const CX9261A_Clock& clock) {
|
||||
Clock result;
|
||||
result.ref = clock.ref;
|
||||
result.adc = clock.adc;
|
||||
result.refDiv = clock.refDiv;
|
||||
result.bbUseIntDiv = clock.bbUseIntDiv;
|
||||
result.refDoubler = clock.refDoubler;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert Calib from C to C++
|
||||
static Calib convertToCxx(const CX9261A_Calib& c) {
|
||||
Calib result;
|
||||
result.calibDC = c.calibDC;
|
||||
result.dcTrackingLength = c.dcTrackingLength;
|
||||
result.dcHighPassFactor = c.dcHighPassFactor;
|
||||
result.rx1CalibPll = c.rx1CalibPll;
|
||||
result.rx2CalibPll = c.rx2CalibPll;
|
||||
result.rx3CalibPll = c.rx3CalibPll;
|
||||
result.tx1CalibPll = c.tx1CalibPll;
|
||||
result.tx2CalibPll = c.tx2CalibPll;
|
||||
result.f0 = c.f0;
|
||||
result.dcCalibMethod = convertToCxx(c.dcCalibMethod);
|
||||
result.rxMethod = convertToCxx(c.rxMethod);
|
||||
result.txMethod = convertToCxx(c.txMethod);
|
||||
if(MAX_MULTI_POINTS < c.numRxPoint) {
|
||||
LOGGING("Rx多点校准的频率校准数量超出限制 MAX_MULTI_POINTS");
|
||||
exit(-1);
|
||||
}
|
||||
if(MAX_MULTI_POINTS < c.numTxPoint) {
|
||||
LOGGING("Tx多点校准的频率校准数量超出限制 MAX_MULTI_POINTS");
|
||||
exit(-1);
|
||||
}
|
||||
result.rxMultiPoints.resize(c.numRxPoint);
|
||||
result.txMultiPoints.resize(c.numTxPoint);
|
||||
std::memcpy(result.rxMultiPoints.data(), c.rxMultiPoints, c.numRxPoint * sizeof(double));
|
||||
std::memcpy(result.txMultiPoints.data(), c.txMultiPoints, c.numTxPoint * sizeof(double));
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert PllSource from C to C++
|
||||
static PllSource convertToCxx(const CX9261A_PllSource& src) {
|
||||
PllSource result;
|
||||
result.rxUseExt = src.rxUseExt;
|
||||
result.txUseExt = src.txUseExt;
|
||||
result.rx1Source = convertToCxx(src.rx1Source);
|
||||
result.rx2Source = convertToCxx(src.rx2Source);
|
||||
result.rx3Source = convertToCxx(src.rx3Source);
|
||||
result.tx1Source = convertToCxx(src.tx1Source);
|
||||
result.tx2Source = convertToCxx(src.tx2Source);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert PllFreq from C to C++
|
||||
static PllFreq convertToCxx(const CX9261A_PllFreq& freq) {
|
||||
PllFreq result;
|
||||
result.pll1Freq = freq.pll1Freq;
|
||||
result.pll2Freq = freq.pll2Freq;
|
||||
result.pll3Freq = freq.pll3Freq;
|
||||
result.pll4Freq = freq.pll4Freq;
|
||||
result.pll5Freq = freq.pll5Freq;
|
||||
result.rxExtFreq = freq.rxExtFreq;
|
||||
result.txExtFreq = freq.txExtFreq;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert Interface from C to C++
|
||||
static Interface convertToCxx(const CX9261A_Interface& iface) {
|
||||
Interface result;
|
||||
result.workMode = convertToCxx(iface.workMode);
|
||||
result.trMode = convertToCxx(iface.trMode);
|
||||
result.portMode = convertToCxx(iface.portMode);
|
||||
result.ioMode = convertToCxx(iface.ioMode);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert TxNCO from C to C++
|
||||
static TxNCO convertToCxx(const CX9261A_TxNCO& nco) {
|
||||
TxNCO result;
|
||||
result.txUseBist = nco.txUseBist;
|
||||
result.txNCOFreq = nco.txNCOFreq;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert RxNCO from C to C++
|
||||
static RxNCO convertToCxx(const CX9261A_RxNCO& nco) {
|
||||
RxNCO result;
|
||||
result.rxUseBist = nco.rxUseBist;
|
||||
result.rxNCOBypass = nco.rxNCOBypass;
|
||||
result.rxNCOUpward = nco.rxNCOUpward;
|
||||
result.rxNCOMaster = nco.rxNCOMaster;
|
||||
result.rxNCOFreq = nco.rxNCOFreq;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert RxConfig from C to C++
|
||||
static RxConfig convertToCxx(const CX9261A_RxConfig& config) {
|
||||
RxConfig result;
|
||||
result.bandwidth = config.bandwidth;
|
||||
result.tia = config.tia;
|
||||
result.mixer = config.mixer;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert TxConfig from C to C++
|
||||
static TxConfig convertToCxx(const CX9261A_TxConfig& config) {
|
||||
TxConfig result;
|
||||
result.bandwidth = config.bandwidth;
|
||||
result.mixer = config.mixer;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert Filters from C to C++
|
||||
static Filters convertToCxx(const CX9261A_Filters& filters) {
|
||||
Filters result;
|
||||
result.fir = filters.fir;
|
||||
result.hbf1 = filters.hbf1;
|
||||
result.hbf2 = filters.hbf2;
|
||||
result.hbf3 = filters.hbf3;
|
||||
result.cic = filters.cic;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Convert Power from C to C++
|
||||
static Power convertToCxx(const CX9261A_Power& power) {
|
||||
Power result;
|
||||
result.dig_tx2 = power.dig_tx2;
|
||||
result.dig_tx1 = power.dig_tx1;
|
||||
result.dig_rx3 = power.dig_rx3;
|
||||
result.dig_rx2 = power.dig_rx2;
|
||||
result.dig_rx1 = power.dig_rx1;
|
||||
result.fref1_rx = power.fref1_rx;
|
||||
result.auxadc2 = power.auxadc2;
|
||||
result.auxadc1 = power.auxadc1;
|
||||
result.auxdac = power.auxdac;
|
||||
result.temp_sensor = power.temp_sensor;
|
||||
result.bgr = power.bgr;
|
||||
result.exlo = power.exlo;
|
||||
result.tx2 = power.tx2;
|
||||
result.tx1 = power.tx1;
|
||||
result.rx3 = power.rx3;
|
||||
result.rx2 = power.rx2;
|
||||
result.rx1 = power.rx1;
|
||||
result.pll5_ldo = power.pll5_ldo;
|
||||
result.pll5 = power.pll5;
|
||||
result.pll4_ldo = power.pll4_ldo;
|
||||
result.pll4 = power.pll4;
|
||||
result.pll3_ldo = power.pll3_ldo;
|
||||
result.pll3 = power.pll3;
|
||||
result.pll2_ldo = power.pll2_ldo;
|
||||
result.pll2 = power.pll2;
|
||||
result.pll1_ldo = power.pll1_ldo;
|
||||
result.pll1 = power.pll1;
|
||||
result.bbpll = power.bbpll;
|
||||
return result;
|
||||
}
|
||||
|
||||
static PowerManagement convertToCxx(const CX9261A_PowerManagement& pwMgmt) {
|
||||
PowerManagement result;
|
||||
result.powerMode = convertToCxx(pwMgmt.powerMode);
|
||||
result.rxPower = convertToCxx(pwMgmt.rxPower);
|
||||
result.txPower = convertToCxx(pwMgmt.txPower);
|
||||
result.fddPower = convertToCxx(pwMgmt.fddPower);
|
||||
return result;
|
||||
}
|
||||
|
||||
static CX9261A_CalibPredis convertToC(const CalibPredis& cp) {
|
||||
CX9261A_CalibPredis result;
|
||||
result.bHigh = cp.bHigh;
|
||||
result.bLow = cp.bLow;
|
||||
result.cHigh = cp.cHigh;
|
||||
result.cLow = cp.cLow;
|
||||
result.dciHigh = cp.dciHigh;
|
||||
result.dciLow = cp.dciLow;
|
||||
result.dcqHigh = cp.dcqHigh;
|
||||
result.dcqLow = cp.dcqLow;
|
||||
return result;
|
||||
}
|
||||
|
||||
static CX9261AConfiguration convertToCxx(const CX9261A_CX9261AConfiguration& config) {
|
||||
CX9261AConfiguration result;
|
||||
result.tempComp = convertToCxx(config.tempComp);
|
||||
result.agc = convertToCxx(config.agc);
|
||||
result.interface = convertToCxx(config.interface);
|
||||
result.clock = convertToCxx(config.clock);
|
||||
result.pllSource = convertToCxx(config.pllSource);
|
||||
result.calib = convertToCxx(config.calib);
|
||||
result.pllFreq = convertToCxx(config.pllFreq);
|
||||
result.txNco = convertToCxx(config.txNco);
|
||||
result.rxNco = convertToCxx(config.rxNco);
|
||||
result.rx1Config = convertToCxx(config.rx1Config);
|
||||
result.rx2Config = convertToCxx(config.rx2Config);
|
||||
result.rx3Config = convertToCxx(config.rx3Config);
|
||||
result.tx1Config = convertToCxx(config.tx1Config);
|
||||
result.tx2Config = convertToCxx(config.tx2Config);
|
||||
result.rxFilters = convertToCxx(config.rxFilters);
|
||||
result.txFilters = convertToCxx(config.txFilters);
|
||||
result.powerManagement = convertToCxx(config.powerManagement);
|
||||
if(MAX_NUM_FIR < config.numRxFIR) {
|
||||
LOGGING("Rx FIR滤波器系数阶数超出限制 MAX_MULTI_POINTS");
|
||||
exit(-1);
|
||||
}
|
||||
if(MAX_NUM_FIR < config.numTxFIR) {
|
||||
LOGGING("Rx FIR滤波器系数阶数超出限制 MAX_MULTI_POINTS");
|
||||
exit(-1);
|
||||
}
|
||||
result.rxFIRCoe.resize(config.numRxFIR);
|
||||
result.txFIRCoe.resize(config.numTxFIR);
|
||||
std::memcpy(result.rxFIRCoe.data(), config.rxFIRCoe, config.numRxFIR);
|
||||
std::memcpy(result.txFIRCoe.data(), config.txFIRCoe, config.numTxFIR);
|
||||
return result;
|
||||
}
|
||||
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialChip, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialBBPLL, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialPLL1, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialPLL2, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialPLL3, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialPLL4, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(initialPLL5, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(configFlashCalib, void)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcBBPll, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcPll1, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcPll2, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcPll3, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcPll4, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(afcPll5, bool)
|
||||
DEFINE_SIMPLE_C_WRAPPER(waitRxTSTFinished, bool)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configAGCMode, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRISCV, bool, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configADCCalib, double, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configDcTrackingLength, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configDcHighPassFactor, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxFIR, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxHBF1, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxHBF2, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxHBF3, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxCIC, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configTxBIST, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxFIR, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxHBF1, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxHBF2, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxHBF3, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxCIC, int, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS(configRxMixer, int, void)
|
||||
|
||||
DEFINE_C_WRAPPER_TWO_PASS(txBisectionQecCalib, double, double, void);
|
||||
DEFINE_C_WRAPPER_TWO_PASS(txBisectionDcCalib, double, double, void)
|
||||
DEFINE_C_WRAPPER_TWO_PASS(configTxNcoFreq, double, double, void);
|
||||
DEFINE_C_WRAPPER_TWO_PASS(configRxNcoFreq, double, double, void);
|
||||
DEFINE_C_WRAPPER_TWO_PASS(configRefDoubler, double, double, void);
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(initialPowerConfig, CX9261AConfiguration, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configBBPLL, CX9261AConfiguration, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configAGCPDT, AGCPDT, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configAGCLMT, AGCLMT, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configAGCDIG, AGCDIG, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configAGC, AGC, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(preparePowerForRxCalib, PllSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configDcCalib, Calib, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configCalibMethod, Calib, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(preparePowerForTxCalib, PllSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(preparePllForTxCalib, CX9261AConfiguration, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(txCalib, CX9261AConfiguration, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configQecCalib, CX9261AConfiguration, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configInterface, Interface, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configPllSource, PllSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configTxFilters, Filters, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configRxFilters, Filters, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT(configFPGA, Interface, void)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(configTemperatureCompensation, TemperatureComp, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(rxTSTCalib, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(configRxNcoMode, NCOMode, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(configRxNcoMS, NCOMode, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(configPowerMode, PowerMode, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(initialRxChannel, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_CONVERT(initialTxChannel, TxChannel, void)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(preparePllForRxCalib, CX9261AConfiguration, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(txTSTCalib, CX9261AConfiguration, TxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(rxCalib, CX9261AConfiguration, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(configPowerPins, Power, PowerMode, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(configRxChannel, RxConfig, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_CONVERT(configTxChannel, TxConfig, TxChannel, void)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_PASS(configTxNco, TxNCO, double, void);
|
||||
DEFINE_C_WRAPPER_ONE_PTR_CONVERT_ONE_PASS(configRxNco, RxNCO, double, void);
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(configPll1, double, Clock, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(configPll2, double, Clock, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(configPll3, double, Clock, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(configPll4, double, Clock, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_PTR_CONVERT(configPll5, double, Clock, void)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(rxDelayCalib, double, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(configRxBandwidth, double, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(configRxTIA, int, RxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(configTxBandwidth, int, TxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(configTxMixer, int, TxChannel, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_ONE_CONVERT(configTxChannelFrequency, double, TxChannel, void)
|
||||
|
||||
DEFINE_C_WRAPPER_ONE_PASS_TWO_CONVERT(saveRxCalibPredis, unsigned char, RxChannel, LoSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_TWO_CONVERT(loadRxCalibPredis, unsigned char, RxChannel, LoSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_TWO_CONVERT(saveTxCalibPredis, unsigned char, TxChannel, LoSource, void)
|
||||
DEFINE_C_WRAPPER_ONE_PASS_TWO_CONVERT(loadTxCalibPredis, unsigned char, TxChannel, LoSource, void)
|
||||
|
||||
|
||||
void CX9261A_beforeQecState(QecStatePair* buff, size_t *len) {
|
||||
std::map<int, int> state = beforeQecState();
|
||||
*len = 0;
|
||||
for (const auto&[first, second]: state) {
|
||||
buff[*len].first = first;
|
||||
buff[*len].second = second;
|
||||
(*len)++;
|
||||
}
|
||||
}
|
||||
|
||||
void CX9261A_restoreQecState(QecStatePair* buff, size_t len) {
|
||||
std::map<int, int> state;
|
||||
for (std::size_t i = 0; i < len; ++i) {
|
||||
state[buff[i].first] = buff[i].second;
|
||||
}
|
||||
restoreQecState(state);
|
||||
}
|
||||
|
||||
|
||||
void CX9261A_configRxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan, const double *points, size_t len) {
|
||||
std::vector<double> points_vec(points, points+len);
|
||||
configRxMultiPointsQec(convertToCxx(*config), points_vec, convertToCxx(chan));
|
||||
}
|
||||
|
||||
void CX9261A_configTxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, const double *points, size_t len) {
|
||||
std::vector<double> points_vec(points, points+len);
|
||||
configTxMultiPointsQec(convertToCxx(*config), points_vec);
|
||||
}
|
||||
|
||||
void CX9261A_configRxFIRCoe(const double *coe, size_t len) {
|
||||
std::vector<double> coe_vec(coe, coe+len);
|
||||
configRxFIRCoe(coe_vec);
|
||||
}
|
||||
|
||||
void CX9261A_configTxFIRCoe(const double *coe, size_t len) {
|
||||
std::vector<double> coe_vec(coe, coe+len);
|
||||
configTxFIRCoe(coe_vec);
|
||||
}
|
||||
|
||||
CX9261A_CalibPredis CX9261A_readRxCalibPredis(CX9261A_RxChannel chan) {
|
||||
return convertToC(readRxCalibPredis(convertToCxx(chan)));
|
||||
}
|
||||
|
||||
CX9261A_CalibPredis CX9261A_readTxCalibPredis(CX9261A_TxChannel chan) {
|
||||
return convertToC(readTxCalibPredis(convertToCxx(chan)));
|
||||
}
|
||||
|
||||
|
||||
static CX9261A_LoggingFunc loggingFunc = NULL;
|
||||
static CX9261A_WriteSpiFunc writeSpiFunc = NULL;
|
||||
static CX9261A_ReadSpiFunc readSpiFunc = NULL;
|
||||
static CX9261A_PauseFunc pauseFunc = NULL;
|
||||
static CX9261A_SetPinFunc setPinFunc = NULL;
|
||||
|
||||
// 设置函数指针
|
||||
void CX9261A_setLoggingFunc(CX9261A_LoggingFunc func) {
|
||||
loggingFunc = func;
|
||||
}
|
||||
|
||||
void CX9261A_setWriteSpiFunc(CX9261A_WriteSpiFunc func) {
|
||||
writeSpiFunc = func;
|
||||
}
|
||||
|
||||
void CX9261A_setReadSpiFunc(CX9261A_ReadSpiFunc func) {
|
||||
readSpiFunc = func;
|
||||
}
|
||||
|
||||
void CX9261A_setPauseFunc(CX9261A_PauseFunc func) {
|
||||
pauseFunc = func;
|
||||
}
|
||||
|
||||
void CX9261A_setSetPinFunc(CX9261A_SetPinFunc func) {
|
||||
setPinFunc = func;
|
||||
}
|
||||
|
||||
#ifdef USE_LOGGING
|
||||
void CX9261A::logging(const std::string& msg) {
|
||||
if(loggingFunc != NULL) {
|
||||
loggingFunc(msg.c_str());
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void CX9261A::writeSpi(int address, int value) {
|
||||
if(writeSpiFunc != NULL) {
|
||||
writeSpiFunc(address, value);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int CX9261A::readSpi(int address) {
|
||||
if(readSpiFunc != NULL) {
|
||||
return readSpiFunc(address);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void CX9261A::pause(double ms) {
|
||||
if(pauseFunc != NULL) {
|
||||
return pauseFunc(ms);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
void CX9261A::setPin(int pin, int value) {
|
||||
if(setPinFunc != NULL) {
|
||||
return setPinFunc(pin, value);
|
||||
}
|
||||
exit(-1);
|
||||
}
|
||||
@@ -0,0 +1,982 @@
|
||||
#ifndef __CX9261ADRIVER_C_H
|
||||
#define __CX9261ADRIVER_C_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
#define MAX_NUM_FIR 64
|
||||
#define MAX_MULTI_POINTS 64
|
||||
|
||||
typedef enum {
|
||||
CX9261A_WKM_Rx,
|
||||
CX9261A_WKM_Tx,
|
||||
CX9261A_WKM_FDD
|
||||
} CX9261A_WorkMode;
|
||||
|
||||
/**
|
||||
* @brief 收发数据通道数量
|
||||
* @note 此模式并不代表使用几个通道进行收发
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TRM_R1T1,
|
||||
CX9261A_TRM_R2T2
|
||||
} CX9261A_TrMode;
|
||||
|
||||
/**
|
||||
* @brief 收发接口通道数量
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_PORTM_Single,
|
||||
CX9261A_PORTM_Dual
|
||||
} CX9261A_PortMode;
|
||||
|
||||
/**
|
||||
* @brief 接口模式:
|
||||
* CMOS CMOS接口模式,
|
||||
* LVDS_S LVDS顺序模式,
|
||||
* LVDS_E LVDS奇偶模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_IOM_CMOS,
|
||||
CX9261A_IOM_LVDS_S,
|
||||
CX9261A_IOM_LVDS_E
|
||||
} CX9261A_IOMode;
|
||||
|
||||
/**
|
||||
* @brief 本振来源
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_LOSRC_Pll1 = 0b00001,
|
||||
CX9261A_LOSRC_Pll2 = 0b00010,
|
||||
CX9261A_LOSRC_Pll3 = 0b00100,
|
||||
CX9261A_LOSRC_Pll4 = 0b01000,
|
||||
CX9261A_LOSRC_Pll5 = 0b10000,
|
||||
CX9261A_LOSRC_Off = 0
|
||||
} CX9261A_LoSource;
|
||||
|
||||
/**
|
||||
* @brief 接收通道
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_RXCH_Rx1 = 1,
|
||||
CX9261A_RXCH_Rx2,
|
||||
CX9261A_RXCH_Rx3
|
||||
} CX9261A_RxChannel;
|
||||
|
||||
/**
|
||||
* @brief 发射通道
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TXCH_Tx1 = 1,
|
||||
CX9261A_TXCH_Tx2
|
||||
} CX9261A_TxChannel;
|
||||
|
||||
/**
|
||||
* @brief 电源模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_PWM_Shutdown = 0,
|
||||
CX9261A_PWM_Sleep,
|
||||
CX9261A_PWM_Alert,
|
||||
CX9261A_PWM_Calib,
|
||||
CX9261A_PWM_Receive,
|
||||
CX9261A_PWM_Transmit,
|
||||
CX9261A_PWM_Duplex,
|
||||
CX9261A_PWM_Obs
|
||||
} CX9261A_PowerMode;
|
||||
|
||||
/**
|
||||
* @brief NCO模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_NCOM_Bypass = 0,
|
||||
CX9261A_NCOM_Up,
|
||||
CX9261A_NCOM_Down,
|
||||
CX9261A_NCOM_BIST,
|
||||
CX9261A_NCOM_Master,
|
||||
CX9261A_NCOM_Slaver
|
||||
} CX9261A_NCOMode;
|
||||
|
||||
/**
|
||||
* @brief 温补模式 DAC: DAC模式 Band: 跳子带模式
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_TEMPCP_DAC = 0,
|
||||
CX9261A_TEMPCP_Band
|
||||
} CX9261A_TemperatureComp;
|
||||
|
||||
/**
|
||||
* @brief 校准方法 TST: 时域统计 Rx通道使用, Bisec: 二分法 Tx通道使用, MultiPoints: 多点校准
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_CALM_TST = 0,
|
||||
CX9261A_CALM_Bisec,
|
||||
CX9261A_CALM_MultiPoints,
|
||||
CX9261A_CALM_Tracking
|
||||
} CX9261A_CalibMethod;
|
||||
|
||||
/**
|
||||
* @brief DC校准方法 Tracking: 跟踪校准 HighPass: 高通滤波器滤掉直流
|
||||
*/
|
||||
typedef enum {
|
||||
CX9261A_DCCALM_Tracking=0,
|
||||
CX9261A_DCCALM_HighPass
|
||||
} CX9261A_DCCalibMethod;
|
||||
|
||||
|
||||
typedef struct {
|
||||
CX9261A_LoSource first;
|
||||
CX9261A_LoSource second;
|
||||
} CX9261A_LoSourcePair;
|
||||
|
||||
typedef struct {
|
||||
CX9261A_LoSourcePair key;
|
||||
uint16_t value;
|
||||
} CX9261A_SrcMapEntry;
|
||||
|
||||
/**
|
||||
* @brief 接收通道本振来源映射表
|
||||
*/
|
||||
static const CX9261A_SrcMapEntry CX9261A_rxSrcMap[] = {
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 0b0010000 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 0b1101000 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 0b0100000 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 0b1000000 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 0b0101010 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 0b1010010 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 0b1001001 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 0b0110001 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 0b0011011 }
|
||||
};
|
||||
/**
|
||||
* @brief 发射通道本振来源映射表
|
||||
*/
|
||||
static const CX9261A_SrcMapEntry CX9261A_txSrcMap[] = {
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll4 }, 16 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll3 }, 104 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll3 }, 32 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll4 }, 64 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll2 }, 1560 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll1 }, 1944 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll1 }, 1688 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll2 }, 1816 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll3 }, 42 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll4 }, 82 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll2 }, 794 }, { { CX9261A_LOSRC_Off, CX9261A_LOSRC_Pll1 }, 666 },
|
||||
{ { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Off }, 73 }, { { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Off }, 49 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Off }, 1177 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Off }, 1305 },
|
||||
{ { CX9261A_LOSRC_Off, CX9261A_LOSRC_Off }, 27 }, { { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll3 }, 1320 },
|
||||
{ { CX9261A_LOSRC_Pll1, CX9261A_LOSRC_Pll4 }, 1360 }, { { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll3 }, 1064 },
|
||||
{ { CX9261A_LOSRC_Pll2, CX9261A_LOSRC_Pll4 }, 1104 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll1 }, 712 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll1 }, 688 }, { { CX9261A_LOSRC_Pll3, CX9261A_LOSRC_Pll2 }, 584 },
|
||||
{ { CX9261A_LOSRC_Pll4, CX9261A_LOSRC_Pll2 }, 560 }
|
||||
};
|
||||
/**
|
||||
* @brief 环路参数选择表
|
||||
*/
|
||||
static const uint8_t CX9261A_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 } }
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @brief AGC PDT模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int pdtN;
|
||||
int pdtM;
|
||||
} CX9261A_AGCPDT;
|
||||
|
||||
/**
|
||||
* @brief AGC LMT模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int count; /**< LMT统计次数阈值*/
|
||||
int threshold1; /**< LMT阈值第一档*/
|
||||
int threshold2; /**< LMT阈值第二档*/
|
||||
int threshold3; /**< LMT阈值第三档*/
|
||||
int threshold4; /**< LMT阈值第四档*/
|
||||
} CX9261A_AGCLMT;
|
||||
|
||||
/**
|
||||
* @brief AGC DIG模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int count; /**< DIG统计次数阈值*/
|
||||
int threshold1; /**< DIG阈值第一档*/
|
||||
int threshold2; /**< DIG阈值第二档*/
|
||||
int threshold3; /**< DIG阈值第三档*/
|
||||
int threshold4; /**< DIG阈值第四档*/
|
||||
} CX9261A_AGCDIG;
|
||||
|
||||
/**
|
||||
* @brief AGC模式的结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int mode; /**< AGC模式选择*/
|
||||
CX9261A_AGCPDT pdt; /**< AGC PDT模式的结构体*/
|
||||
CX9261A_AGCLMT lmt; /**< AGC LMT模式的结构体*/
|
||||
CX9261A_AGCDIG dig; /**< AGC DIG模式的结构体*/
|
||||
} CX9261A_AGC;
|
||||
|
||||
/**
|
||||
* @brief 时钟相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
double ref; /**< 参考时钟频率,单位MHz*/
|
||||
double adc; /**< ADC频率,单位MHz*/
|
||||
int refDiv; /**< 参考时钟分频比*/
|
||||
bool bbUseIntDiv; /**< 是否使用整数分频模式*/
|
||||
bool refDoubler; /**< 是否使用参考时钟倍频器*/
|
||||
} CX9261A_Clock;
|
||||
|
||||
/**
|
||||
* @brief 校准相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool calibDC; /**< 是否开启DC Tracking*/
|
||||
CX9261A_DCCalibMethod dcCalibMethod;
|
||||
int dcTrackingLength; /**< DC Tracking长度*/
|
||||
int dcHighPassFactor; /**< DC高通滤波系数,越大代表滤波器阶数越高,滤波范围越窄*/
|
||||
uint8_t rx1CalibPll; /**< rx1校准的pll选择,Pll1 | Pll2*/
|
||||
uint8_t rx2CalibPll; /**< rx2校准的pll选择,Pll1 | Pll2*/
|
||||
uint8_t rx3CalibPll; /**< rx3校准的pll选择,Pll5*/
|
||||
uint8_t tx1CalibPll; /**< tx1校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
|
||||
uint8_t tx2CalibPll; /**< tx2校准的pll选择,Pll1 | Pll2 | Pll3 | Pll4*/
|
||||
CX9261A_CalibMethod rxMethod;
|
||||
CX9261A_CalibMethod txMethod;
|
||||
double f0; /**< 校准音频率*/
|
||||
uint32_t numRxPoint; /**< Rx多点校准的频率个数*/
|
||||
uint32_t numTxPoint; /**< Tx多点校准的频率个数*/
|
||||
double rxMultiPoints[MAX_MULTI_POINTS]; /**< Rx多点校准的频率*/
|
||||
double txMultiPoints[MAX_MULTI_POINTS]; /**< Tx多点校准的频率*/
|
||||
} CX9261A_Calib;
|
||||
|
||||
/**
|
||||
* @brief 配置PLL来源相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool rxUseExt; /**< 接收通道是否使用外本振*/
|
||||
bool txUseExt; /**< 发射通道是否使用外本振*/
|
||||
CX9261A_LoSource rx1Source; /**< Rx1通道本振来源*/
|
||||
CX9261A_LoSource rx2Source; /**< Rx2通道本振来源*/
|
||||
CX9261A_LoSource rx3Source; /**< Rx3通道本振来源*/
|
||||
CX9261A_LoSource tx1Source; /**< Tx1通道本振来源*/
|
||||
CX9261A_LoSource tx2Source; /**< Tx2通道本振来源*/
|
||||
} CX9261A_PllSource;
|
||||
|
||||
/**
|
||||
* @brief 配置PLL频率相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
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*/
|
||||
} CX9261A_PllFreq;
|
||||
|
||||
/**
|
||||
* @brief 配置接口相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
CX9261A_WorkMode workMode; /**< 芯片工作模式*/
|
||||
CX9261A_TrMode trMode; /**< 收发数据通道模式*/
|
||||
CX9261A_PortMode portMode; /**< 收发接口通道模式*/
|
||||
CX9261A_IOMode ioMode; /**< 接口电平模式*/
|
||||
} CX9261A_Interface;
|
||||
|
||||
/**
|
||||
* @brief 配置TX NCO相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool txUseBist; /**< 是否开启BIST模式*/
|
||||
double txNCOFreq; /**< NCO频率*/
|
||||
} CX9261A_TxNCO;
|
||||
|
||||
/**
|
||||
* @brief 配置RX NCO相关参数结构体
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool rxUseBist; /**< 是否开启BIST模式*/
|
||||
bool rxNCOBypass; /**< 是否Bypass NCO*/
|
||||
bool rxNCOUpward; /**< 开启上/下混频模式*/
|
||||
bool rxNCOMaster; /**< 使用Master/Slaver模式*/
|
||||
double rxNCOFreq; /**< NCO频率*/
|
||||
} CX9261A_RxNCO;
|
||||
|
||||
/**
|
||||
* @brief 配置接收通道相关参数结构体
|
||||
*/
|
||||
typedef struct {
|
||||
double bandwidth; /**< 接收通道1dB带宽,单位MHz*/
|
||||
int tia; /**< 接收通道TIA增益配置,推荐配置6*/
|
||||
int mixer; /**< 接收通道Mixer增益配置*/
|
||||
} CX9261A_RxConfig;
|
||||
|
||||
/**
|
||||
* @brief 配置发射通道相关参数结构体
|
||||
*/
|
||||
typedef struct {
|
||||
double bandwidth; /**< 发射通道1dB带宽,单位MHz*/
|
||||
int mixer; /**< 发射通道Mixer增益配置*/
|
||||
} CX9261A_TxConfig;
|
||||
|
||||
/**
|
||||
* @brief 配置滤波器相关参数结构体,0代表bypass
|
||||
*/
|
||||
typedef struct {
|
||||
int fir; /**< FIR滤波器抽取/插值倍数*/
|
||||
int hbf1; /**< HBF1滤波器抽取/插值倍数*/
|
||||
int hbf2; /**< HBF2滤波器抽取/插值倍数*/
|
||||
int hbf3; /**< HBF3滤波器抽取/插值倍数*/
|
||||
int cic; /**< CIC滤波器抽取/插值倍数*/
|
||||
} CX9261A_Filters;
|
||||
|
||||
/**
|
||||
* @brief 配置电源模式结构体,1代表该模块上电
|
||||
*/
|
||||
typedef struct {
|
||||
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;
|
||||
} CX9261A_Power;
|
||||
|
||||
/**
|
||||
* @brief 配置电源模式管理,包含模式选择,接收模式,发射模式,FDD模式
|
||||
*/
|
||||
typedef struct {
|
||||
CX9261A_PowerMode powerMode;
|
||||
CX9261A_Power rxPower;
|
||||
CX9261A_Power txPower;
|
||||
CX9261A_Power fddPower;
|
||||
} CX9261A_PowerManagement;
|
||||
|
||||
/**
|
||||
* @brief 储存窄带校准结果的结构体
|
||||
*/
|
||||
typedef struct {
|
||||
int bHigh;
|
||||
int bLow;
|
||||
int cHigh;
|
||||
int cLow;
|
||||
int dciHigh;
|
||||
int dciLow;
|
||||
int dcqHigh;
|
||||
int dcqLow;
|
||||
} CX9261A_CalibPredis;
|
||||
|
||||
/**
|
||||
* @brief CX9261A结构体
|
||||
*/
|
||||
typedef struct {
|
||||
CX9261A_TemperatureComp tempComp; /**< 温度补偿*/
|
||||
CX9261A_AGC agc; /**< AGC结构体*/
|
||||
CX9261A_Interface interface; /**< Interface结构体*/
|
||||
CX9261A_Clock clock; /**< Clock结构体*/
|
||||
CX9261A_PllSource pllSource; /**< PllSource结构体*/
|
||||
CX9261A_Calib calib; /**< Calib结构体*/
|
||||
CX9261A_PllFreq pllFreq; /**< PllFreq结构体*/
|
||||
CX9261A_TxNCO txNco; /**< TxNCO结构体*/
|
||||
CX9261A_RxNCO rxNco; /**< RxNCO结构体*/
|
||||
CX9261A_RxConfig rx1Config; /**< RxConfig结构体*/
|
||||
CX9261A_RxConfig rx2Config; /**< RxConfig结构体*/
|
||||
CX9261A_RxConfig rx3Config; /**< RxConfig结构体*/
|
||||
CX9261A_TxConfig tx1Config; /**< TxConfig结构体*/
|
||||
CX9261A_TxConfig tx2Config; /**< TxConfig结构体*/
|
||||
CX9261A_Filters rxFilters; /**< Filters结构体*/
|
||||
CX9261A_Filters txFilters; /**< Filters结构体*/
|
||||
CX9261A_PowerManagement powerManagement; /**< PowerManagement结构体*/
|
||||
uint32_t numRxFIR;
|
||||
uint32_t numTxFIR;
|
||||
double rxFIRCoe[MAX_NUM_FIR]; /**< Rx FIR滤波器系数*/
|
||||
double txFIRCoe[MAX_NUM_FIR]; /**< Tx FIR滤波器系数*/
|
||||
} CX9261A_CX9261AConfiguration;
|
||||
|
||||
typedef struct {
|
||||
int first;
|
||||
int second;
|
||||
}QecStatePair;
|
||||
|
||||
|
||||
// 定义函数指针类型
|
||||
typedef void (*CX9261A_LoggingFunc)(const char* msg);
|
||||
typedef void (*CX9261A_WriteSpiFunc)(int address, int value);
|
||||
typedef int (*CX9261A_ReadSpiFunc)(int address);
|
||||
typedef void (*CX9261A_PauseFunc)(double ms);
|
||||
typedef void (*CX9261A_SetPinFunc)(int pin, int value);
|
||||
|
||||
/**
|
||||
* @brief 绑定日志函数
|
||||
* @param msg 要输出的内容
|
||||
*/
|
||||
void CX9261A_setLoggingFunc(CX9261A_LoggingFunc func);
|
||||
/**
|
||||
* @brief 绑定SPI写入寄存器函数
|
||||
* @param address 要写入的寄存器地址
|
||||
* @param value 要写入的寄存器值
|
||||
*/
|
||||
void CX9261A_setWriteSpiFunc(CX9261A_WriteSpiFunc func);
|
||||
/**
|
||||
* @brief 绑定等待函数
|
||||
* @param ms 等待时间,单位毫秒
|
||||
*/
|
||||
void CX9261A_setReadSpiFunc(CX9261A_ReadSpiFunc func);
|
||||
/**
|
||||
* @brief 绑定SPI读取寄存器函数
|
||||
* @param address 要读取的寄存器地址
|
||||
* @return 返回的寄存器值
|
||||
*/
|
||||
void CX9261A_setPauseFunc(CX9261A_PauseFunc func);
|
||||
/**
|
||||
* @brief 绑定配置FPGA对应寄存器函数
|
||||
* @param pin 寄存器地址
|
||||
* @param value 寄存器值
|
||||
*/
|
||||
void CX9261A_setSetPinFunc(CX9261A_SetPinFunc func);
|
||||
|
||||
/**
|
||||
* @brief 初始化芯片状态,写入与具体配置无关的寄存器值
|
||||
*/
|
||||
void CX9261A_initialChip();
|
||||
/**
|
||||
* @brief 初始化电源配置,如果只自定义配置部分模式下的电源管理,在自定义配置之前需要先调用此函数
|
||||
*/
|
||||
void CX9261A_initialPowerConfig(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 初始化BBPLL相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialBBPLL();
|
||||
/**
|
||||
* @brief 初始化PLL1相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL1();
|
||||
/**
|
||||
* @brief 初始化PLL2相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL2();
|
||||
/**
|
||||
* @brief 初始化PLL3相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL3();
|
||||
/**
|
||||
* @brief 初始化PLL4相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL4();
|
||||
/**
|
||||
* @brief 初始化PLL5相关寄存器,如果调用了initialChip,则无需单独调用此函数
|
||||
*/
|
||||
void CX9261A_initialPLL5();
|
||||
/**
|
||||
* @brief 配置受参考时钟频率影响的寄存器
|
||||
* @param ref 参考时钟频率,单位MHz
|
||||
*/
|
||||
void CX9261A_configRef(double ref);
|
||||
/**
|
||||
* @brief 配置时钟相关寄存器,包括ADC和BBPLL
|
||||
* @param config CX9261A参数结构体
|
||||
*/
|
||||
void CX9261A_configBBPLL(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief BBPLL AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcBBPll();
|
||||
/**
|
||||
* @brief 配置PLL1频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll1(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll1 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll1();
|
||||
/**
|
||||
* @brief 配置PLL2频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll2(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll2 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll2();
|
||||
/**
|
||||
* @brief 配置PLL3频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll3(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll3 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll3();
|
||||
/**
|
||||
* @brief 配置PLL4频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll4(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll4 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll4();
|
||||
/**
|
||||
* @brief 配置PLL5频率
|
||||
* @param lo 目标频率
|
||||
* @param clock 时钟结构体,使用其中的ref和refDoubler属性
|
||||
*/
|
||||
void CX9261A_configPll5(double lo, const CX9261A_Clock *clock);
|
||||
/**
|
||||
* @brief Pll5 AFC
|
||||
* @return 是否锁定
|
||||
*/
|
||||
bool CX9261A_afcPll5();
|
||||
/**
|
||||
* @brief 配置AGC模式
|
||||
* @param mode 模式0~13
|
||||
*/
|
||||
void CX9261A_configAGCMode(int mode);
|
||||
/**
|
||||
* @brief 配置AGC PDT
|
||||
* @param pdt AGCPDT结构体
|
||||
*/
|
||||
void CX9261A_configAGCPDT(const CX9261A_AGCPDT *pdt);
|
||||
/**
|
||||
* @brief 配置AGC LMT
|
||||
* @param lmt AGCLMT结构体
|
||||
*/
|
||||
void CX9261A_configAGCLMT(const CX9261A_AGCLMT *lmt);
|
||||
/**
|
||||
* @brief 配置AGC DIG
|
||||
* @param dig AGCDIG结构体
|
||||
*/
|
||||
void CX9261A_configAGCDIG(const CX9261A_AGCDIG *dig);
|
||||
/**
|
||||
* @brief 配置AGC
|
||||
* @param agc AGC结构体
|
||||
*/
|
||||
void CX9261A_configAGC(const CX9261A_AGC *agc);
|
||||
/**
|
||||
* @brief 配置片内处理器,仅在使用需要处理器辅助的校准方法时需要开启处理器
|
||||
* @param on 开启/关闭
|
||||
*/
|
||||
void CX9261A_configRISCV(bool on);
|
||||
/**
|
||||
* @brief 配置温补
|
||||
* @param mode 温补模式 DAC/Band
|
||||
*/
|
||||
void CX9261A_configTemperatureCompensation(CX9261A_TemperatureComp mode);
|
||||
/**
|
||||
* @brief ADC校准
|
||||
* @param adc ADC速率
|
||||
*/
|
||||
void CX9261A_configADCCalib(double adc);
|
||||
/**
|
||||
* @brief Flash校准
|
||||
*/
|
||||
void CX9261A_configFlashCalib();
|
||||
/**
|
||||
* @brief QEC校准会改变部分寄存器配置,在进行校准之前需要保存这部分寄存器,校准后恢复
|
||||
* @return 包含寄存器地址和值的map
|
||||
*/
|
||||
void CX9261A_beforeQecState(QecStatePair* buff, size_t *len);
|
||||
/**
|
||||
* @brief 恢复QEC校准过程中改变的寄存器
|
||||
* @param state beforeQecState函数返回的map
|
||||
*/
|
||||
void CX9261A_restoreQecState(QecStatePair* buff, size_t len);
|
||||
/**
|
||||
* @brief 根据pll来源配置校准模式下的电源管理
|
||||
* @param pllSource PllSource结构体
|
||||
*/
|
||||
void CX9261A_preparePowerForRxCalib(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 调整校准时Pll的配置
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要进行校准的通道
|
||||
*/
|
||||
void CX9261A_preparePllForRxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 等待RxTST窄带校准结束,可重写
|
||||
* @return 校准是否结束
|
||||
*/
|
||||
bool CX9261A_waitRxTSTFinished();
|
||||
/**
|
||||
* @brief RX时域统计校准
|
||||
* @param chan 校准的RX通道
|
||||
*/
|
||||
void CX9261A_rxTSTCalib(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief RX延时线校准
|
||||
* @param fs ADC采样率
|
||||
* @param chan 校准的RX通道
|
||||
*/
|
||||
void CX9261A_rxDelayCalib(double fs, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief DC Tracking
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_configDcCalib(const CX9261A_Calib *config);
|
||||
void CX9261A_configDcCalibMethod(CX9261A_DCCalibMethod method);
|
||||
void CX9261A_configDcTrackingLength(int length);
|
||||
void CX9261A_configDcHighPassFactor(int factor);
|
||||
/**
|
||||
* @brief Rx校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要进行校准的通道
|
||||
*/
|
||||
void CX9261A_rxCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 选择校准方法
|
||||
* @param calib 校准结构体
|
||||
*/
|
||||
void CX9261A_configCalibMethod(const CX9261A_Calib *calib);
|
||||
/**
|
||||
* @brief 读取当前Rx chan通道的校准值
|
||||
* @param chan Rx通道
|
||||
* @return 校准值结构体
|
||||
*/
|
||||
CX9261A_CalibPredis CX9261A_readRxCalibPredis(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 储存校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 接收通道
|
||||
* @param pll 使用的PLL
|
||||
*/
|
||||
void CX9261A_saveRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief 加载保存的校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 指定加载校准值的通道
|
||||
* @param pll 使用的PLL
|
||||
*/
|
||||
void CX9261A_loadRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Rx窄带多点校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param points 校准点
|
||||
* @param chan 接收通道
|
||||
*/
|
||||
void CX9261A_configRxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, CX9261A_RxChannel chan, const double *points, size_t len);
|
||||
/**
|
||||
* @brief 根据pll来源配置校准模式下的电源管理
|
||||
* @param pllSource PllSource结构体
|
||||
*/
|
||||
void CX9261A_preparePowerForTxCalib(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 调整校准时Pll的配置
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_preparePllForTxCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief TX二分法QEC校准
|
||||
* @param f0 校准音频率
|
||||
* @param fs adc频率
|
||||
*/
|
||||
void CX9261A_txBisectionQecCalib(double f0, double fs);
|
||||
/**
|
||||
* @brief TX时域统计法校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param chan 要校准的通道
|
||||
*/
|
||||
void CX9261A_txTSTCalib(const CX9261A_CX9261AConfiguration *config, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief TX二分法DC校准
|
||||
* @param f0 校准音频率
|
||||
* @param fs adc频率
|
||||
*/
|
||||
void CX9261A_txBisectionDcCalib(double f0, double fs);
|
||||
/**
|
||||
* @brief Tx多点校准
|
||||
* @param config CX9261A配置结构体
|
||||
* @param points 校准点
|
||||
*/
|
||||
void CX9261A_configTxMultiPointsQec(const CX9261A_CX9261AConfiguration *config, const double *points, size_t len);
|
||||
/**
|
||||
* @brief Tx通道校准
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_txCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 储存校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 发射通道
|
||||
* @param pll pll
|
||||
*/
|
||||
void CX9261A_saveTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief 加载保存的校准值
|
||||
* @param index 第index组校准值
|
||||
* @param chan 指定加载校准值的通道
|
||||
* @param pll 指定加载校准值对应的PLL
|
||||
*/
|
||||
void CX9261A_loadTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准
|
||||
* @param config CX9261A配置结构体
|
||||
*/
|
||||
void CX9261A_configQecCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
/**
|
||||
* @brief 配置TX NCO相关寄存器
|
||||
* @param nco TX NCO配置结构体
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configTxNco(const CX9261A_TxNCO *nco, double fs);
|
||||
/**
|
||||
* @brief 配置TX NCO BIST模式
|
||||
* @param bist 开启/关闭BIST
|
||||
*/
|
||||
void CX9261A_configTxBIST(bool bist);
|
||||
/**
|
||||
* @brief 配置TX NCO频率
|
||||
* @param freq 混频频率
|
||||
* @param fs adc抽取后速率
|
||||
*/
|
||||
void CX9261A_configTxNcoFreq(double freq, double fs);
|
||||
/**
|
||||
* @brief 配置RX NCO相关寄存器
|
||||
* @param nco RX NCO配置结构体
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configRxNco(const CX9261A_RxNCO *nco, double fs);
|
||||
/**
|
||||
* @brief 配置Rx NCO模式
|
||||
* @param mode NCO模式:Bypass/BIST/Up/Down
|
||||
*/
|
||||
void CX9261A_configRxNcoMode(CX9261A_NCOMode mode);
|
||||
/**
|
||||
* @brief 配置Rx NCO模式
|
||||
* @param mode NCO模式:Master/Slaver
|
||||
*/
|
||||
void CX9261A_configRxNcoMS(CX9261A_NCOMode mode);
|
||||
/**
|
||||
* @brief 配置Rx NCO频率
|
||||
* @param freq 混频频率
|
||||
* @param fs adc速率
|
||||
*/
|
||||
void CX9261A_configRxNcoFreq(double freq, double fs);
|
||||
/**
|
||||
* @brief 配置接口相关寄存器
|
||||
* @param interface Interface配置结构体
|
||||
*/
|
||||
void CX9261A_configInterface(const CX9261A_Interface *interface);
|
||||
/**
|
||||
* @brief 配置PLL来源
|
||||
* @param pllSource PLlSource结构体
|
||||
*/
|
||||
void CX9261A_configPllSource(const CX9261A_PllSource *pllSource);
|
||||
/**
|
||||
* @brief 切换电源模式
|
||||
* @param pm 电源模式
|
||||
*/
|
||||
void CX9261A_configPowerMode(CX9261A_PowerMode pm);
|
||||
/**
|
||||
* @brief 配置电源管理
|
||||
* @param power 电源配置结构体
|
||||
* @param pm 电源模式
|
||||
*/
|
||||
void CX9261A_configPowerPins(const CX9261A_Power *power, CX9261A_PowerMode pm);
|
||||
/**
|
||||
* @brief 配置参考倍频器
|
||||
* @param doubler 倍频器开关
|
||||
* @param ref 参考时钟频率,单位MHz
|
||||
*/
|
||||
void CX9261A_configRefDoubler(bool doubler, double ref);
|
||||
/**
|
||||
* @brief 初始化通道,调用initialChip函数会初始化RX1,RX2,RX3三个通道
|
||||
* @param chan 通道 RX1/RX2/RX3
|
||||
*/
|
||||
void CX9261A_initialRxChannel(CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx带宽
|
||||
* @note 只改变Rx带宽会导致通道增益改变,建议使用configRxChannel函数进行带宽调整
|
||||
* @param bandwidth 带宽,单位(MHz)
|
||||
* @param chan 通道 Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxBandwidth(double bandwidth, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx TIA
|
||||
* @note 只改变TIA会导致通道带宽改变,建议使用configRxChannel函数进行TIA调整
|
||||
* @param tia tia档位
|
||||
* @param chan 通道 Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxTIA(int tia, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx Mixer
|
||||
* @param mixer mixer档位
|
||||
*/
|
||||
void CX9261A_configRxMixer(int mixer);
|
||||
/**
|
||||
* @brief 配置Rx通道,包含TIA,Mixer以及Bandwidth
|
||||
* @param config RxConfig结构体
|
||||
* @param chan Rx1/Rx2/Rx3
|
||||
*/
|
||||
void CX9261A_configRxChannel(const CX9261A_RxConfig *config, CX9261A_RxChannel chan);
|
||||
/**
|
||||
* @brief 配置Rx FIR滤波器抽取倍数
|
||||
* @param fir 抽取倍数 0(Bypass)/1/2/3/4/8
|
||||
*/
|
||||
void CX9261A_configRxFIR(int fir);
|
||||
/**
|
||||
* @brief 配置Rx HBF1滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configRxHBF1(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx HBF2滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configRxHBF2(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx HBF3滤波器抽取倍数
|
||||
* @param hbf 抽取倍数 0(Bypass)/2/3
|
||||
*/
|
||||
void CX9261A_configRxHBF3(int hbf);
|
||||
/**
|
||||
* @brief 配置Rx CIC滤波器
|
||||
* @param cic 抽取倍数 0(Bypass)/20
|
||||
*/
|
||||
void CX9261A_configRxCIC(int cic);
|
||||
/**
|
||||
* @brief 配置Rx滤波器
|
||||
* @param filters Filters结构体
|
||||
*/
|
||||
void CX9261A_configRxFilters(const CX9261A_Filters *filters);
|
||||
/**
|
||||
* @brief 配置Rx FIR滤波器系数
|
||||
* @param coe 滤波器系数,长度为16的整倍数,最大128
|
||||
*/
|
||||
void CX9261A_configRxFIRCoe(const double *coe, size_t len);
|
||||
/**
|
||||
* @brief 配置Tx带宽
|
||||
* @param bandwidth 带宽,单位(MHz)
|
||||
* @param chan 通道 TX1/TX2
|
||||
*/
|
||||
void CX9261A_configTxBandwidth(double bandwidth, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx Mixer
|
||||
* @param mixer 混频器值
|
||||
* @param chan TX1/TX2
|
||||
*/
|
||||
void CX9261A_configTxMixer(int mixer, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 初始化Tx通道
|
||||
* @param chan 通道 TX1/TX2
|
||||
*/
|
||||
void CX9261A_initialTxChannel(CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 根据Tx通道的本振频率,配置对应的参数
|
||||
* @param lo 本振频率,单位(MHz)
|
||||
* @param chan 通道(Tx1/Tx2)
|
||||
*/
|
||||
void CX9261A_configTxChannelFrequency(double lo, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx通道,Mixer以及Bandwidth
|
||||
* @param config TxConfig结构体
|
||||
* @param chan Tx1/Tx2
|
||||
*/
|
||||
void CX9261A_configTxChannel(const CX9261A_TxConfig *config, CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 配置Tx FIR滤波器插值倍数
|
||||
* @param fir 插值倍数 0(Bypass)/1/2/3/4/8
|
||||
*/
|
||||
void CX9261A_configTxFIR(int fir);
|
||||
/**
|
||||
* @brief 配置Tx HBF1滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configTxHBF1(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx HBF2滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2
|
||||
*/
|
||||
void CX9261A_configTxHBF2(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx HBF3滤波器插值倍数
|
||||
* @param hbf 插值倍数 0(Bypass)/2/3
|
||||
*/
|
||||
void CX9261A_configTxHBF3(int hbf);
|
||||
/**
|
||||
* @brief 配置Tx CIC滤波器
|
||||
* @param cic 插值倍数 0(Bypass)/8/20/32/80
|
||||
*/
|
||||
void CX9261A_configTxCIC(int cic);
|
||||
/**
|
||||
* @brief 配置Tx滤波器
|
||||
* @param filters Filters结构体
|
||||
*/
|
||||
void CX9261A_configTxFilters(const CX9261A_Filters *filters);
|
||||
/**
|
||||
* @brief 配置Tx FIR滤波器系数
|
||||
* @param coe 滤波器系数,长度为16的整倍数,最大128
|
||||
*/
|
||||
void CX9261A_configTxFIRCoe(const double *coe, size_t len);
|
||||
/**
|
||||
* @brief 读取当前Tx chan通道的校准值
|
||||
* @param chan Tx通道
|
||||
* @return 校准值结构体
|
||||
*/
|
||||
CX9261A_CalibPredis CX9261A_readTxCalibPredis(CX9261A_TxChannel chan);
|
||||
/**
|
||||
* @brief 此函数为Demo板配套配置函数,用于配置FPGA接口,用户开发自己的程序时应重写对应功能
|
||||
* @param interface Interface结构体
|
||||
*/
|
||||
void CX9261A_configFPGA(const CX9261A_Interface *interface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __CX9261ADRIVER_C_H
|
||||
@@ -0,0 +1,234 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "cx9261adriver_c.h"
|
||||
|
||||
#define max(x, y) ((x >= y) ? x : y)
|
||||
|
||||
// --- Dummy systemcall implementation
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
int _write(int file, char *ptr, int len)
|
||||
{
|
||||
return len;
|
||||
}
|
||||
|
||||
int _read(int file, char *ptr, int len)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _close(int file)
|
||||
{
|
||||
return -1; // 模拟文件关闭失败
|
||||
}
|
||||
|
||||
int _fstat(int file, struct stat *st)
|
||||
{
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _lseek(int file, int ptr, int dir)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _isatty(int file)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int _kill(int pid, int sig)
|
||||
{
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
int _getpid(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
// ---
|
||||
|
||||
void udelay(uint32_t cnt)
|
||||
{
|
||||
while (cnt--)
|
||||
;
|
||||
}
|
||||
|
||||
void CX9261A_Log(const char *msg)
|
||||
{
|
||||
printf("[CX9261A] %s\n", msg);
|
||||
}
|
||||
void CX9261A_spiWrite(int address, int value)
|
||||
{
|
||||
printf("[CX9261A] spi write 0x%08X = 0x%08X\n", address, value);
|
||||
}
|
||||
int CX9261A_spiRead(int address)
|
||||
{
|
||||
printf("[CX9261A] spi read 0x%08X\n", address);
|
||||
return 0xFFFFF;
|
||||
}
|
||||
void CX9261A_mdelay(double ms)
|
||||
{
|
||||
udelay((uint32_t)ms * 1e3);
|
||||
}
|
||||
void CX9261A_setPin(int pin, int value)
|
||||
{
|
||||
printf("[CX9261A] set 0x%08X = 0x%08X\n", pin, value);
|
||||
return;
|
||||
}
|
||||
|
||||
CX9261A_CX9261AConfiguration 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},
|
||||
// 发射模式电源管理
|
||||
.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模式电源管理
|
||||
.fddPower = {1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1,
|
||||
0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1},
|
||||
.powerMode = CX9261A_PWM_Receive,
|
||||
},
|
||||
// 接口模式
|
||||
.interface = {.workMode = CX9261A_WKM_Rx,
|
||||
.trMode = CX9261A_TRM_R1T1,
|
||||
.portMode = CX9261A_PORTM_Single,
|
||||
.ioMode = CX9261A_IOM_CMOS},
|
||||
// 时钟相关
|
||||
.clock = {.ref = 125,
|
||||
.adc = 64,
|
||||
.refDiv = 2,
|
||||
.bbUseIntDiv = false,
|
||||
.refDoubler = false},
|
||||
// 本振相关
|
||||
// 本振来源
|
||||
.pllSource = {.rxUseExt = false,
|
||||
.txUseExt = false,
|
||||
.rx1Source = CX9261A_LOSRC_Pll1,
|
||||
.rx2Source = CX9261A_LOSRC_Pll1,
|
||||
.rx3Source = CX9261A_LOSRC_Off,
|
||||
.tx1Source = CX9261A_LOSRC_Off,
|
||||
.tx2Source = CX9261A_LOSRC_Off},
|
||||
// 本振频率 注意:使用的所有PLL,频率必须设为正数
|
||||
.pllFreq = {.pll1Freq = 5800,
|
||||
.pll2Freq = 5800,
|
||||
.pll3Freq = 800,
|
||||
.pll4Freq = 900,
|
||||
.pll5Freq = 1000},
|
||||
// Rx通道 注意:tia推荐配置为6 Mixer为三个通道共用同一个寄存器
|
||||
.rx1Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
.rx2Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
.rx3Config = {.bandwidth = 32, .tia = 6, .mixer = 31},
|
||||
// Tx通道
|
||||
.tx1Config = {.bandwidth = 20, .mixer = 63},
|
||||
.tx2Config = {.bandwidth = 20, .mixer = 63},
|
||||
// 接收滤波器
|
||||
.rxFilters = {.fir = 0, .hbf1 = 0, .hbf2 = 0, .hbf3 = 0, .cic = 0},
|
||||
// 发射滤波器
|
||||
.txFilters = {.fir = 0, .hbf1 = 2, .hbf2 = 2, .hbf3 = 0, .cic = 0},
|
||||
// Rx NCO
|
||||
.rxNco = {.rxUseBist = false,
|
||||
.rxNCOBypass = true,
|
||||
.rxNCOUpward = true,
|
||||
.rxNCOMaster = true,
|
||||
.rxNCOFreq = 0},
|
||||
// Tx NCO
|
||||
.txNco = {.txUseBist = false, .txNCOFreq = 0},
|
||||
// AGC 注意:mode = 0表示关闭AGC,此时其他的参数可以不配置
|
||||
// 校准
|
||||
.calib = {.calibDC = true,
|
||||
.dcCalibMethod = CX9261A_DCCALM_Tracking,
|
||||
.dcTrackingLength = 16384,
|
||||
.dcHighPassFactor = 8191,
|
||||
.rx1CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2,
|
||||
.rx2CalibPll = CX9261A_LOSRC_Pll1 | CX9261A_LOSRC_Pll2,
|
||||
.rx3CalibPll = CX9261A_LOSRC_Pll5,
|
||||
.tx1CalibPll = 0,
|
||||
.tx2CalibPll = 0,
|
||||
.rxMethod = CX9261A_CALM_MultiPoints,
|
||||
.txMethod = CX9261A_CALM_Bisec,
|
||||
.f0 = 4,
|
||||
.rxMultiPoints = {2200, 2400, 2600, 2800, 3000, 3200, 3400,
|
||||
3600, 3800, 4000, 4200, 4400, 4600, 4800,
|
||||
5000, 5200, 5400, 5600, 5800, 6000}},
|
||||
.agc = {.mode = 0},
|
||||
.tempComp = CX9261A_TEMPCP_Band
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
// 绑定函数
|
||||
CX9261A_setLoggingFunc(CX9261A_Log);
|
||||
CX9261A_setWriteSpiFunc(CX9261A_spiWrite);
|
||||
CX9261A_setReadSpiFunc(CX9261A_spiRead);
|
||||
CX9261A_setPauseFunc(CX9261A_mdelay);
|
||||
CX9261A_setSetPinFunc(CX9261A_setPin);
|
||||
|
||||
// 开始配置芯片
|
||||
CX9261A_initialChip(); // 最开始需要调用此函数
|
||||
CX9261A_initialPowerConfig(&configuration);
|
||||
// 配置温补
|
||||
CX9261A_configTemperatureCompensation(configuration.tempComp);
|
||||
// 不需要自定义电源管理时,这部分代码可以省略
|
||||
CX9261A_configPowerPins(&(configuration.powerManagement.rxPower), CX9261A_PWM_Receive);
|
||||
CX9261A_configPowerPins(&(configuration.powerManagement.txPower), CX9261A_PWM_Transmit);
|
||||
CX9261A_configPowerPins(&(configuration.powerManagement.fddPower), CX9261A_PWM_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_RXCH_Rx1);
|
||||
CX9261A_configRxChannel(&(configuration.rx2Config), CX9261A_RXCH_Rx2);
|
||||
CX9261A_configRxChannel(&(configuration.rx3Config), CX9261A_RXCH_Rx3);
|
||||
// 配置Tx通道
|
||||
CX9261A_configTxChannelFrequency(configuration.pllFreq.pll1Freq, CX9261A_TXCH_Tx1);
|
||||
CX9261A_configTxChannelFrequency(configuration.pllFreq.pll2Freq, CX9261A_TXCH_Tx2);
|
||||
CX9261A_configTxChannel(&(configuration.tx1Config), CX9261A_TXCH_Tx1);
|
||||
CX9261A_configTxChannel(&(configuration.tx2Config), CX9261A_TXCH_Tx2);
|
||||
// 配置滤波器
|
||||
CX9261A_configRxFilters(&(configuration.rxFilters));
|
||||
CX9261A_configTxFilters(&(configuration.txFilters));
|
||||
// 配置NCO
|
||||
CX9261A_configRxNco(&(configuration.rxNco), configuration.clock.adc);
|
||||
int filters = max(configuration.rxFilters.fir, 1) * max(configuration.rxFilters.hbf3, 1) *
|
||||
max(configuration.rxFilters.hbf2, 1) *
|
||||
max(configuration.rxFilters.hbf1, 1) * max(configuration.rxFilters.cic, 1);
|
||||
CX9261A_configTxNco(&(configuration.txNco), configuration.clock.adc / filters);
|
||||
// 配置AGC
|
||||
CX9261A_configAGC(&(configuration.agc));
|
||||
// 切换到休眠模式
|
||||
CX9261A_configPowerMode(CX9261A_PWM_Sleep);
|
||||
udelay(1000 * 1000);
|
||||
// 切换到校准模式
|
||||
CX9261A_configPowerMode(CX9261A_PWM_Calib);
|
||||
udelay(100 * 1000);
|
||||
// 锁定BBPLL
|
||||
CX9261A_afcBBPll();
|
||||
// 配置校准
|
||||
CX9261A_configADCCalib(configuration.clock.adc);
|
||||
CX9261A_configFlashCalib();
|
||||
CX9261A_configDcCalib(&(configuration.calib));
|
||||
CX9261A_configQecCalib(&configuration);
|
||||
CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx1, CX9261A_LOSRC_Pll1);
|
||||
CX9261A_loadRxCalibPredis(0, CX9261A_RXCH_Rx2, CX9261A_LOSRC_Pll1);
|
||||
// 配置接口
|
||||
CX9261A_configInterface(&(configuration.interface));
|
||||
// 配置FPGA接口相关 此为示例,仅适用于Demo工程,用户应根据实际情况进行配置
|
||||
CX9261A_configFPGA(&(configuration.interface));
|
||||
// 锁定PLL1
|
||||
CX9261A_afcPll1();
|
||||
// 锁定PLL2
|
||||
CX9261A_afcPll2();
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user