diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8191e986..c22083de4 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -57,9 +57,9 @@ set(LIME_SUITE_SOURCES memory/MemoryPool.cpp mcu_program/spi.cpp - mcu_program/common_src/lms7002m_calibrations.cpp - mcu_program/common_src/lms7002m_controls.cpp - mcu_program/common_src/lms7002m_filters.cpp + mcu_program/common_src/lms7002m_calibrations.c + mcu_program/common_src/lms7002m_controls.c + mcu_program/common_src/lms7002m_filters.c API/LMS_APIWrapper.cpp @@ -68,6 +68,12 @@ set(LIME_SUITE_SOURCES include/limesuite/SDRDevice.cpp ) +SET_SOURCE_FILES_PROPERTIES( + mcu_program/common_src/lms7002m_calibrations.c + mcu_program/common_src/lms7002m_controls.c + mcu_program/common_src/lms7002m_filters.c + PROPERTIES LANGUAGE CXX) + set(LIME_SUITE_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/include diff --git a/src/gnuPlotPipe.h b/src/gnuPlotPipe.h index 8a32fc5a4..4a417aeed 100644 --- a/src/gnuPlotPipe.h +++ b/src/gnuPlotPipe.h @@ -1,8 +1,8 @@ #ifndef GNUPLOT_PIPE_H #define GNUPLOT_PIPE_H -#include -#include +#include +#include /// @brief A class to pipe data into GNUPlot class GNUPlotPipe diff --git a/src/mcu_program/common_src/lms7002m_calibrations.cpp b/src/mcu_program/common_src/lms7002m_calibrations.c similarity index 95% rename from src/mcu_program/common_src/lms7002m_calibrations.cpp rename to src/mcu_program/common_src/lms7002m_calibrations.c index ad797e142..6b44e4e41 100644 --- a/src/mcu_program/common_src/lms7002m_calibrations.cpp +++ b/src/mcu_program/common_src/lms7002m_calibrations.c @@ -2,32 +2,32 @@ #include "LMS7002M_parameters_compact.h" #include "spi.h" #include "lms7002m_controls.h" -#include +#include #include "mcu_defines.h" +#include #define ENABLE_EXTERNAL_LOOPBACK 1 -#include +#ifdef __cplusplus //#define VERBOSE 1 //#define DRAW_GNU_PLOTS -#include -#include -#include -#include -#include -#include + #include + #include + #include + #include + #include -#ifdef DRAW_GNU_PLOTS - #define PUSH_GMEASUREMENT_VALUES(value, rssi) gMeasurements.push_back({ value, rssi }) + #ifdef DRAW_GNU_PLOTS + #define PUSH_GMEASUREMENT_VALUES(value, rssi) gMeasurements.push_back({ value, rssi }) GNUPlotPipe saturationPlot; GNUPlotPipe IQImbalancePlot; GNUPlotPipe txDCPlot; -#else - #define PUSH_GMEASUREMENT_VALUES(value, rssi) -#endif -#include + #else + #define PUSH_GMEASUREMENT_VALUES(value, rssi) + #endif + #include typedef std::vector> MeasurementsVector; MeasurementsVector gMeasurements; @@ -51,13 +51,21 @@ void DrawMeasurement(GNUPlotPipe& gp, const MeasurementsVector& vec) gp.write("e\n"); } +extern "C" { +#else + #define VERBOSE 0 + #define PUSH_GMEASUREMENT_VALUES(value, rssi) + + #include "lms7002_regx51.h" //MCU timer sfr +#endif // __cplusplus + ///APPROXIMATE conversion float ChipRSSI_2_dBFS(uint32_t rssi) { uint32_t maxRSSI = 0x15FF4; if (rssi == 0) rssi = 1; - return 20 * log10(static_cast(rssi) / maxRSSI); + return 20 * log10((float)(rssi) / maxRSSI); } int16_t toSigned(int16_t val, uint8_t msblsb) @@ -78,6 +86,15 @@ uint16_t RSSIDelayCounter = 1; // MCU timer delay between RSSI measurements // [1:0] SEL_PATH_RFE, when calibrating Tx uint8_t extLoopbackPair = 0; +int16_t clamp(int16_t value, int16_t minBound, int16_t maxBound) +{ + if (value < minBound) + return minBound; + if (value > maxBound) + return maxBound; + return value; +} + static void FlipRisingEdge(const uint16_t addr, const uint8_t bits) { Modify_SPI_Reg_bits(addr, bits, 0); @@ -110,7 +127,7 @@ void UpdateRSSIDelay() decimation = 1; //bypass { float waitTime = sampleCount / ((GetReferenceClk_TSP_MHz(false) / 2) / decimation); - RSSIDelayCounter = (0xFFFF) - static_cast(waitTime * RefClk / 12); + RSSIDelayCounter = (0xFFFF) - (uint16_t)(waitTime * RefClk / 12); } } @@ -233,7 +250,7 @@ int CheckSaturationTxRx(bool extLoopback) Modify_SPI_Reg_bits(CMIX_BYP_RXTSP, 0); SetNCOFrequency(LMS7002M_Rx, calibrationSXOffset_Hz - offsetNCO + (bandwidthRF / calibUserBwDivider) * 2, 0); - g_pga = static_cast(Get_SPI_Reg_bits(G_PGA_RBB)); + g_pga = (uint8_t)Get_SPI_Reg_bits(G_PGA_RBB); #if ENABLE_EXTERNAL_LOOPBACK if (extLoopback) { @@ -242,7 +259,7 @@ int CheckSaturationTxRx(bool extLoopback) } else #endif - g_rfe = static_cast(Get_SPI_Reg_bits(G_RXLOOPB_RFE)); + g_rfe = (uint8_t)Get_SPI_Reg_bits(G_RXLOOPB_RFE); rssi = GetRSSI(); PUSH_GMEASUREMENT_VALUES(index, ChipRSSI_2_dBFS(rssi)); @@ -281,7 +298,7 @@ int CheckSaturationTxRx(bool extLoopback) break; Modify_SPI_Reg_bits(G_PGA_RBB, g_pga); rssi = GetRSSI(); - if (static_cast(rssi) / rssi_prev < 1.05) // pga should give ~1dB change + if ((float)rssi / rssi_prev < 1.05) // pga should give ~1dB change break; rssi_prev = rssi; PUSH_GMEASUREMENT_VALUES(++index, ChipRSSI_2_dBFS(rssi)); @@ -438,12 +455,12 @@ void AdjustAutoDC(const uint16_t address, bool tx) minValue = initVal = ReadAnalogDC(address); minRSSI = rssi = GetRSSI(); - WriteAnalogDC(address, std::clamp(initVal + 1, -range, range)); + WriteAnalogDC(address, clamp(initVal + 1, -range, range)); valChange = GetRSSI() < rssi ? 1 : -1; for (i = 8; i; --i) { - initVal = std::clamp(initVal + valChange, -range, range); + initVal = clamp(initVal + valChange, -range, range); WriteAnalogDC(address, initVal); rssi = GetRSSI(); if (rssi < minRSSI) @@ -563,10 +580,10 @@ void CalibrateTxDCAuto() qparams.result = 0; //ReadAnalogDC(qparams.param.address); for (i = 0; i < 3; ++i) { - iparams.minValue = std::clamp(iparams.result - offset[i], -1024, 1023); - iparams.maxValue = std::clamp(iparams.result + offset[i], -1024, 1023); - qparams.minValue = std::clamp(qparams.result - offset[i], -1024, 1023); - qparams.maxValue = std::clamp(qparams.result + offset[i], -1024, 1023); + iparams.minValue = clamp(iparams.result - offset[i], -1024, 1023); + iparams.maxValue = clamp(iparams.result + offset[i], -1024, 1023); + qparams.minValue = clamp(qparams.result - offset[i], -1024, 1023); + qparams.maxValue = clamp(qparams.result + offset[i], -1024, 1023); TxDcBinarySearch(&iparams); #ifdef DRAW_GNU_PLOTS @@ -711,8 +728,10 @@ void CalibrateIQImbalance(bool tx) uint8_t SetupCGEN() { - uint8_t cgenMultiplier = std::clamp(std::round(GetFrequencyCGEN() / 46.08e6), 2, 13); - uint8_t gfir3n = 4 * cgenMultiplier; + uint8_t cgenMultiplier; + uint8_t gfir3n; + cgenMultiplier = clamp((GetFrequencyCGEN() / 46.08e6) + 0.5, 2, 13); + gfir3n = 4 * cgenMultiplier; if (Get_SPI_Reg_bits(EN_ADCCLKH_CLKGN) == 1) gfir3n /= pow2(Get_SPI_Reg_bits(CLKH_OV_CLKL_CGEN)); @@ -911,7 +930,7 @@ uint8_t CalibrateTxSetup(bool extLoopback) LoadDC_REG_TX_IQ(); SetNCOFrequency(LMS7002M_Tx, bandwidthRF / calibUserBwDivider, 0); { - const uint8_t sel_band1_2_trf = static_cast(Get_SPI_Reg_bits(0x0103, MSB_LSB(11, 10))); + const uint8_t sel_band1_2_trf = (uint8_t)Get_SPI_Reg_bits(0x0103, MSB_LSB(11, 10)); #if ENABLE_EXTERNAL_LOOPBACK if (extLoopback) { @@ -962,11 +981,10 @@ uint8_t CalibrateTxSetup(bool extLoopback) uint8_t CalibrateTx(bool extLoopback) { const uint16_t x0020val = SPI_read(0x0020); -#ifdef VERBOSE +#if defined(VERBOSE) && defined(__cplusplus) auto beginTime = std::chrono::high_resolution_clock::now(); #endif #if VERBOSE - uint8_t sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(SEL_BAND1_TRF); printf("Tx ch.%s , BW: %g MHz, RF output: %s, Gain: %i, loopb: %s\n", (x0020val & 3) == 0x1 ? "A" : "B", @@ -1301,7 +1319,7 @@ uint8_t CheckSaturationRx(const float_type bandwidth_Hz, bool extLoopback) { ROM const uint16_t target_rssi = 0x07000; //0x0B000 = -3 dBFS uint16_t rssi; - uint8_t cg_iamp = static_cast(Get_SPI_Reg_bits(CG_IAMP_TBB)); + uint8_t cg_iamp = (uint8_t)Get_SPI_Reg_bits(CG_IAMP_TBB); #ifdef DRAW_GNU_PLOTS int index = 0; GNUPlotPipe& gp = saturationPlot; @@ -1416,7 +1434,7 @@ uint8_t CheckSaturationRx(const float_type bandwidth_Hz, bool extLoopback) uint8_t CalibrateRx(bool extLoopback, bool dcOnly) { -#ifdef VERBOSE +#if defined(VERBOSE) && defined(__cplusplus) auto beginTime = std::chrono::high_resolution_clock::now(); #endif uint8_t status; @@ -1467,7 +1485,7 @@ uint8_t CalibrateRx(bool extLoopback, bool dcOnly) goto RxCalibrationEndStage; if (!extLoopback) { - if (Get_SPI_Reg_bits(SEL_PATH_RFE) == 2) + if ((uint8_t)Get_SPI_Reg_bits(SEL_PATH_RFE) == 2) { Modify_SPI_Reg_bits(PD_RLOOPB_2_RFE, 0); Modify_SPI_Reg_bits(EN_INSHSW_LB2_RFE, 0); @@ -1540,3 +1558,7 @@ RxCalibrationEndStage : { #endif //LMS_VERBOSE_OUTPUT return MCU_NO_ERROR; } + +#ifdef __cplusplus +} // extern C +#endif diff --git a/src/mcu_program/common_src/lms7002m_calibrations.h b/src/mcu_program/common_src/lms7002m_calibrations.h index e2c426588..b2a7bbb52 100644 --- a/src/mcu_program/common_src/lms7002m_calibrations.h +++ b/src/mcu_program/common_src/lms7002m_calibrations.h @@ -1,13 +1,18 @@ #ifndef LMS7002M_CALIBRATIONS_H #define LMS7002M_CALIBRATIONS_H -#include "typedefs.h" +#ifdef __cplusplus namespace lime { class LMS7002M; } void SetupCalibrations(lime::LMS7002M* chip, double BW); +extern "C" { +#endif + +#include "typedefs.h" + int16_t ReadAnalogDC(const uint16_t addr); void UpdateRSSIDelay(); uint32_t GetRSSI(); @@ -20,4 +25,8 @@ void CalibrateRxDCAuto(); uint8_t RunAGC(uint32_t wantedRSSI); int16_t clamp(int16_t value, int16_t minBound, int16_t maxBound); +#ifdef __cplusplus +} +#endif + #endif diff --git a/src/mcu_program/common_src/lms7002m_controls.cpp b/src/mcu_program/common_src/lms7002m_controls.c similarity index 95% rename from src/mcu_program/common_src/lms7002m_controls.cpp rename to src/mcu_program/common_src/lms7002m_controls.c index 8e77b3eaf..00e8d9798 100644 --- a/src/mcu_program/common_src/lms7002m_controls.cpp +++ b/src/mcu_program/common_src/lms7002m_controls.c @@ -4,13 +4,15 @@ #include "math.h" #include "typedefs.h" #include "mcu_defines.h" +#include #ifdef __cplusplus - #include - #include -using namespace std; #include #include + #include +using namespace std; + +extern "C" { #else #include "lms7002_regx51.h" //MCU timer sfr uint16_t gComparatorDelayCounter = 0xFF00; // ~100us @ ref 30.72MHz @@ -95,88 +97,421 @@ void SaveChipState(bool wr) SPI_write(0x0020, ch); } +void SetDefaultsSX() +{ + ROM const uint16_t SXAddr[] = { 0x011C, 0x011D, 0x011E, 0x011F, 0x0121, 0x0122, 0x0123 }; + ROM const uint16_t SXdefVals[] = { 0xAD43, 0x0400, 0x0780, 0x3640, 0x3404, 0x033F, 0x067B }; + + uint8_t i; + for (i = sizeof(SXAddr) / sizeof(uint16_t); i; --i) + SPI_write(SXAddr[i - 1], SXdefVals[i - 1]); + //keep 0x0120[7:0]ICT_VCO bias value intact + Modify_SPI_Reg_bits(0x0120, MSB_LSB(15, 8), 0xB9FF); +} + +void ClockLogicResets() +{ + //MCLK2 toggle + uint16_t reg = SPI_read(0x002B); + SPI_write(0x002B, reg ^ (1 << 9)); + SPI_write(0x002B, reg); + + //TSP logic reset + reg = SPI_read(0x0020); + SPI_write(0x0020, reg & ~0xAA00); + SPI_write(0x0020, reg); +} + +float_type GetFrequencyCGEN() +{ + const float_type dMul = (RefClk / 2.0) / (Get_SPI_Reg_bits(DIV_OUTCH_CGEN) + 1); //DIV_OUTCH_CGEN + const uint16_t gINT = Get_SPI_Reg_bits(0x0088, MSB_LSB(13, 0)); //read whole register to reduce SPI transfers + const uint32_t gFRAC = ((uint32_t)(gINT & 0xF) << 16) | Get_SPI_Reg_bits(0x0087, MSB_LSB(15, 0)); + return dMul * (((gINT >> 4) + 1 + gFRAC / 1048576.0)); +} + +uint8_t SetFrequencyCGEN(float_type freq) +{ + float_type dFvco; + float_type intpart; + //VCO frequency selection according to F_CLKH + { + uint8_t iHdiv_high = (2.94e9 / 2 / freq) - 1; + uint8_t iHdiv_low = (1.93e9 / 2 / freq); + uint8_t iHdiv = (iHdiv_low + iHdiv_high) / 2; + dFvco = 2 * (iHdiv + 1) * freq; + Modify_SPI_Reg_bits(DIV_OUTCH_CGEN, iHdiv); + } + //Integer division + intpart = dFvco / RefClk; + Modify_SPI_Reg_bits(INT_SDM_CGEN, intpart - 1); //INT_SDM_CGEN + //Fractional division + { + const float_type dFrac = intpart - (uint32_t)(dFvco / RefClk); + const uint32_t gFRAC = (uint32_t)(dFrac * 1048576); + Modify_SPI_Reg_bits(0x0087, MSB_LSB(15, 0), gFRAC & 0xFFFF); //INT_SDM_CGEN[15:0] + Modify_SPI_Reg_bits(0x0088, MSB_LSB(3, 0), gFRAC >> 16); //INT_SDM_CGEN[19:16] + } + +#if VERBOSE + //printf("CGEN: Freq=%g MHz, VCO=%g GHz, INT=%i, FRAC=%i, DIV_OUTCH_CGEN=%i\n", freq/1e6, dFvco/1e9, gINT, gFRAC, iHdiv); +#endif // NDEBUG + if (TuneVCO(VCO_CGEN) != 0) + return MCU_CGEN_TUNE_FAILED; + return 0; +} + +float_type GetReferenceClk_TSP_MHz(bool tx) +{ + const float_type cgenFreq = GetFrequencyCGEN(); + const float_type clklfreq = cgenFreq / pow2(Get_SPI_Reg_bits(CLKH_OV_CLKL_CGEN)); + if (Get_SPI_Reg_bits(EN_ADCCLKH_CLKGN) == 0) + return tx ? clklfreq : cgenFreq / 4; + else + return tx ? cgenFreq : clklfreq / 4; +} + +void SetNCOFrequency(const bool tx, const float freq, uint8_t index) +{ + const uint16_t addr = (tx ? 0x0242 : 0x0442) + index * 2; + const uint32_t fcw = (uint32_t)((freq / GetReferenceClk_TSP_MHz(tx)) * 4294967296.0); + SPI_write(addr, (fcw >> 16)); //NCO frequency control word register MSB part. + SPI_write(addr + 1, fcw); //NCO frequency control word register LSB part. +} + +float_type GetFrequencySX(const bool Tx) +{ + const uint16_t ch = SPI_read(0x0020); //(uint8_t)Get_SPI_Reg_bits(MAC); //remember previously used channel + Modify_SPI_Reg_bits(MAC, Tx ? 2 : 1); // Rx mac = 1, Tx mac = 2 + { + const uint16_t gINT = Get_SPI_Reg_bits(0x011E, MSB_LSB(13, 0)); // read whole register to reduce SPI transfers + const uint32_t gFRAC = ((uint32_t)(gINT & 0xF) << 16) | SPI_read(0x011D); + const uint8_t enDiv2 = Get_SPI_Reg_bits(EN_DIV2_DIVPROG) + 1; + const uint8_t divLoch = Get_SPI_Reg_bits(DIV_LOCH) + 1; + SPI_write(0x0020, ch); + //Calculate real frequency according to the calculated parameters + return (enDiv2) * (RefClk / pow2(divLoch)) * ((gINT >> 4) + 4 + (gFRAC / 1048576.0)); + } +} + +uint8_t SetFrequencySX(const bool tx, const float_type freq_Hz) +{ + int16_t tuneScore[3] = { 255, 255, 255 }; // best is closest to 0 + const uint16_t macBck = SPI_read(0x0020); + bool canDeliverFrequency = false; + + Modify_SPI_Reg_bits(MAC, tx ? 2 : 1); + //find required VCO frequency + { + float_type VCOfreq; + float_type temp; + { + uint8_t div_loch; + for (div_loch = 7; div_loch; --div_loch) + { + VCOfreq = pow2(div_loch) * freq_Hz; + if ((VCOfreq >= 3800e6) && (VCOfreq <= 7714e6)) + break; + } + Modify_SPI_Reg_bits(DIV_LOCH, div_loch - 1); + } + { + uint32_t fractionalPart; + const uint8_t enDiv2 = (VCOfreq > 5500e6) ? 1 : 0; + Modify_SPI_Reg_bits(EN_DIV2_DIVPROG, enDiv2); //EN_DIV2_DIVPROG + temp = VCOfreq / (RefClk * (1 + enDiv2)); + fractionalPart = (uint32_t)((temp - (uint32_t)(temp)) * 1048576); + + Modify_SPI_Reg_bits(INT_SDM, (uint16_t)(temp - 4)); //INT_SDM + Modify_SPI_Reg_bits(0x011E, MSB_LSB(3, 0), (fractionalPart >> 16)); //FRAC_SDM[19:16] + SPI_write(0x011D, fractionalPart & 0xFFFF); //FRAC_SDM[15:0] + } + } + while (1) + { + uint8_t sel_vco; + uint8_t bestvco = 0; + for (sel_vco = 0; sel_vco < 3; ++sel_vco) + { + Modify_SPI_Reg_bits(SEL_VCO, sel_vco); + if (TuneVCO(1) == MCU_NO_ERROR) + { + tuneScore[sel_vco] = Get_SPI_Reg_bits(CSW_VCO) - 128; + canDeliverFrequency = true; + } + if (abs(tuneScore[sel_vco]) < abs(tuneScore[bestvco])) + bestvco = sel_vco; + } + if (canDeliverFrequency) + { + Modify_SPI_Reg_bits(SEL_VCO, bestvco); + Modify_SPI_Reg_bits(CSW_VCO, tuneScore[bestvco] + 128); + break; + } + { + uint16_t bias = Get_SPI_Reg_bits(ICT_VCO); + if (bias == 255) + break; + Modify_SPI_Reg_bits(ICT_VCO, bias + 32 > 255 ? 255 : bias + 32); + } + } + SPI_write(0x0020, macBck); + if (canDeliverFrequency == false) + return tx ? MCU_SXT_TUNE_FAILED : MCU_SXR_TUNE_FAILED; + return MCU_NO_ERROR; +} + +static uint8_t ReadCMP(const bool SX) +{ #ifdef __cplusplus - #include -void SetDefaults(uint16_t start, uint16_t end) + std::this_thread::sleep_for(std::chrono::microseconds(100)); +#else + TR0 = 0; //stop timer 0 + TH0 = (gComparatorDelayCounter >> 8); + TL0 = (gComparatorDelayCounter & 0xFF); + TF0 = 0; // clear overflow + TR0 = 1; //start timer 0 + while (!TF0) + ; // wait for timer overflow +#endif + return (uint8_t)(Get_SPI_Reg_bits(SX ? 0x0123 : 0x008C, MSB_LSB(13, 12))); +} + +uint8_t TuneVCO(bool SX) // 0-cgen, 1-SXR, 2-SXT { - ROM const uint16_t defaultAddrs[] = { 0x0020, - 0x0021, - 0x0022, - 0x0023, - 0x0024, - 0x0025, - 0x0026, - 0x0027, - 0x0028, - 0x0029, - 0x002A, - 0x002B, - 0x002C, - 0x002E, - 0x002F, - 0x0081, - 0x0082, - 0x0084, - 0x0085, - 0x0086, - 0x0087, - 0x0088, - 0x0089, - 0x008A, - 0x008B, - 0x008C, - 0x0092, - 0x0093, - 0x0094, - 0x0095, - 0x0096, - 0x0097, - 0x0098, - 0x0099, - 0x009A, - 0x009B, - 0x009C, - 0x009D, - 0x009E, - 0x009F, - 0x00A0, - 0x00A1, - 0x00A2, - 0x00A3, - 0x00A4, - 0x00A5, - 0x00A6, - 0x00A7, - 0x00A8, - 0x00AA, - 0x00AB, - 0x00AD, - 0x00AE, - 0x0100, - 0x0101, - 0x0102, - 0x0103, - 0x0104, - 0x0105, - 0x0106, - 0x0107, - 0x0108, - 0x0109, - 0x010A, - 0x010B, - 0x010C, - 0x010D, - 0x010E, - 0x010F, - 0x0110, - 0x0111, - 0x0112, - 0x0113, - 0x0114, - 0x0115, - 0x0116, - 0x0117, - 0x0118, + typedef struct { + uint8_t high; + uint8_t low; + uint8_t hasLock; + } CSWInteval; + + uint16_t addrCSW_VCO; + uint8_t msblsb; + + CSWInteval cswSearch[2]; + cswSearch[0].high = 0; //search interval lowest value + cswSearch[0].low = 127; + cswSearch[1].high = 128; + cswSearch[1].low = 255; + cswSearch[1].hasLock = cswSearch[0].hasLock = false; + + if (SX) + { + addrCSW_VCO = 0x0121; + msblsb = MSB_LSB(10, 3); //CSW msb lsb + //assuming the active channel is already correct + Modify_SPI_Reg_bits(0x011C, MSB_LSB(2, 1), 0); //activate VCO and comparator + } + else //CGEN + { + addrCSW_VCO = 0x008B; + msblsb = MSB_LSB(8, 1); //CSW msb lsb + Modify_SPI_Reg_bits(0x0086, MSB_LSB(2, 1), 0); //activate VCO and comparator + } +#ifndef __cplusplus + gComparatorDelayCounter = 0xFFFF - (uint16_t)((0.0009 / 12) * RefClk); // ~900us +#endif + //check if lock is within VCO range + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, 0); + if (ReadCMP(SX) == 3) //VCO too high + return MCU_ERROR; + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, 255); + if (ReadCMP(SX) == 0) //VCO too low + return MCU_ERROR; + + //search intervals [0-127][128-255] + { + uint8_t t; + for (t = 0; t < 2; ++t) + { + uint8_t mask; + for (mask = (1 << 6); mask; mask >>= 1) + { + uint8_t cmpValue; + cswSearch[t].high |= mask; // CSW_VCO=1 + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswSearch[t].high); + cmpValue = ReadCMP(SX); + if (cmpValue == 0x03) // reduce CSW + cswSearch[t].high ^= mask; // CSW_VCO=0 + else if (cmpValue == 0x02 && cswSearch[t].high <= cswSearch[t].low) + { + cswSearch[t].hasLock = true; + cswSearch[t].low = cswSearch[t].high; + } + } + for (; cswSearch[t].low; --cswSearch[t].low) + { + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswSearch[t].low); + if (ReadCMP(SX) != 0x2) + { + if (cswSearch[t].low < cswSearch[t].high) + ++cswSearch[t].low; + break; + } + } + } + } + { + uint8_t cswValue; + //compare which interval is wider + { + if (cswSearch[1].hasLock && (cswSearch[1].high - cswSearch[1].low >= cswSearch[0].high - cswSearch[0].low)) + cswValue = cswSearch[1].low + ((cswSearch[1].high - cswSearch[1].low) >> 1); + else + cswValue = cswSearch[0].low + ((cswSearch[0].high - cswSearch[0].low) >> 1); + } + + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswValue); + if (ReadCMP(SX) != 0x2) //just in case high-low==1, if low fails, check if high locks + Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, ++cswValue); + } + if (ReadCMP(SX) == 0x2) + return MCU_NO_ERROR; + return MCU_ERROR; +} + +void WriteMaskedRegs(const RegisterBatch ROM* regs) +{ + uint8_t i; + uint8_t index; + for (i = regs->cnt; i; --i) + { + index = i - 1; + SPI_write(regs->addr[index], (SPI_read(regs->addr[index]) & ~regs->mask[index]) | regs->val[index]); + } + for (i = regs->wrOnlyAddrCnt; i; --i) + { + index = i - 1; + SPI_write(regs->wrOnlyAddr[index], i > regs->wrOnlyDataCnt ? 0 : regs->wrOnlyData[index]); + } +} + +uint8_t GetValueOf_c_ctl_pga_rbb(uint8_t g_pga_rbb) +{ + if (g_pga_rbb < 21) + return 1; + if (g_pga_rbb < 13) + return 2; + if (g_pga_rbb < 8) + return 3; + return 0; +} + +void EnableChannelPowerControls() +{ + uint16_t afe = SPI_read(0x0082); + uint16_t value = SPI_read(0x0020); + if ((value & 3) == 1) + { + value = value | 0x0014; + afe &= ~0x14; + } + else + { + value = value | 0x0028; + afe &= ~0x0A; + } + SPI_write(0x0020, value); + SPI_write(0x0082, afe); +} + +void EnableMIMOBuffersIfNecessary() +{ + //modifications when calibrating channel B + uint16_t x0020val = SPI_read(0x0020); + if ((x0020val & 0x3) == 2) + { + Modify_SPI_Reg_bits(MAC, 1); + Modify_SPI_Reg_bits(EN_NEXTRX_RFE, 1); + Modify_SPI_Reg_bits(EN_NEXTTX_TRF, 1); + SPI_write(0x0020, x0020val); + } +} + +#ifdef __cplusplus +} // extern C +#endif + +void SetDefaults(uint16_t start, uint16_t end) +{ + ROM const uint16_t defaultAddrs[] = { 0x0020, + 0x0021, + 0x0022, + 0x0023, + 0x0024, + 0x0025, + 0x0026, + 0x0027, + 0x0028, + 0x0029, + 0x002A, + 0x002B, + 0x002C, + 0x002E, + 0x002F, + 0x0081, + 0x0082, + 0x0084, + 0x0085, + 0x0086, + 0x0087, + 0x0088, + 0x0089, + 0x008A, + 0x008B, + 0x008C, + 0x0092, + 0x0093, + 0x0094, + 0x0095, + 0x0096, + 0x0097, + 0x0098, + 0x0099, + 0x009A, + 0x009B, + 0x009C, + 0x009D, + 0x009E, + 0x009F, + 0x00A0, + 0x00A1, + 0x00A2, + 0x00A3, + 0x00A4, + 0x00A5, + 0x00A6, + 0x00A7, + 0x00A8, + 0x00AA, + 0x00AB, + 0x00AD, + 0x00AE, + 0x0100, + 0x0101, + 0x0102, + 0x0103, + 0x0104, + 0x0105, + 0x0106, + 0x0107, + 0x0108, + 0x0109, + 0x010A, + 0x010B, + 0x010C, + 0x010D, + 0x010E, + 0x010F, + 0x0110, + 0x0111, + 0x0112, + 0x0113, + 0x0114, + 0x0115, + 0x0116, + 0x0117, + 0x0118, 0x0119, 0x011A, 0x011C, @@ -509,7 +844,7 @@ void SetDefaults(uint16_t start, uint16_t end) 0x0000, 0x00A0, 0x1020 }; - #ifdef __cplusplus +#ifdef __cplusplus //int status = 0; std::vector addrs; std::vector values; @@ -527,338 +862,7 @@ void SetDefaults(uint16_t start, uint16_t end) } } SPI_write_batch(addrs.data(), values.data(), addrs.size()); - #else +#else - #endif -} #endif -void SetDefaultsSX() -{ - ROM const uint16_t SXAddr[] = { 0x011C, 0x011D, 0x011E, 0x011F, 0x0121, 0x0122, 0x0123 }; - ROM const uint16_t SXdefVals[] = { 0xAD43, 0x0400, 0x0780, 0x3640, 0x3404, 0x033F, 0x067B }; - - uint8_t i; - for (i = sizeof(SXAddr) / sizeof(uint16_t); i; --i) - SPI_write(SXAddr[i - 1], SXdefVals[i - 1]); - //keep 0x0120[7:0]ICT_VCO bias value intact - Modify_SPI_Reg_bits(0x0120, MSB_LSB(15, 8), 0xB9FF); -} - -void ClockLogicResets() -{ - //MCLK2 toggle - uint16_t reg = SPI_read(0x002B); - SPI_write(0x002B, reg ^ (1 << 9)); - SPI_write(0x002B, reg); - - //TSP logic reset - reg = SPI_read(0x0020); - SPI_write(0x0020, reg & ~0xAA00); - SPI_write(0x0020, reg); -} - -float_type GetFrequencyCGEN() -{ - const float_type dMul = (RefClk / 2.0) / (Get_SPI_Reg_bits(DIV_OUTCH_CGEN) + 1); //DIV_OUTCH_CGEN - const uint16_t gINT = Get_SPI_Reg_bits(0x0088, MSB_LSB(13, 0)); //read whole register to reduce SPI transfers - const uint32_t gFRAC = (static_cast(gINT & 0xF) << 16) | Get_SPI_Reg_bits(0x0087, MSB_LSB(15, 0)); - return dMul * (((gINT >> 4) + 1 + gFRAC / 1048576.0)); -} - -uint8_t SetFrequencyCGEN(float_type freq) -{ - float_type dFvco; - float_type intpart; - //VCO frequency selection according to F_CLKH - { - uint8_t iHdiv_high = (2.94e9 / 2 / freq) - 1; - uint8_t iHdiv_low = (1.93e9 / 2 / freq); - uint8_t iHdiv = (iHdiv_low + iHdiv_high) / 2; - dFvco = 2 * (iHdiv + 1) * freq; - Modify_SPI_Reg_bits(DIV_OUTCH_CGEN, iHdiv); - } - //Integer division - intpart = dFvco / RefClk; - Modify_SPI_Reg_bits(INT_SDM_CGEN, intpart - 1); //INT_SDM_CGEN - //Fractional division - { - const float_type dFrac = intpart - static_cast(dFvco / RefClk); - const uint32_t gFRAC = static_cast(dFrac * 1048576); - Modify_SPI_Reg_bits(0x0087, MSB_LSB(15, 0), gFRAC & 0xFFFF); //INT_SDM_CGEN[15:0] - Modify_SPI_Reg_bits(0x0088, MSB_LSB(3, 0), gFRAC >> 16); //INT_SDM_CGEN[19:16] - } - -#if VERBOSE - //printf("CGEN: Freq=%g MHz, VCO=%g GHz, INT=%i, FRAC=%i, DIV_OUTCH_CGEN=%i\n", freq/1e6, dFvco/1e9, gINT, gFRAC, iHdiv); -#endif // NDEBUG - if (TuneVCO(VCO_CGEN) != 0) - return MCU_CGEN_TUNE_FAILED; - return 0; -} - -float_type GetReferenceClk_TSP_MHz(bool tx) -{ - const float_type cgenFreq = GetFrequencyCGEN(); - const float_type clklfreq = cgenFreq / pow2(Get_SPI_Reg_bits(CLKH_OV_CLKL_CGEN)); - if (Get_SPI_Reg_bits(EN_ADCCLKH_CLKGN) == 0) - return tx ? clklfreq : cgenFreq / 4; - else - return tx ? cgenFreq : clklfreq / 4; -} - -void SetNCOFrequency(const bool tx, const float freq, uint8_t index) -{ - const uint16_t addr = (tx ? 0x0242 : 0x0442) + index * 2; - const uint32_t fcw = static_cast((freq / GetReferenceClk_TSP_MHz(tx)) * 4294967296.0); - SPI_write(addr, (fcw >> 16)); //NCO frequency control word register MSB part. - SPI_write(addr + 1, fcw); //NCO frequency control word register LSB part. -} - -float_type GetFrequencySX(const bool Tx) -{ - const uint16_t ch = SPI_read(0x0020); //(uint8_t)Get_SPI_Reg_bits(MAC); //remember previously used channel - Modify_SPI_Reg_bits(MAC, Tx ? 2 : 1); // Rx mac = 1, Tx mac = 2 - { - const uint16_t gINT = Get_SPI_Reg_bits(0x011E, MSB_LSB(13, 0)); // read whole register to reduce SPI transfers - const uint32_t gFRAC = (static_cast(gINT & 0xF) << 16) | SPI_read(0x011D); - const uint8_t enDiv2 = Get_SPI_Reg_bits(EN_DIV2_DIVPROG) + 1; - const uint8_t divLoch = Get_SPI_Reg_bits(DIV_LOCH) + 1; - SPI_write(0x0020, ch); - //Calculate real frequency according to the calculated parameters - return (enDiv2) * (RefClk / pow2(divLoch)) * ((gINT >> 4) + 4 + (gFRAC / 1048576.0)); - } -} - -uint8_t SetFrequencySX(const bool tx, const float_type freq_Hz) -{ - int16_t tuneScore[3] = { 255, 255, 255 }; // best is closest to 0 - const uint16_t macBck = SPI_read(0x0020); - bool canDeliverFrequency = false; - - Modify_SPI_Reg_bits(MAC, tx ? 2 : 1); - //find required VCO frequency - { - float_type VCOfreq; - float_type temp; - { - uint8_t div_loch; - for (div_loch = 7; div_loch; --div_loch) - { - VCOfreq = pow2(div_loch) * freq_Hz; - if ((VCOfreq >= 3800e6) && (VCOfreq <= 7714e6)) - break; - } - Modify_SPI_Reg_bits(DIV_LOCH, div_loch - 1); - } - { - uint32_t fractionalPart; - const uint8_t enDiv2 = (VCOfreq > 5500e6) ? 1 : 0; - Modify_SPI_Reg_bits(EN_DIV2_DIVPROG, enDiv2); //EN_DIV2_DIVPROG - temp = VCOfreq / (RefClk * (1 + enDiv2)); - fractionalPart = static_cast((temp - static_cast(temp)) * 1048576); - - Modify_SPI_Reg_bits(INT_SDM, static_cast(temp - 4)); //INT_SDM - Modify_SPI_Reg_bits(0x011E, MSB_LSB(3, 0), (fractionalPart >> 16)); //FRAC_SDM[19:16] - SPI_write(0x011D, fractionalPart & 0xFFFF); //FRAC_SDM[15:0] - } - } - while (1) - { - uint8_t sel_vco; - uint8_t bestvco = 0; - for (sel_vco = 0; sel_vco < 3; ++sel_vco) - { - Modify_SPI_Reg_bits(SEL_VCO, sel_vco); - if (TuneVCO(1) == MCU_NO_ERROR) - { - tuneScore[sel_vco] = Get_SPI_Reg_bits(CSW_VCO) - 128; - canDeliverFrequency = true; - } - if (abs(tuneScore[sel_vco]) < abs(tuneScore[bestvco])) - bestvco = sel_vco; - } - if (canDeliverFrequency) - { - Modify_SPI_Reg_bits(SEL_VCO, bestvco); - Modify_SPI_Reg_bits(CSW_VCO, tuneScore[bestvco] + 128); - break; - } - { - uint16_t bias = Get_SPI_Reg_bits(ICT_VCO); - if (bias == 255) - break; - Modify_SPI_Reg_bits(ICT_VCO, bias + 32 > 255 ? 255 : bias + 32); - } - } - SPI_write(0x0020, macBck); - if (canDeliverFrequency == false) - return tx ? MCU_SXT_TUNE_FAILED : MCU_SXR_TUNE_FAILED; - return MCU_NO_ERROR; -} - -static uint8_t ReadCMP(const bool SX) -{ -#ifdef __cplusplus - std::this_thread::sleep_for(std::chrono::microseconds(100)); -#else - TR0 = 0; //stop timer 0 - TH0 = (gComparatorDelayCounter >> 8); - TL0 = (gComparatorDelayCounter & 0xFF); - TF0 = 0; // clear overflow - TR0 = 1; //start timer 0 - while (!TF0) - ; // wait for timer overflow -#endif - return static_cast(Get_SPI_Reg_bits(SX ? 0x0123 : 0x008C, MSB_LSB(13, 12))); -} - -uint8_t TuneVCO(bool SX) // 0-cgen, 1-SXR, 2-SXT -{ - typedef struct { - uint8_t high; - uint8_t low; - uint8_t hasLock; - } CSWInteval; - - uint16_t addrCSW_VCO; - uint8_t msblsb; - - CSWInteval cswSearch[2]; - cswSearch[0].high = 0; //search interval lowest value - cswSearch[0].low = 127; - cswSearch[1].high = 128; - cswSearch[1].low = 255; - cswSearch[1].hasLock = cswSearch[0].hasLock = false; - - if (SX) - { - addrCSW_VCO = 0x0121; - msblsb = MSB_LSB(10, 3); //CSW msb lsb - //assuming the active channel is already correct - Modify_SPI_Reg_bits(0x011C, MSB_LSB(2, 1), 0); //activate VCO and comparator - } - else //CGEN - { - addrCSW_VCO = 0x008B; - msblsb = MSB_LSB(8, 1); //CSW msb lsb - Modify_SPI_Reg_bits(0x0086, MSB_LSB(2, 1), 0); //activate VCO and comparator - } -#ifndef __cplusplus - gComparatorDelayCounter = 0xFFFF - (uint16_t)((0.0009 / 12) * RefClk); // ~900us -#endif - //check if lock is within VCO range - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, 0); - if (ReadCMP(SX) == 3) //VCO too high - return MCU_ERROR; - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, 255); - if (ReadCMP(SX) == 0) //VCO too low - return MCU_ERROR; - - //search intervals [0-127][128-255] - { - uint8_t t; - for (t = 0; t < 2; ++t) - { - uint8_t mask; - for (mask = (1 << 6); mask; mask >>= 1) - { - uint8_t cmpValue; - cswSearch[t].high |= mask; // CSW_VCO=1 - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswSearch[t].high); - cmpValue = ReadCMP(SX); - if (cmpValue == 0x03) // reduce CSW - cswSearch[t].high ^= mask; // CSW_VCO=0 - else if (cmpValue == 0x02 && cswSearch[t].high <= cswSearch[t].low) - { - cswSearch[t].hasLock = true; - cswSearch[t].low = cswSearch[t].high; - } - } - for (; cswSearch[t].low; --cswSearch[t].low) - { - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswSearch[t].low); - if (ReadCMP(SX) != 0x2) - { - if (cswSearch[t].low < cswSearch[t].high) - ++cswSearch[t].low; - break; - } - } - } - } - { - uint8_t cswValue; - //compare which interval is wider - { - if (cswSearch[1].hasLock && (cswSearch[1].high - cswSearch[1].low >= cswSearch[0].high - cswSearch[0].low)) - cswValue = cswSearch[1].low + ((cswSearch[1].high - cswSearch[1].low) >> 1); - else - cswValue = cswSearch[0].low + ((cswSearch[0].high - cswSearch[0].low) >> 1); - } - - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, cswValue); - if (ReadCMP(SX) != 0x2) //just in case high-low==1, if low fails, check if high locks - Modify_SPI_Reg_bits(addrCSW_VCO, msblsb, ++cswValue); - } - if (ReadCMP(SX) == 0x2) - return MCU_NO_ERROR; - return MCU_ERROR; -} - -void WriteMaskedRegs(const RegisterBatch ROM* regs) -{ - uint8_t i; - uint8_t index; - for (i = regs->cnt; i; --i) - { - index = i - 1; - SPI_write(regs->addr[index], (SPI_read(regs->addr[index]) & ~regs->mask[index]) | regs->val[index]); - } - for (i = regs->wrOnlyAddrCnt; i; --i) - { - index = i - 1; - SPI_write(regs->wrOnlyAddr[index], i > regs->wrOnlyDataCnt ? 0 : regs->wrOnlyData[index]); - } -} - -uint8_t GetValueOf_c_ctl_pga_rbb(uint8_t g_pga_rbb) -{ - if (g_pga_rbb < 21) - return 1; - if (g_pga_rbb < 13) - return 2; - if (g_pga_rbb < 8) - return 3; - return 0; -} - -void EnableChannelPowerControls() -{ - uint16_t afe = SPI_read(0x0082); - uint16_t value = SPI_read(0x0020); - if ((value & 3) == 1) - { - value = value | 0x0014; - afe &= ~0x14; - } - else - { - value = value | 0x0028; - afe &= ~0x0A; - } - SPI_write(0x0020, value); - SPI_write(0x0082, afe); -} - -void EnableMIMOBuffersIfNecessary() -{ - //modifications when calibrating channel B - uint16_t x0020val = SPI_read(0x0020); - if ((x0020val & 0x3) == 2) - { - Modify_SPI_Reg_bits(MAC, 1); - Modify_SPI_Reg_bits(EN_NEXTRX_RFE, 1); - Modify_SPI_Reg_bits(EN_NEXTTX_TRF, 1); - SPI_write(0x0020, x0020val); - } } diff --git a/src/mcu_program/common_src/lms7002m_filters.cpp b/src/mcu_program/common_src/lms7002m_filters.c similarity index 93% rename from src/mcu_program/common_src/lms7002m_filters.cpp rename to src/mcu_program/common_src/lms7002m_filters.c index 74cf002fa..0510aa2da 100644 --- a/src/mcu_program/common_src/lms7002m_filters.cpp +++ b/src/mcu_program/common_src/lms7002m_filters.c @@ -3,9 +3,12 @@ #include "lms7002m_filters.h" #include "LMS7002M_parameters_compact.h" #include "spi.h" -#include +#include #include "mcu_defines.h" -#include + +#ifdef __cplusplus +extern "C" { +#endif enum { SEARCH_SUCCESS = 0, SEARCH_NEED_TO_DECREASE, SEARCH_NEED_TO_INCREASE }; @@ -21,7 +24,7 @@ static ROM const float_type TxLPF_RF_LimitHigh = 130e6; static uint8_t ConfigCGEN_ForLPF_IF(float IF_Hz) { - uint8_t cgenMultiplier = std::clamp(std::round(IF_Hz * 20 / 46.08e6), 2, 13); + uint8_t cgenMultiplier = clamp(round(IF_Hz * 20 / 46.08e6), 2, 13); return SetFrequencyCGEN(46.08e6 * cgenMultiplier + 10e6); } @@ -38,7 +41,7 @@ static uint8_t RxFilterSearch(const uint16_t addr, const uint8_t msblsb, const u value -= stepSize; else value += stepSize; - value = std::clamp(value, 0, maxValue); + value = clamp(value, 0, maxValue); Modify_SPI_Reg_bits(addr, msblsb, value); if (doDecrement != (GetRSSI() < rssi_3dB)) break; @@ -52,7 +55,7 @@ static uint8_t RxFilterSearch(const uint16_t addr, const uint8_t msblsb, const u value += stepSize; else value -= stepSize; - value = std::clamp(value, 0, maxValue); + value = clamp(value, 0, maxValue); Modify_SPI_Reg_bits(addr, msblsb, value); } return 0; @@ -303,19 +306,19 @@ uint8_t TuneRxFilterSetup(const float_type rx_lpf_IF) int8_t ccomp_tia_rfe; if (g_tia_rfe > 1) { - cfb_tia_rfe = static_cast(1680e6 / rx_lpf_IF - 10); + cfb_tia_rfe = (int16_t)(1680e6 / rx_lpf_IF - 10); ccomp_tia_rfe = cfb_tia_rfe / 100; } else if (g_tia_rfe == 1) { - cfb_tia_rfe = static_cast(5400e6 / rx_lpf_IF - 15); + cfb_tia_rfe = (int16_t)(5400e6 / rx_lpf_IF - 15); ccomp_tia_rfe = cfb_tia_rfe / 100 + 1; } else return MCU_RX_INVALID_TIA; - SPI_write(0x0112, (std::clamp(ccomp_tia_rfe, 0, 15) << 8) | std::clamp(cfb_tia_rfe, 0, 4095)); + SPI_write(0x0112, (clamp(ccomp_tia_rfe, 0, 15) << 8) | clamp(cfb_tia_rfe, 0, 4095)); - Modify_SPI_Reg_bits(RCOMP_TIA_RFE, std::clamp(15 - cfb_tia_rfe / 100, 0, 15)); + Modify_SPI_Reg_bits(RCOMP_TIA_RFE, clamp(15 - cfb_tia_rfe / 100, 0, 15)); } { const int8_t rcc_ctl_pga_rbb = (430 * pow(0.65, g_pga_rbb / 10) - 110.35) / 20.45 + 16; @@ -328,7 +331,7 @@ uint8_t TuneRxFilterSetup(const float_type rx_lpf_IF) Modify_SPI_Reg_bits(INPUT_CTL_PGA_RBB, 0); { const float freqIF = rx_lpf_IF * 1.3; - int16_t c_ctl_lpfl_rbb = std::clamp(2160e6 / freqIF - 103, 0, 2047); + int16_t c_ctl_lpfl_rbb = clamp(2160e6 / freqIF - 103, 0, 2047); uint8_t rcc_ctl_lpfl_rbb = 5; if (freqIF < 15e6) @@ -350,8 +353,8 @@ uint8_t TuneRxFilterSetup(const float_type rx_lpf_IF) Modify_SPI_Reg_bits(INPUT_CTL_PGA_RBB, 1); { const float lpfIF_adjusted = rx_lpf_IF * 1.3; - uint8_t c_ctl_lpfh_rbb = std::clamp(6000e6 / lpfIF_adjusted - 50, 0, 255); - uint8_t rcc_ctl_lpfh_rbb = std::clamp(lpfIF_adjusted / 10e6 - 3, 0, 7); + uint8_t c_ctl_lpfh_rbb = clamp(6000e6 / lpfIF_adjusted - 50, 0, 255); + uint8_t rcc_ctl_lpfh_rbb = clamp(lpfIF_adjusted / 10e6 - 3, 0, 7); Modify_SPI_Reg_bits(0x0116, MSB_LSB(10, 0), (rcc_ctl_lpfh_rbb << 8) | c_ctl_lpfh_rbb); } } @@ -467,24 +470,24 @@ uint8_t TuneRxFilter(const float_type rx_lpf_freq_RF) uint16_t cfb_tia_rfe; uint8_t g_tia_rfe = Get_SPI_Reg_bits(G_TIA_RFE); if (g_tia_rfe == 3 || g_tia_rfe == 2) - cfb_tia_rfe = static_cast(1680e6 / (rx_lpf_IF * 0.72) - 10); + cfb_tia_rfe = (int)(1680e6 / (rx_lpf_IF * 0.72) - 10); else if (g_tia_rfe == 1) - cfb_tia_rfe = static_cast(5400e6 / (rx_lpf_IF * 0.72) - 15); + cfb_tia_rfe = (int)(5400e6 / (rx_lpf_IF * 0.72) - 15); else { status = MCU_RX_INVALID_TIA; goto RxFilterSearchEndStage; } - cfb_tia_rfe = std::clamp(cfb_tia_rfe, 0, 4095); + cfb_tia_rfe = clamp(cfb_tia_rfe, 0, 4095); Modify_SPI_Reg_bits(CFB_TIA_RFE, cfb_tia_rfe); { uint8_t ccomp_tia_rfe = cfb_tia_rfe / 100; if (g_tia_rfe == 1) ccomp_tia_rfe += 1; - Modify_SPI_Reg_bits(CCOMP_TIA_RFE, std::clamp(ccomp_tia_rfe, 0, 15)); + Modify_SPI_Reg_bits(CCOMP_TIA_RFE, clamp(ccomp_tia_rfe, 0, 15)); } - Modify_SPI_Reg_bits(RCOMP_TIA_RFE, std::clamp(15 - cfb_tia_rfe / 100, 0, 15)); + Modify_SPI_Reg_bits(RCOMP_TIA_RFE, clamp(15 - cfb_tia_rfe / 100, 0, 15)); } } else //if(rx_lpf_IF > 54e6) @@ -718,14 +721,14 @@ uint8_t TuneTxFilterSetup(const float_type tx_lpf_IF) const float_type freq = (16.0 / 20.0) * tx_lpf_IF / 1e6; int16_t rcal_lpflad_tbb = pow(freq, 4) * 1.29858903647958e-16 + pow(freq, 3) * (-0.000110746929967704) + pow(freq, 2) * 0.00277593485991029 + freq * 21.0384293169607 + (-48.4092606238297); - Modify_SPI_Reg_bits(RCAL_LPFLAD_TBB, std::clamp(rcal_lpflad_tbb, 0, 255)); + Modify_SPI_Reg_bits(RCAL_LPFLAD_TBB, clamp(rcal_lpflad_tbb, 0, 255)); } else { const float_type freq = tx_lpf_IF / 1e6; int16_t rcal_lpfh_tbb = pow(freq, 4) * 1.10383261611112e-06 + pow(freq, 3) * (-0.000210800032517545) + pow(freq, 2) * 0.0190494874803309 + freq * 1.43317445923528 + (-47.6950779298333); - Modify_SPI_Reg_bits(RCAL_LPFH_TBB, std::clamp(rcal_lpfh_tbb, 0, 255)); + Modify_SPI_Reg_bits(RCAL_LPFH_TBB, clamp(rcal_lpfh_tbb, 0, 255)); } //CGEN @@ -800,13 +803,13 @@ static uint8_t SearchTxFilterCCAL_RCAL(uint16_t addr, uint8_t msblsb) uint8_t R = Get_SPI_Reg_bits(addr, msblsb); if (R == 0 || R == 255) return MCU_NO_ERROR; // reached filter bandwidth limit - Modify_SPI_Reg_bits(addr, msblsb, std::clamp(R + rcal_step, 0, 255)); + Modify_SPI_Reg_bits(addr, msblsb, clamp(R + rcal_step, 0, 255)); Modify_SPI_Reg_bits(CCAL_LPFLAD_TBB, 16); } else if (needToChangeCCAL) { uint8_t ccal_lpflad_tbb = Get_SPI_Reg_bits(CCAL_LPFLAD_TBB); - ccal_lpflad_tbb = std::clamp(ccal_lpflad_tbb + 1, 0, 31); + ccal_lpflad_tbb = clamp(ccal_lpflad_tbb + 1, 0, 31); Modify_SPI_Reg_bits(CCAL_LPFLAD_TBB, ccal_lpflad_tbb); } --iterationsLeft; @@ -862,3 +865,7 @@ TxFilterSearchEndStage : { return MCU_NO_ERROR; } + +#ifdef __cplusplus +} +#endif diff --git a/src/mcu_program/common_src/lms7002m_filters.h b/src/mcu_program/common_src/lms7002m_filters.h index 68e36cf71..9d59019e5 100644 --- a/src/mcu_program/common_src/lms7002m_filters.h +++ b/src/mcu_program/common_src/lms7002m_filters.h @@ -3,7 +3,15 @@ #include "typedefs.h" +#ifdef __cplusplus +extern "C" { +#endif + uint8_t TuneTxFilter(const float_type bandwidth); uint8_t TuneRxFilter(const float_type rx_lpf_freq_RF); +#ifdef __cplusplus +} +#endif + #endif