Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1252fe538e | ||
|
|
2fc5941f0f |
@@ -10,10 +10,10 @@ 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 \
|
||||
-pedantic -Wall -Wextra \
|
||||
-fmessage-length=0 -mfpu=vfpv3 -mfloat-abi=hard \
|
||||
-I. -I./cx9261A_api
|
||||
CFLAGS := -std=c17 -Wall -Wextra \
|
||||
CFLAGS := -std=c17 -pedantic -Wall -Wextra \
|
||||
-fmessage-length=0 -mfpu=vfpv3 -mfloat-abi=hard \
|
||||
-I.
|
||||
DEBUG_FLAGS := -fdebug-prefix-map=$(CURDIR)/=/tmp/dbg/cx9261a_c/ \
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "cx9261adriver.h"
|
||||
#include <cstdint>
|
||||
#include "cx9261adriver.h"
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -295,7 +296,7 @@ void configBBPLL(const CX9261AConfiguration& config)
|
||||
bbloDiv *= 2;
|
||||
}
|
||||
Register r602;
|
||||
r602.replace(1, 0, static_cast<unsigned char>(std::log2(bbloDiv)));
|
||||
r602.replace(1, 0, static_cast<std::uint8_t>(std::log2(bbloDiv)));
|
||||
r602[5] = fclkDiv == 5;
|
||||
// ref div
|
||||
Register r601{ 0x0F };
|
||||
@@ -303,14 +304,14 @@ void configBBPLL(const CX9261AConfiguration& config)
|
||||
writeSpi(0x601, r601);
|
||||
// nf
|
||||
const auto nf = bblo * clock.refDiv / (clock.ref * (clock.refDoubler ? 2 : 1));
|
||||
int n = floor(nf);
|
||||
int n = floor32(nf);
|
||||
const auto f = nf - n;
|
||||
r602[6] = clock.bbUseIntDiv;
|
||||
writeSpi(0x602, r602);
|
||||
// 整数模式
|
||||
if (clock.bbUseIntDiv)
|
||||
n = round(2.0 * n / bbloDiv + 1);
|
||||
const int fBin = round(std::pow(2, 25) * f);
|
||||
n = round32(2.0 * n / bbloDiv + 1);
|
||||
const int fBin = round32(std::pow(2, 25) * f);
|
||||
Register r60D{ 0x0C };
|
||||
r60D[0] = f >= 0.5;
|
||||
r60D[4] = clock.bbUseIntDiv;
|
||||
@@ -360,7 +361,7 @@ void configBBPLL(const CX9261AConfiguration& config)
|
||||
writeSpi(0x747, r70F);
|
||||
auto c = 8600 * adjAdc / adcClock;
|
||||
c = (c - 3000) / 80;
|
||||
const Register r70D = round(c);
|
||||
const Register r70D = round32(c);
|
||||
writeSpi(0x70D, r70D);
|
||||
writeSpi(0x729, r70D);
|
||||
writeSpi(0x745, r70D);
|
||||
@@ -383,7 +384,7 @@ bool afcBBPll()
|
||||
LOGGING("BBPLL AFC");
|
||||
writeSpi(0x600, 0x00);
|
||||
writeSpi(0x600, 0x11);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
return readSpi(0x615) & 0b00100000;
|
||||
}
|
||||
|
||||
@@ -453,13 +454,13 @@ std::vector<int> configPllImpl(const double lo, const double ref)
|
||||
}();
|
||||
ret[1] = outputDiv;
|
||||
const auto nf = static_cast<std::int64_t>(std::round(vco / ref * 1e9)) / 1.0e9;
|
||||
const auto n = floor(nf);
|
||||
const auto n = floor32(nf);
|
||||
const auto f = nf - n;
|
||||
const Register nHigh = n >= 256;
|
||||
ret[2] = nHigh;
|
||||
const Register nLow = n & 0xFF;
|
||||
ret[3] = nLow;
|
||||
const int fint = round(std::pow(2, 24) * f);
|
||||
const int fint = round32(std::pow(2, 24) * f);
|
||||
ret[4] = fint >> 16 & 0xFF;
|
||||
ret[5] = fint >> 8 & 0xFF;
|
||||
ret[6] = fint & 0xFF;
|
||||
@@ -494,7 +495,7 @@ bool afcPll1()
|
||||
writeSpi(0x61D, r61D);
|
||||
writeSpi(0x617, 0x00);
|
||||
writeSpi(0x617, 0x13);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
writeSpi(0x61D, saved);
|
||||
const auto lock = readSpi(0x635);
|
||||
return 0x10 & lock;
|
||||
@@ -526,7 +527,7 @@ bool afcPll2()
|
||||
writeSpi(0x63F, r63F);
|
||||
writeSpi(0x639, 0x00);
|
||||
writeSpi(0x639, 0x13);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
writeSpi(0x63F, saved);
|
||||
const auto lock = readSpi(0x657);
|
||||
return 0x10 & lock;
|
||||
@@ -558,7 +559,7 @@ bool afcPll3()
|
||||
writeSpi(0x661, r661);
|
||||
writeSpi(0x65B, 0x00);
|
||||
writeSpi(0x65B, 0x13);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
writeSpi(0x661, saved);
|
||||
const auto lock = readSpi(0x679);
|
||||
return 0x10 & lock;
|
||||
@@ -590,7 +591,7 @@ bool afcPll4()
|
||||
writeSpi(0x683, r683);
|
||||
writeSpi(0x67D, 0x00);
|
||||
writeSpi(0x67D, 0x13);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
writeSpi(0x683, saved);
|
||||
const auto lock = readSpi(0x69B);
|
||||
return 0x10 & lock;
|
||||
@@ -622,7 +623,7 @@ bool afcPll5()
|
||||
writeSpi(0x6A5, r6A5);
|
||||
writeSpi(0x69F, 0x00);
|
||||
writeSpi(0x69F, 0x13);
|
||||
pause(delay);
|
||||
pause(afcDelay);
|
||||
writeSpi(0x6A5, saved);
|
||||
const auto lock = readSpi(0x6BD);
|
||||
return 0x10 & lock;
|
||||
@@ -1120,19 +1121,19 @@ CalibPredis readRxCalibPredis(const RxChannel chan)
|
||||
LOGGING(std::string("读取") + toString(chan) + "校准值");
|
||||
writeSpi(0x000, chan == RxChannel::Rx1 ? 0x12 : chan == RxChannel::Rx2 ? 0x22 : 0x32);
|
||||
writeSpi(0x121, 0x00);
|
||||
const CalibPredis predis{ .bHigh = readSpi(0x13D),
|
||||
.bLow = readSpi(0x13E),
|
||||
.cHigh = readSpi(0x13F),
|
||||
.cLow = readSpi(0x140),
|
||||
.dciHigh = readSpi(0x141),
|
||||
.dciLow = readSpi(0x142),
|
||||
.dcqHigh = readSpi(0x143),
|
||||
.dcqLow = readSpi(0x144) };
|
||||
CalibPredis predis;
|
||||
predis.bLow = readSpi(0x13E);
|
||||
predis.cHigh = readSpi(0x13F);
|
||||
predis.cLow = readSpi(0x140);
|
||||
predis.dciHigh = readSpi(0x141);
|
||||
predis.dciLow = readSpi(0x142);
|
||||
predis.dcqHigh = readSpi(0x143);
|
||||
predis.dcqLow = readSpi(0x144);
|
||||
writeSpi(0x000, 02);
|
||||
return predis;
|
||||
}
|
||||
|
||||
void saveRxCalibPredis(const unsigned char index, const RxChannel chan, const LoSource pll)
|
||||
void saveRxCalibPredis(const std::uint8_t index, const RxChannel chan, const LoSource pll)
|
||||
{
|
||||
LOGGING(std::string("保存") + toString(chan) + " " + toString(pll) + " index: " + std::to_string(index)
|
||||
+ " 校准值");
|
||||
@@ -1143,7 +1144,7 @@ void saveRxCalibPredis(const unsigned char index, const RxChannel chan, const Lo
|
||||
writeSpi(0x0A0, 0x01);
|
||||
}
|
||||
|
||||
void loadRxCalibPredis(const unsigned char index, const RxChannel chan, const LoSource pll)
|
||||
void loadRxCalibPredis(const std::uint8_t index, const RxChannel chan, const LoSource pll)
|
||||
{
|
||||
LOGGING("加载: " + toString(chan) + " " + toString(pll) + " " + std::to_string(index) + " 校准值")
|
||||
writeSpi(0x0A0, 0x00);
|
||||
@@ -1157,7 +1158,7 @@ void configRxMultiPointsQecImpl(const CX9261AConfiguration& config, const std::v
|
||||
const RxChannel chan)
|
||||
{
|
||||
auto mutConfig = config;
|
||||
for (auto i = 0; i < points.size(); ++i) {
|
||||
for (size_t i = 0; i < points.size(); ++i) {
|
||||
LOGGING("频点: " + std::to_string(points[i]));
|
||||
const auto source = chan == RxChannel::Rx1 ? config.pllSource.rx1Source
|
||||
: chan == RxChannel::Rx2 ? config.pllSource.rx2Source
|
||||
@@ -1340,7 +1341,7 @@ void txBisectionDcCalib(const double f0, const double fs)
|
||||
void configTxMultiPointsQecImpl(const CX9261AConfiguration& config, const std::vector<double>& points)
|
||||
{
|
||||
LOGGING("Tx多点校准");
|
||||
for (auto i = 0; i < points.size(); ++i) {
|
||||
for (size_t i = 0; i < points.size(); ++i) {
|
||||
LOGGING("频点: " + std::to_string(points[i]));
|
||||
configTxChannelFrequency(points[i], TxChannel::Tx1);
|
||||
configTxChannelFrequency(points[i], TxChannel::Tx2);
|
||||
@@ -1375,7 +1376,7 @@ void configTxMultiPointsQecImpl(const CX9261AConfiguration& config, const std::v
|
||||
void configTxMultiPointsQec(const CX9261AConfiguration& config, const std::vector<double>& points)
|
||||
{
|
||||
auto mutConfig = config;
|
||||
for (int i = 0; i < 5; ++i) {
|
||||
for (size_t i = 0; i < 5; ++i) {
|
||||
const auto& calibPll = mutConfig.calib.tx1CalibPll;
|
||||
if (calibPll & (0b1 << i)) {
|
||||
mutConfig.pllSource.tx1Source = static_cast<LoSource>(calibPll & (0b1 << i));
|
||||
@@ -1405,7 +1406,7 @@ void txCalib(const CX9261AConfiguration& config)
|
||||
}
|
||||
}
|
||||
|
||||
void saveTxCalibPredis(const unsigned char index, const TxChannel chan, const LoSource pll)
|
||||
void saveTxCalibPredis(const std::uint8_t index, const TxChannel chan, const LoSource pll)
|
||||
{
|
||||
LOGGING(std::string("保存") + toString(chan) + " " + "pll: " + toString(pll) + " "
|
||||
+ " index: " + std::to_string(index) + " 校准值");
|
||||
@@ -1416,7 +1417,7 @@ void saveTxCalibPredis(const unsigned char index, const TxChannel chan, const Lo
|
||||
writeSpi(0x0A0, 0x01);
|
||||
}
|
||||
|
||||
void loadTxCalibPredis(const unsigned char index, const TxChannel chan, const LoSource pll)
|
||||
void loadTxCalibPredis(const std::uint8_t index, const TxChannel chan, const LoSource pll)
|
||||
{
|
||||
LOGGING("加载: " + toString(chan) + toString(pll) + " " + " " + std::to_string(index) + " 校准值")
|
||||
writeSpi(0x0A0, 0x00);
|
||||
@@ -1466,17 +1467,11 @@ void configQecCalib(const CX9261AConfiguration& config)
|
||||
configPll5(config.pllFreq.pll5Freq, config.clock);
|
||||
afcPll5();
|
||||
}
|
||||
auto loadRxDefault = [&config](const RxChannel chan, const LoSource source, const double freq) {
|
||||
auto points = config.calib.rxMultiPoints;
|
||||
std::sort(points.begin(), points.end());
|
||||
const auto location = std::lower_bound(points.begin(), points.end(), freq);
|
||||
if (location != points.end()) {
|
||||
const auto fundFreq = *location;
|
||||
const auto it =
|
||||
std::find(config.calib.rxMultiPoints.begin(), config.calib.rxMultiPoints.end(), fundFreq);
|
||||
if (it != config.calib.rxMultiPoints.end()) {
|
||||
loadRxCalibPredis(it - config.calib.rxMultiPoints.begin(), chan, source);
|
||||
}
|
||||
const auto& points = config.calib.rxMultiPoints;
|
||||
auto loadRxDefault = [&points](const RxChannel chan, const LoSource source, const double freq) {
|
||||
const auto idx = search_first_ge(points, freq);
|
||||
if (idx != points.size()) {
|
||||
loadRxCalibPredis(idx, chan, source);
|
||||
}
|
||||
};
|
||||
if (config.pllSource.rx1Source != LoSource::Off) {
|
||||
@@ -1525,17 +1520,11 @@ void configQecCalib(const CX9261AConfiguration& config)
|
||||
configPll4(config.pllFreq.pll4Freq, config.clock);
|
||||
afcPll4();
|
||||
}
|
||||
auto loadTxDefault = [&config](const TxChannel chan, const LoSource source, const double freq) {
|
||||
auto points = config.calib.txMultiPoints;
|
||||
std::sort(points.begin(), points.end());
|
||||
const auto location = std::lower_bound(points.begin(), points.end(), freq);
|
||||
if (location != points.end()) {
|
||||
const auto fundFreq = *location;
|
||||
const auto it =
|
||||
std::find(config.calib.txMultiPoints.begin(), config.calib.txMultiPoints.end(), fundFreq);
|
||||
if (it != config.calib.txMultiPoints.end()) {
|
||||
loadTxCalibPredis(it - config.calib.txMultiPoints.begin(), chan, source);
|
||||
}
|
||||
const auto& points = config.calib.txMultiPoints;
|
||||
auto loadTxDefault = [&points](const TxChannel chan, const LoSource source, const double freq) {
|
||||
const auto idx = search_first_ge(points, freq);
|
||||
if (idx != points.size()) {
|
||||
loadTxCalibPredis(idx, chan, source);
|
||||
}
|
||||
};
|
||||
if (config.pllSource.tx1Source != LoSource::Off) {
|
||||
@@ -1797,12 +1786,12 @@ std::pair<int, int> configBandwidthImpl(const double bandwidth)
|
||||
auto c = 255;
|
||||
auto r = 0;
|
||||
for (; c > 0; --c) {
|
||||
r = floor(c * x + 128 * x - 1);
|
||||
r = floor32(c * x + 128 * x - 1);
|
||||
if (r <= 31 && r >= 0)
|
||||
break;
|
||||
}
|
||||
r = clamp(r, 0, 31);
|
||||
c = round((r + 1) / x) - 128;
|
||||
c = round32((r + 1) / x) - 128;
|
||||
return { r, c };
|
||||
}
|
||||
|
||||
@@ -1836,7 +1825,7 @@ void configRxChannel(const RxConfig& config, const RxChannel chan)
|
||||
{
|
||||
LOGGING("配置通道" + toString(chan));
|
||||
configRxTIA(config.tia, chan);
|
||||
int tiaCSel = round(1036.4364 * (config.tia + 1) / config.bandwidth - 40);
|
||||
int tiaCSel = round32(1036.4364 * (config.tia + 1) / config.bandwidth - 40);
|
||||
tiaCSel = clamp(tiaCSel, 0, 8191);
|
||||
const Register c1 = tiaCSel >> 8;
|
||||
const Register c2 = tiaCSel & 0xFF;
|
||||
@@ -1901,8 +1890,8 @@ void configRxFilters(const Filters& filters)
|
||||
void configRxFIRCoe(const std::vector<double>& coe)
|
||||
{
|
||||
LOGGING("配置Rx FIR系数");
|
||||
for (auto i = 0; i < coe.size(); ++i) {
|
||||
const auto value = round(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0);
|
||||
for (size_t i = 0; i < coe.size(); ++i) {
|
||||
const auto value = round32(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0);
|
||||
writeSpi(0x401, i);
|
||||
writeSpi(0x402, value >> 8 & 0xFF);
|
||||
writeSpi(0x403, value & 0xFF);
|
||||
@@ -1920,12 +1909,12 @@ std::pair<int, int> configTxBandwidthImpl(const double bandwidth)
|
||||
auto c = 127;
|
||||
auto r = 0;
|
||||
for (; c > 0; --c) {
|
||||
r = floor(c * x + 128 * x - 1);
|
||||
r = floor32(c * x + 128 * x - 1);
|
||||
if (r <= 31 && r >= 0)
|
||||
break;
|
||||
}
|
||||
r = clamp(r, 0, 31);
|
||||
c = round((r + 1) / x) - 128;
|
||||
c = round32((r + 1) / x) - 128;
|
||||
return { r, c };
|
||||
}
|
||||
|
||||
@@ -2041,8 +2030,8 @@ void configTxFilters(const Filters& filters)
|
||||
void configTxFIRCoe(const std::vector<double>& coe)
|
||||
{
|
||||
LOGGING("配置Tx FIR系数");
|
||||
for (auto i = 0; i < coe.size(); ++i) {
|
||||
const auto value = round(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0);
|
||||
for (size_t i = 0; i < coe.size(); ++i) {
|
||||
const auto value = round32(coe[i] * std::pow(2, 15)) + (coe[i] < 0 ? 65536 : 0);
|
||||
writeSpi(0x501, i);
|
||||
writeSpi(0x502, value >> 8 & 0xFF);
|
||||
writeSpi(0x503, value & 0xFF);
|
||||
@@ -2059,39 +2048,40 @@ CalibPredis readTxCalibPredis(const TxChannel chan)
|
||||
LOGGING("读取校准系数: " + toString(chan));
|
||||
writeSpi(0x000, chan == TxChannel::Tx1 ? 0x12 : 0x22);
|
||||
writeSpi(0x121, 0x00);
|
||||
const CalibPredis predis{ .bHigh = readSpi(0x145),
|
||||
.bLow = readSpi(0x146),
|
||||
.cHigh = readSpi(0x147),
|
||||
.cLow = readSpi(0x148),
|
||||
.dciHigh = readSpi(0x149),
|
||||
.dciLow = readSpi(0x14A),
|
||||
.dcqHigh = readSpi(0x14B),
|
||||
.dcqLow = readSpi(0x14C) };
|
||||
CalibPredis predis;
|
||||
predis.bHigh = readSpi(0x145);
|
||||
predis.bLow = readSpi(0x146);
|
||||
predis.cHigh = readSpi(0x147);
|
||||
predis.cLow = readSpi(0x148);
|
||||
predis.dciHigh = readSpi(0x149);
|
||||
predis.dciLow = readSpi(0x14A);
|
||||
predis.dcqHigh = readSpi(0x14B);
|
||||
predis.dcqLow = readSpi(0x14C);
|
||||
writeSpi(0x000, 02);
|
||||
return predis;
|
||||
}
|
||||
|
||||
void configFPGA(const Interface& interface)
|
||||
{
|
||||
setPin(33, 1);
|
||||
setPin(39, 1);
|
||||
setPin(40, 1);
|
||||
setPin(33, true);
|
||||
setPin(39, true);
|
||||
setPin(40, true);
|
||||
|
||||
setPin(32, 1);
|
||||
setPin(7, interface.ioMode == IOMode::LVDS_E ? 0 : 1);
|
||||
setPin(34, 1);
|
||||
setPin(34, 0);
|
||||
setPin(32, true);
|
||||
setPin(7, interface.ioMode == IOMode::CMOS ? 0 : 1);
|
||||
setPin(34, true);
|
||||
setPin(34, false);
|
||||
|
||||
setPin(38, interface.portMode == PortMode::Single);
|
||||
setPin(37, interface.trMode == TrMode::R2T2);
|
||||
setPin(36, interface.workMode != WorkMode::FDD);
|
||||
setPin(35, interface.workMode == WorkMode::Rx);
|
||||
|
||||
setPin(34, 1);
|
||||
setPin(34, 0);
|
||||
setPin(34, true);
|
||||
setPin(34, false);
|
||||
|
||||
setPin(43, 0);
|
||||
setPin(43, 1);
|
||||
setPin(43, false);
|
||||
setPin(43, true);
|
||||
}
|
||||
|
||||
void rxFFTCalib(const double lo, const double fs, const int firLength, const CX9261AConfiguration& config,
|
||||
@@ -2114,13 +2104,13 @@ void rxFFTCalib(const double lo, const double fs, const int firLength, const CX9
|
||||
writeSpi(0x77E, chan == RxChannel::Rx1 ? 0x50 : chan == RxChannel::Rx2 ? 0x0A : 0x03);
|
||||
writeSpi(0x09B, 0x01); // TXPLL4
|
||||
writeSpi(0x09D, firLength);
|
||||
writeSpi(0x096, (round(lo) >> 8) & 0xFF);
|
||||
writeSpi(0x097, round(lo) & 0xFF);
|
||||
writeSpi(0x096, (round32(lo) >> 8) & 0xFF);
|
||||
writeSpi(0x097, round32(lo) & 0xFF);
|
||||
const double ref = config.clock.ref * (config.clock.refDoubler ? 2 : 1);
|
||||
writeSpi(0x098, (round(ref * 10) >> 8) & 0xFF);
|
||||
writeSpi(0x099, round(ref * 10) & 0xFF);
|
||||
writeSpi(0x09E, (round(fs * 100) >> 8) & 0xFF);
|
||||
writeSpi(0x09F, round(fs * 100) & 0xFF);
|
||||
writeSpi(0x098, (round32(ref * 10) >> 8) & 0xFF);
|
||||
writeSpi(0x099, round32(ref * 10) & 0xFF);
|
||||
writeSpi(0x09E, (round32(fs * 100) >> 8) & 0xFF);
|
||||
writeSpi(0x09F, round32(fs * 100) & 0xFF);
|
||||
writeSpi(0x09C, static_cast<int>(chan));
|
||||
pause(qecDelay);
|
||||
while (true) {
|
||||
@@ -2161,8 +2151,8 @@ void txTSTPhaseDelay(const Clock& clock, const double lo, const double fs, const
|
||||
writeSpi(0x18C, 0x00);
|
||||
writeSpi(chan == TxChannel::Tx1 ? 0x763 : 0x76D, 0x14);
|
||||
writeSpi(0x095, 0x00);
|
||||
writeSpi(0x096, (round(lo) >> 8) & 0xFF);
|
||||
writeSpi(0x097, round(lo) & 0xFF);
|
||||
writeSpi(0x096, (round32(lo) >> 8) & 0xFF);
|
||||
writeSpi(0x097, round32(lo) & 0xFF);
|
||||
writeSpi(0x09C, chan == TxChannel::Tx1 ? 6 : 7);
|
||||
pause(qecDelay);
|
||||
while (true) {
|
||||
|
||||
@@ -28,13 +28,13 @@ void logging(const std::string& msg);
|
||||
* @param address 要写入的寄存器地址
|
||||
* @param value 要写入的寄存器值
|
||||
*/
|
||||
void writeSpi(int address, int value);
|
||||
void writeSpi(std::uint16_t address, std::uint8_t value);
|
||||
/**
|
||||
* @brief 需要实现的函数,实现SPI读取寄存器功能
|
||||
* @param address 要读取的寄存器地址
|
||||
* @return 返回的寄存器值
|
||||
*/
|
||||
int readSpi(int address);
|
||||
std::uint8_t readSpi(std::uint16_t address);
|
||||
/**
|
||||
* @brief 需要实现的函数,实现等待功能
|
||||
* @param ms 等待时间,单位毫秒
|
||||
@@ -45,7 +45,7 @@ void pause(double ms);
|
||||
* @param pin 寄存器地址
|
||||
* @param value 寄存器值
|
||||
*/
|
||||
void setPin(int pin, int value);
|
||||
void setPin(std::uint32_t pin, bool value);
|
||||
/**
|
||||
* @brief 初始化芯片状态,写入与具体配置无关的寄存器值
|
||||
*/
|
||||
|
||||
+6
-2
@@ -5,10 +5,10 @@
|
||||
#ifndef CX9261ADRIVER_DEFS_H
|
||||
#define CX9261ADRIVER_DEFS_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <bitset>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <cstdint>
|
||||
|
||||
#ifdef interface
|
||||
# undef interface
|
||||
@@ -119,9 +119,13 @@ enum class CalibMethod : std::uint8_t { TST = 0, Bisec, MultiPoints, Tracking };
|
||||
*/
|
||||
enum class DCCalibMethod : std::uint8_t { Tracking = 0, HighPass };
|
||||
/**
|
||||
* @brief AFC等待延时,单位ms
|
||||
* @brief 等待延时,单位ms
|
||||
*/
|
||||
constexpr double delay = 100;
|
||||
/**
|
||||
* @brief AFC等待延时,单位ms
|
||||
*/
|
||||
constexpr double afcDelay = 25e-3; // 25us
|
||||
/**
|
||||
* @brief QEC等待延时,单位ms
|
||||
*/
|
||||
|
||||
+48
-38
@@ -4,52 +4,62 @@
|
||||
|
||||
#ifndef CX9261ADRIVER_UTILS_H
|
||||
#define CX9261ADRIVER_UTILS_H
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#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);
|
||||
if (v < lo) return lo;
|
||||
if (v > hi) return hi;
|
||||
return v;
|
||||
}
|
||||
#else
|
||||
|
||||
template <typename Float>
|
||||
std::int32_t round32(Float f) {
|
||||
return static_cast<std::int32_t>(std::round(f));
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
std::int64_t round64(Float f) {
|
||||
return static_cast<std::int64_t>(std::round(f));
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
std::int32_t floor32(Float f) {
|
||||
return static_cast<std::int32_t>(std::floor(f));
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
std::int64_t floor64(Float f) {
|
||||
return static_cast<std::int64_t>(std::floor(f));
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
std::int32_t ceil32(Float f) {
|
||||
return static_cast<std::int32_t>(std::ceil(f));
|
||||
}
|
||||
|
||||
template <typename Float>
|
||||
std::int64_t ceil64(Float f) {
|
||||
return static_cast<std::int64_t>(std::ceil(f));
|
||||
}
|
||||
|
||||
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));
|
||||
size_t search_first_ge(const std::vector<T>& arr, const T& value) {
|
||||
size_t ret = arr.size(); // 如果搜索失败默认返回数组长度
|
||||
for (size_t i = 0; i < arr.size(); ++i) {
|
||||
if (arr[i] >= value) {
|
||||
// 找到更小的元素时更新下标
|
||||
if (ret == arr.size() || arr[i] < arr[ret]) {
|
||||
ret = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
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类,提供方便的位操作函数
|
||||
*/
|
||||
@@ -63,7 +73,7 @@ public:
|
||||
/**
|
||||
* 以十进制返回寄存器值
|
||||
*/
|
||||
unsigned char value() const { return static_cast<unsigned char>(m_value.to_ulong()); }
|
||||
std::uint8_t value() const { return static_cast<std::uint8_t>(m_value.to_ulong()); }
|
||||
/**
|
||||
* 对寄存器值进行部分值的替换操作
|
||||
* 例:replace(7, 4, 0b1111); 使寄存器的高四位为1
|
||||
@@ -71,7 +81,7 @@ public:
|
||||
* @param end 中止位
|
||||
* @param after 要替换的值
|
||||
*/
|
||||
void replace(const unsigned int start, const unsigned int end, unsigned char after) {
|
||||
void replace(const std::uint8_t start, const std::uint8_t end, std::uint8_t after) {
|
||||
for (auto i = end; i <= start; ++i) {
|
||||
m_value[i] = (after >> (i - end)) & 0b1;
|
||||
}
|
||||
|
||||
+3
-3
@@ -520,14 +520,14 @@ void CX9261A::logging(const std::string& msg) {
|
||||
}
|
||||
#endif
|
||||
|
||||
void CX9261A::writeSpi(int address, int value) {
|
||||
void CX9261A::writeSpi(std::uint16_t address, std::uint8_t value) {
|
||||
if(writeSpiFunc == NULL) {
|
||||
exit(-1);
|
||||
}
|
||||
return writeSpiFunc(address, value);
|
||||
}
|
||||
|
||||
int CX9261A::readSpi(int address) {
|
||||
std::uint8_t CX9261A::readSpi(std::uint16_t address) {
|
||||
if(readSpiFunc == NULL) {
|
||||
exit(-1);
|
||||
}
|
||||
@@ -541,7 +541,7 @@ void CX9261A::pause(double ms) {
|
||||
return pauseFunc(ms);
|
||||
}
|
||||
|
||||
void CX9261A::setPin(int pin, int value) {
|
||||
void CX9261A::setPin(std::uint32_t pin, bool value) {
|
||||
if(setPinFunc == NULL) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
+7
-7
@@ -450,10 +450,10 @@ typedef struct {
|
||||
|
||||
// 定义函数指针类型
|
||||
typedef void (*CX9261A_LoggingFunc)(const char* msg);
|
||||
typedef void (*CX9261A_WriteSpiFunc)(int address, int value);
|
||||
typedef int (*CX9261A_ReadSpiFunc)(int address);
|
||||
typedef void (*CX9261A_WriteSpiFunc)(uint16_t address, uint8_t value);
|
||||
typedef int (*CX9261A_ReadSpiFunc)(uint16_t address);
|
||||
typedef void (*CX9261A_SetPinFunc)(uint32_t pin, bool value);
|
||||
typedef void (*CX9261A_PauseFunc)(double ms);
|
||||
typedef void (*CX9261A_SetPinFunc)(int pin, int value);
|
||||
|
||||
/**
|
||||
* @brief 绑定日志函数
|
||||
@@ -698,14 +698,14 @@ CX9261A_CalibPredis CX9261A_readRxCalibPredis(CX9261A_RxChannel chan);
|
||||
* @param chan 接收通道
|
||||
* @param pll 使用的PLL
|
||||
*/
|
||||
void CX9261A_saveRxCalibPredis(unsigned char index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
void CX9261A_saveRxCalibPredis(uint8_t 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);
|
||||
void CX9261A_loadRxCalibPredis(uint8_t index, CX9261A_RxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Rx窄带多点校准
|
||||
* @param config CX9261A配置结构体
|
||||
@@ -758,14 +758,14 @@ void CX9261A_txCalib(const CX9261A_CX9261AConfiguration *config);
|
||||
* @param chan 发射通道
|
||||
* @param pll pll
|
||||
*/
|
||||
void CX9261A_saveTxCalibPredis(unsigned char index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
void CX9261A_saveTxCalibPredis(uint8_t 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);
|
||||
void CX9261A_loadTxCalibPredis(uint8_t index, CX9261A_TxChannel chan, CX9261A_LoSource pll);
|
||||
/**
|
||||
* @brief Qec校准顶层函数,内部根据配置选择使用对应方法进行校准
|
||||
* @param config CX9261A配置结构体
|
||||
|
||||
Reference in New Issue
Block a user