diff --git a/CMakeLists.txt b/CMakeLists.txt index 1ec79b3b1..ea73cfe3a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -176,7 +176,7 @@ if(ENABLE_TESTING) FetchContent_Declare( googletest GIT_REPOSITORY https://github.com/google/googletest.git - GIT_TAG b10fad38c4026a29ea6561ab15fc4818170d1c10 # latest main at the time of writing this + GIT_TAG dddb219c3eb96d7f9200f09b0a381f016e6b4562 # latest main at the time of writing this ) set(INSTALL_GMOCK OFF) # Don't install the GMock headers diff --git a/SoapyLMS7/Settings.cpp b/SoapyLMS7/Settings.cpp index 33178260a..d53dcd825 100644 --- a/SoapyLMS7/Settings.cpp +++ b/SoapyLMS7/Settings.cpp @@ -388,7 +388,6 @@ void SoapyLMS7::setFrequency( TRXDir dir = direction == SOAPY_SDR_TX ? TRXDir::Tx : TRXDir::Rx; if (name == "RF") { - const auto clkId = dir == TRXDir::Tx ? 2 : 1; try { sdrDevice->SetFrequency(0, dir, channel, frequency); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index f8cd98537..b88e3b331 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -50,6 +50,7 @@ set(LIME_SUITE_SOURCES threadHelper/threadHelper.cpp CDCM6208/CDCM6208_Dev.cpp gnuPlotPipe.h + parsers/CoefficientFileParser.cpp EnumToString.cpp @@ -196,7 +197,6 @@ set(LMS7SUITE_GUI_SOURCES lms7002_wxgui/lms7002_pnlLDO_view.cpp lms7002_wxgui/lms7002_pnlAFE_view.cpp lms7002_wxgui/lms7002_pnlGains_view.cpp - lms7002_wxgui/CoefficientFileParser.cpp lms7002_wxgui/lms7002_pnlRxTSP_view.cpp lms7002_wxgui/lms7002_mainPanel.cpp # lms7002_wxgui/dlgViewSFR.cpp diff --git a/src/boards/LMS7002M_SDRDevice.cpp b/src/boards/LMS7002M_SDRDevice.cpp index 49f6ceb20..9a61c4b8a 100644 --- a/src/boards/LMS7002M_SDRDevice.cpp +++ b/src/boards/LMS7002M_SDRDevice.cpp @@ -942,11 +942,11 @@ std::vector LMS7002M_SDRDevice::GetGFIRCoefficients(uint8_t moduleIndex, lime::LMS7002M* lms = mLMSChips.at(moduleIndex); const uint8_t count = gfirID == 2 ? 120 : 40; - std::vector coefficientBuffer(count); + std::vector coefficientBuffer(count); lms->GetGFIRCoefficients(trx, gfirID, coefficientBuffer.data(), count); - return std::vector(coefficientBuffer.begin(), coefficientBuffer.end()); + return coefficientBuffer; } void LMS7002M_SDRDevice::SetGFIRCoefficients( @@ -954,9 +954,7 @@ void LMS7002M_SDRDevice::SetGFIRCoefficients( { lime::LMS7002M* lms = mLMSChips.at(moduleIndex); - std::vector convertedCoefficients(coefficients.begin(), coefficients.end()); - - lms->SetGFIRCoefficients(trx, gfirID, convertedCoefficients.data(), convertedCoefficients.size()); + lms->SetGFIRCoefficients(trx, gfirID, coefficients.data(), coefficients.size()); } void LMS7002M_SDRDevice::SetGFIR(uint8_t moduleIndex, TRXDir trx, uint8_t channel, uint8_t gfirID, bool enabled) diff --git a/src/boards_wxgui/pnlGPIO.cpp b/src/boards_wxgui/pnlGPIO.cpp index 1d18e0269..e15f16a2e 100644 --- a/src/boards_wxgui/pnlGPIO.cpp +++ b/src/boards_wxgui/pnlGPIO.cpp @@ -30,9 +30,9 @@ void pnlGPIO::Initialize(lime::SDRDevice* pControl) auto info = device->GetDescriptor(); const std::unordered_map specialGpioCounts{ - { string(GetDeviceName(LMS_DEV_LIMESDRMINI)), 10 }, - { string(GetDeviceName(LMS_DEV_LIMESDRMINI_V2)), 10 }, - { string(GetDeviceName(LMS_DEV_LIMESDR_PCIE)), 16 }, + { GetDeviceName(LMS_DEV_LIMESDRMINI), 10 }, + { GetDeviceName(LMS_DEV_LIMESDRMINI_V2), 10 }, + { GetDeviceName(LMS_DEV_LIMESDR_PCIE), 16 }, }; if (specialGpioCounts.find(info.name) != specialGpioCounts.end()) diff --git a/src/comms/USB/LMS64C_LMS7002M_Over_USB.cpp b/src/comms/USB/LMS64C_LMS7002M_Over_USB.cpp index fcae3cb68..c70eff991 100644 --- a/src/comms/USB/LMS64C_LMS7002M_Over_USB.cpp +++ b/src/comms/USB/LMS64C_LMS7002M_Over_USB.cpp @@ -21,4 +21,4 @@ int LMS64C_LMS7002M_Over_USB::SPI(uint32_t spiBusAddress, const uint32_t* MOSI, int LMS64C_LMS7002M_Over_USB::ResetDevice(int chipSelect) { return LMS64CProtocol::DeviceReset(*pipe, chipSelect); -}; +} diff --git a/src/fftviewer_wxgui/fftviewer_frFFTviewer.cpp b/src/fftviewer_wxgui/fftviewer_frFFTviewer.cpp index 6139850ed..d71a86cf2 100644 --- a/src/fftviewer_wxgui/fftviewer_frFFTviewer.cpp +++ b/src/fftviewer_wxgui/fftviewer_frFFTviewer.cpp @@ -55,13 +55,13 @@ bool fftviewer_frFFTviewer::Initialize(SDRDevice* pDataPort) else { constexpr uint8_t modeChoicesItemCount = 2; - const std::array modeChoices{ "SISO", "MIMO" }; + const std::array modeChoices{ "SISO", "MIMO" }; cmbMode->Set(modeChoicesItemCount, modeChoices.data()); cmbMode->SetSelection(0); cmbMode->GetContainingSizer()->Layout(); // update the width of the box constexpr uint8_t channelVisibilityChoicesItemCount = 3; - const std::array channelVisibilityChoices{ "A", "B", "A&B" }; + const std::array channelVisibilityChoices{ "A", "B", "A&B" }; cmbChannelVisibility->Set(channelVisibilityChoicesItemCount, channelVisibilityChoices.data()); cmbChannelVisibility->SetSelection(0); cmbChannelVisibility->GetContainingSizer()->Layout(); // update the width of the box diff --git a/src/include/limesuite/LMS7002M.h b/src/include/limesuite/LMS7002M.h index 3ea35a3de..8bde083ae 100644 --- a/src/include/limesuite/LMS7002M.h +++ b/src/include/limesuite/LMS7002M.h @@ -280,11 +280,10 @@ class LIME_API LMS7002M int SetNCOPhaseOffsetForMode0(TRXDir dir, float_type angle_Deg); int SetNCOPhaseOffset(TRXDir dir, uint8_t index, float_type angle_Deg); float_type GetNCOPhaseOffset_Deg(TRXDir dir, uint8_t index); - int SetGFIRCoefficients(TRXDir dir, uint8_t GFIR_index, const int16_t* coef, uint8_t coefCount); - int GetGFIRCoefficients(TRXDir dir, uint8_t GFIR_index, int16_t* coef, uint8_t coefCount); float_type GetReferenceClk_TSP(TRXDir dir); - int WriteGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_type* coef, uint8_t coefCount); + int GetGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, float_type* coef, uint8_t coefCount); + int SetGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_type* coef, uint8_t coefCount); int SetGFIRFilter(TRXDir dir, unsigned ch, bool enabled, double bandwidth); int SetNCOFrequencies(TRXDir dir, const float_type* freq_Hz, uint8_t count, float_type phaseOffset); diff --git a/src/include/limesuite/LimeSuiteConfig.h b/src/include/limesuite/LimeSuiteConfig.h deleted file mode 100644 index 78a140751..000000000 --- a/src/include/limesuite/LimeSuiteConfig.h +++ /dev/null @@ -1,37 +0,0 @@ -/** -@file config.h -@author Lime Microsystems -@brief Configuration constants and macros for lime suite library. -*/ - -// Generic helper definitions for shared library support -#if defined _WIN32 || defined __CYGWIN__ - #define LIME_HELPER_DLL_IMPORT __declspec(dllimport) - #define LIME_HELPER_DLL_EXPORT __declspec(dllexport) - #define LIME_HELPER_DLL_LOCAL -#else - #if __GNUC__ >= 4 - #define LIME_HELPER_DLL_IMPORT __attribute__((visibility("default"))) - #define LIME_HELPER_DLL_EXPORT __attribute__((visibility("default"))) - #define LIME_HELPER_DLL_LOCAL __attribute__((visibility("hidden"))) - #else - #define LIME_HELPER_DLL_IMPORT - #define LIME_HELPER_DLL_EXPORT - #define LIME_HELPER_DLL_LOCAL - #endif -#endif - -// Now we use the generic helper definitions above to define LIME_API and LIME_LOCAL. -// LIME_API is used for the public API symbols. It either DLL imports or DLL exports (or does nothing for static build) -// LIME_LOCAL is used for non-api symbols. -#ifdef LIME_DLL // defined if LIME is compiled as a DLL - #ifdef LIME_DLL_EXPORTS // defined if we are building the LIME DLL (instead of using it) - #define LIME_API LIME_HELPER_DLL_EXPORT - #else - #define LIME_API LIME_HELPER_DLL_IMPORT - #endif // LIME_DLL_EXPORTS - #define LIME_LOCAL LIME_HELPER_DLL_LOCAL -#else // LIME_DLL is not defined: this means LIME is a static lib. - #define LIME_API - #define LIME_LOCAL -#endif // LIME_DLL diff --git a/src/include/limesuite/commonTypes.h b/src/include/limesuite/commonTypes.h index d04399c48..c6ccfaa19 100644 --- a/src/include/limesuite/commonTypes.h +++ b/src/include/limesuite/commonTypes.h @@ -5,7 +5,7 @@ namespace lime { enum class TRXDir : bool { Rx, Tx }; struct Range { - Range(double min = 0.0, double max = 0.0, double step = 0.0) + constexpr Range(double min = 0.0, double max = 0.0, double step = 0.0) : min(min) , max(max) , step(step){}; @@ -21,14 +21,14 @@ struct Range { template class DeltaVariable { public: - DeltaVariable(T init) + constexpr DeltaVariable(T init) : mValue(init) , mLastValue(0){}; - void set(T val) { mValue = val; } - void add(T val) { mValue += val; } - T delta() { return mValue - mLastValue; } // value change since last reset - T value() const { return mValue; } - void checkpoint() { mLastValue = mValue; } + constexpr void set(T val) { mValue = val; } + constexpr void add(T val) { mValue += val; } + constexpr T delta() const { return mValue - mLastValue; } // value change since last reset + constexpr T value() const { return mValue; } + constexpr void checkpoint() { mLastValue = mValue; } private: T mValue; diff --git a/src/lms7002_wxgui/CoefficientFileParser.cpp b/src/lms7002_wxgui/CoefficientFileParser.cpp deleted file mode 100644 index b12bc5202..000000000 --- a/src/lms7002_wxgui/CoefficientFileParser.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/** -@file CoefficientFileParser.cpp -@author Lime Microsystems -@brief Coefficient file parser functions -*/ - -#include -#include -#include -#include "CoefficientFileParser.h" -#include -using namespace std; - -// *************************************************************** -// Check if 'c' is blank character. -// *************************************************************** -bool Parser::IsBlank(char c) -{ - char blankchar[] = ", \t\n\r"; - for (unsigned i = 0; i < strlen(blankchar); i++) - if (c == blankchar[i]) - return (true); - - return (false); -} - -// *************************************************************** -// Check if 'c' is a digit. -// *************************************************************** -bool Parser::IsDigit(char c) -{ - char digit[] = ".0123456789+-"; - for (unsigned i = 0; i < strlen(digit); i++) - if (c == digit[i]) - return (true); - return (false); -} - -// *************************************************************** -// Get integer value from the file -// Returns: -// 0 upon success, -// -1 if EOF or -// -2 if syntax error -// *************************************************************** -int Parser::getValue(FILE* fp, float* v) -{ - char c, c1, str[256]; - int i, opencomments; - - /* Skip blanks, tabs and new lines */ - while (IsBlank(c = fgetc(fp))) - ; - - /* Its end of file, nothing to read */ - if (c == EOF) - return (EOF); - - if (c == '/') - { /* check for comments */ - c1 = fgetc(fp); - if (c1 == '/') - { /* C++ one line comment */ - while ((c = fgetc(fp)) != '\n' && c != EOF) - ; - if (c == EOF) - return (EOF); - else - return (getValue(fp, v)); - } - else if (c1 == '*') - { /* C like comment */ - opencomments = 1; - c = fgetc(fp); - if (c == EOF) - return (EOF); - while ((c1 = fgetc(fp)) != EOF) - { - if (c == '/' && c1 == '*') - opencomments++; - if (c == '*' && c1 == '/') - opencomments--; - c = c1; - if (opencomments == 0) - break; - } - if (c1 == EOF) - return (EOF); - else - return (getValue(fp, v)); - } - else - { - ungetc(c1, fp); - } - } - - if (IsDigit(c)) - { - i = 0; - str[i] = c; - i++; - while (IsDigit(c = fgetc(fp))) - { - str[i] = c; - i++; - } - ungetc(c, fp); - str[i] = '\0'; - *v = atof(str); - return (0); - } - else - return (-2); -} - -// *************************************************************** -// Get the coefficients from a file. Return values: -// -2 syntax error within the file -// -3 filename is empty string -// -4 can not open the file -// -5 too many coefficients in the file -// >=0 number of the coefficients read -// *************************************************************** -int Parser::getcoeffs(const char* filename, float* v, int max) -{ - int i, n; - FILE* fp; - - if (strlen(filename) == 0) - return (-3); - if ((fp = fopen(filename, "r")) == NULL) - return (-4); - - for (n = 0; n < max;) - { - i = getValue(fp, v); - if (i == EOF) - { - fclose(fp); - return (n); - } - else if (i == -2) - { - fclose(fp); - return (-2); - } - else if (i == 0) - { - n++; - v++; - } - } - fclose(fp); - return (-5); -} - -// *************************************************************** -// Get pair of the coefficients from a file. Return values: -// -1 odd number of the coefficients found in the file -// -2 syntax error within the file -// -3 filename is empty string -// -4 can not open the file -// -5 too many coefficients in the file -// >=0 number of the coefficients read -// *************************************************************** -int Parser::getcoeffs2(const char* filename, float* v1, float* v2, int max) -{ - int i, n; - FILE* fp; - - if (strlen(filename) == 0) - return (-3); - if ((fp = fopen(filename, "r")) == NULL) - return (-4); - - for (n = 0; n < max + 1;) - { - i = getValue(fp, v1); - if (i == EOF) - { - fclose(fp); - return (n); - } - else if (i == -2) - { - fclose(fp); - return (-2); - } - else if (i == 0) - { - v1++; - } - - i = getValue(fp, v2); - if (i == EOF) - { - fclose(fp); - return (-2); - } - else if (i == -2) - { - fclose(fp); - return (-2); - } - else if (i == 0) - { - v2++; - n++; - } - } - - fclose(fp); - return (-5); -} - -// *************************************************************** -// Saves given coefficients to fir file -// *************************************************************** -void Parser::saveToFile(const std::string& filename, const float* coefficients, int coefficientCount) -{ - fstream fout; - fout.open(filename, ios::out); - - std::string fname; - std::size_t name_pos = filename.rfind('\\'); - - if (name_pos == std::string::npos) - { - name_pos = filename.rfind('/'); - } - - fout << "/* ******************************************************************" << endl; - fout << " FILE:\t"; - if (name_pos != std::string::npos) - { - fname = filename.substr(name_pos + 1); - fout << fname << endl; - } - else - { - fout << "???" << endl; - } - - fout << " DESCRIPTION:\t" << endl; - fout << " DATE:\t" << endl; - fout << " REVISIONS:\t" << endl; - fout << " ****************************************************************** */" << endl << endl; - - for (int i = 0; i < coefficientCount; ++i) - { - fout << "\t" << std::fixed << coefficients[i]; - if (i < coefficientCount - 1) - fout << ',' << endl; - } - fout.close(); -} diff --git a/src/lms7002_wxgui/CoefficientFileParser.h b/src/lms7002_wxgui/CoefficientFileParser.h deleted file mode 100644 index f6793d6ae..000000000 --- a/src/lms7002_wxgui/CoefficientFileParser.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef COEFFICIENT_FILE_PARSER_H -#define COEFFICIENT_FILE_PARSER_H - -/** -@file CoefficientFileParser.h -@author Lime Microsystems -@brief Just group parser functions into the same namespace. -*/ - -#include - -namespace Parser { -bool IsBlank(char); -bool IsDigit(char); -int getValue(FILE*, float*); -int getcoeffs(const char*, float*, int); -int getcoeffs2(const char*, float*, float*, int); -void saveToFile(const std::string& filename, const float* coefficients, int coefficientCount); -} // namespace Parser - -#endif // COEFFICIENT_FILE_PARSER_H diff --git a/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.cpp b/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.cpp index 2f696da79..f6d785486 100644 --- a/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.cpp +++ b/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.cpp @@ -1,7 +1,9 @@ #include "lms7002_dlgGFIR_Coefficients.h" #include #include -#include "CoefficientFileParser.h" +#include "parsers/CoefficientFileParser.h" +#include "limesuite/commonTypes.h" +#include "limesuite/LMS7002M.h" lms7002_dlgGFIR_Coefficients::lms7002_dlgGFIR_Coefficients(wxWindow* parent, wxWindowID id, const wxString& title) : wxDialog(parent, id, title, wxDefaultPosition, wxDefaultSize, 0) @@ -115,8 +117,8 @@ void lms7002_dlgGFIR_Coefficients::OnLoadFromFile(wxCommandEvent& event) if (dlg.ShowModal() == wxID_CANCEL) return; - float cbuf[200]; - int iVal = Parser::getcoeffs(dlg.GetPath().ToStdString().c_str(), cbuf, 200); + std::vector coefficients(200, 0); + int iVal = lime::CoefficientFileParser::getCoefficients(dlg.GetPath().ToStdString(), coefficients, 200); switch (iVal) { @@ -142,7 +144,7 @@ void lms7002_dlgGFIR_Coefficients::OnLoadFromFile(wxCommandEvent& event) gridCoef->GetTable()->AppendRows(spinCoefCount->GetValue()); for (int i = 0; i < iVal; ++i) { - gridCoef->SetCellValue(i, 0, std::to_string(cbuf[i])); + gridCoef->SetCellValue(i, 0, std::to_string(coefficients[i])); } } @@ -150,17 +152,19 @@ void lms7002_dlgGFIR_Coefficients::OnSaveToFile(wxCommandEvent& event) { wxFileDialog dlg(this, _("Save coefficients file"), "", "", "FIR Coeffs (*.fir)|*.fir", wxFD_SAVE | wxFD_OVERWRITE_PROMPT); if (dlg.ShowModal() == wxID_CANCEL) + { return; - float coefficients[200]; - memset(coefficients, 0, sizeof(unsigned short) * 200); - double ltemp; - for (int i = 0; i < spinCoefCount->GetValue(); ++i) + } + + const int coefficientCount = spinCoefCount->GetValue(); + std::vector coefficients(coefficientCount, 0); + + for (int i = 0; i < coefficientCount; ++i) { - ltemp = 0; - gridCoef->GetCellValue(i, 0).ToDouble(<emp); - coefficients[i] = ltemp; + gridCoef->GetCellValue(i, 0).ToDouble(&coefficients[i]); } - Parser::saveToFile(dlg.GetPath().ToStdString(), coefficients, spinCoefCount->GetValue()); + + lime::CoefficientFileParser::saveToFile(dlg.GetPath().ToStdString(), coefficients); } void lms7002_dlgGFIR_Coefficients::OnClearTable(wxCommandEvent& event) @@ -214,4 +218,37 @@ void lms7002_dlgGFIR_Coefficients::OnBtnOkClick(wxCommandEvent& event) void lms7002_dlgGFIR_Coefficients::OnBtnCancelClick(wxCommandEvent& event) { EndModal(wxID_CANCEL); -} \ No newline at end of file +} + +int lms7002_dlgGFIR_Coefficients::ReadCoefficients(lime::TRXDir direction, uint8_t gfirIndex, lime::LMS7002M* lmsControl) +{ + if (gfirIndex > 2) + { + gfirIndex = 2; + } + + std::vector coefficients; + const int maxCoefCount = gfirIndex == 2 ? 120 : 40; + coefficients.resize(maxCoefCount, 0); + + int status = lmsControl->GetGFIRCoefficients(direction, gfirIndex, &coefficients[0], coefficients.size()); + if (status < 0) + { + wxMessageBox(_("Error reading GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); + return status; + } + + SetCoefficients(coefficients); + return status; +} + +void lms7002_dlgGFIR_Coefficients::WriteCoefficients(lime::TRXDir direction, uint8_t gfirIndex, lime::LMS7002M* lmsControl) +{ + std::vector coefficients = GetCoefficients(); + int status = lmsControl->SetGFIRCoefficients(direction, gfirIndex, &coefficients[0], coefficients.size()); + + if (status < 0) + { + wxMessageBox(_("Error writing GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); + } +} diff --git a/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.h b/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.h index 9bca3d421..5d559c0b1 100644 --- a/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.h +++ b/src/lms7002_wxgui/lms7002_dlgGFIR_Coefficients.h @@ -2,6 +2,10 @@ #define __lms7002_dlgGFIR_Coefficients__ #include "lms7002_wxgui.h" +#include "limesuite/commonTypes.h" +#include "limesuite/LMS7002M.h" + +#include #include class lms7002_dlgGFIR_Coefficients : public wxDialog @@ -19,6 +23,10 @@ class lms7002_dlgGFIR_Coefficients : public wxDialog lms7002_dlgGFIR_Coefficients(wxWindow* parent, wxWindowID id, const wxString& title); void SetCoefficients(const std::vector& coefficients); std::vector GetCoefficients(); + + int ReadCoefficients(lime::TRXDir direction, uint8_t gfirIndex, lime::LMS7002M* lmsControl); + void WriteCoefficients(lime::TRXDir direction, uint8_t gfirIndex, lime::LMS7002M* lmsControl); + wxButton* btnLoadFromFile; wxButton* btnSaveToFile; wxButton* btnClearTable; diff --git a/src/lms7002_wxgui/lms7002_pnlMCU_BD_view.cpp b/src/lms7002_wxgui/lms7002_pnlMCU_BD_view.cpp index d54f19596..fefe629f0 100644 --- a/src/lms7002_wxgui/lms7002_pnlMCU_BD_view.cpp +++ b/src/lms7002_wxgui/lms7002_pnlMCU_BD_view.cpp @@ -589,9 +589,7 @@ void lms7002_pnlMCU_BD_view::OnbtnLoadTestFileClick(wxCommandEvent& event) int test_code = 0; int address = 0; int value = 0; - int i = 0; - int scanStatus = 0; - //int temp; + wxFileDialog dlg(this, _("Open txt file"), _("txt"), @@ -607,17 +605,12 @@ void lms7002_pnlMCU_BD_view::OnbtnLoadTestFileClick(wxCommandEvent& event) temps = temps + m_sTxtFileName; lblTestResultsFile->SetLabel(temps); - FILE* inFile = NULL; - inFile = fopen(m_sTxtFileName.mb_str(), "r"); + std::ifstream inFile(m_sTxtFileName); - // debugging - //FILE * outFile=NULL; - //outFile = fopen("Out.txt", "w"); - // end debugging - if (inFile != NULL) + if (inFile.is_open()) { m_iTestResultFileLine = 0; - for (i = 0; i < 256; i++) + for (int i = 0; i < 256; i++) { TestResultArray_code[i] = 0; TestResultArray_address[i] = 0; @@ -625,31 +618,22 @@ void lms7002_pnlMCU_BD_view::OnbtnLoadTestFileClick(wxCommandEvent& event) } m_iTestResultFileLine = 0; - scanStatus = fscanf(inFile, "%d", &test_code); - while (!feof(inFile) && scanStatus >= 0) + inFile >> test_code; + + while (!inFile.eof() && !inFile.fail()) { - //fscanf(inFile, "%d %d %d", &test_code, &address, &value); - scanStatus = fscanf(inFile, "%d ", &address); - scanStatus = fscanf(inFile, "%d\n", &value); - TestResultArray_code[m_iTestResultFileLine] = (unsigned char)(test_code); - TestResultArray_address[m_iTestResultFileLine] = (unsigned char)(address); - TestResultArray_value[m_iTestResultFileLine] = (unsigned char)(value); + inFile >> address; + inFile >> value; + TestResultArray_code[m_iTestResultFileLine] = static_cast(test_code); + TestResultArray_address[m_iTestResultFileLine] = static_cast(address); + TestResultArray_value[m_iTestResultFileLine] = static_cast(value); m_iTestResultFileLine++; - scanStatus = fscanf(inFile, "%d", &test_code); + inFile >> test_code; } } - fclose(inFile); - - // debugging - //for (i=0; iSetLabel("Test results file: " + m_sTxtFileName); - int scanStatus = 0; - FILE* inFile = NULL; - inFile = fopen(m_sTxtFileName.mb_str(), "r"); + std::ifstream inFile(m_sTxtFileName); - if (inFile != NULL) + if (inFile.is_open()) { m_iTestResultFileLine = 0; for (int i = 0; i < 256; i++) @@ -939,17 +921,18 @@ void lms7002_pnlMCU_BD_view::OnbtnRunTestClick(wxCommandEvent& event) int test_code = 0; int address = 0; int value = 0; - scanStatus = fscanf(inFile, "%d", &test_code); - while (!feof(inFile) && scanStatus >= 0) + + inFile >> test_code; + while (!inFile.eof() && !inFile.fail()) { - scanStatus = fscanf(inFile, "%d ", &address); - scanStatus = fscanf(inFile, "%d\n", &value); - TestResultArray_code[m_iTestResultFileLine] = (unsigned char)(test_code); - TestResultArray_address[m_iTestResultFileLine] = (unsigned char)(address); - TestResultArray_value[m_iTestResultFileLine] = (unsigned char)(value); + inFile >> address; + inFile >> value; + TestResultArray_code[m_iTestResultFileLine] = static_cast(test_code); + TestResultArray_address[m_iTestResultFileLine] = static_cast(address); + TestResultArray_value[m_iTestResultFileLine] = static_cast(value); m_iTestResultFileLine++; - scanStatus = fscanf(inFile, "%d", &test_code); + inFile >> test_code; } } else @@ -957,7 +940,8 @@ void lms7002_pnlMCU_BD_view::OnbtnRunTestClick(wxCommandEvent& event) wxMessageBox(_("lms7suite_mcu/TestResults.txt file not found")); return; } - fclose(inFile); + + inFile.close(); unsigned char tempc1, tempc2, tempc3 = 0x00; int retval = 0; diff --git a/src/lms7002_wxgui/lms7002_pnlRxTSP_view.cpp b/src/lms7002_wxgui/lms7002_pnlRxTSP_view.cpp index bbf805eef..038a32ef3 100644 --- a/src/lms7002_wxgui/lms7002_pnlRxTSP_view.cpp +++ b/src/lms7002_wxgui/lms7002_pnlRxTSP_view.cpp @@ -1611,81 +1611,40 @@ lms7002_pnlRXTSP_view::lms7002_pnlRXTSP_view(wxWindow* parent, wxWindowID id, co void lms7002_pnlRXTSP_view::onbtnGFIR1Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR1 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 40; - coefficients.resize(maxCoefCount, 0); - - // TODO: - // int status = lmsControl->GetGFIRCoefficients(LMS_CH_RX, mChannel, 0, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Error reading GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // lmsControl->SetGFIRCoefficients(LMS_CH_RX, mChannel, 0, &coefficients[0], - // coefficients.size()); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR1 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Rx, 0, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Rx, 0, lmsControl); + } + UpdateGUI(); } void lms7002_pnlRXTSP_view::onbtnGFIR2Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR2 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 40; - coefficients.resize(maxCoefCount, 0); - // TODO: - // int status = lmsControl->GetGFIRCoefficients(LMS_CH_RX, mChannel, 1, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Error reading GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // lmsControl->SetGFIRCoefficients(LMS_CH_RX, mChannel, 1, &coefficients[0], - // coefficients.size()); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR2 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Rx, 1, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Rx, 1, lmsControl); + } + UpdateGUI(); } void lms7002_pnlRXTSP_view::onbtnGFIR3Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR3 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 120; - coefficients.resize(maxCoefCount, 0); - - // TODO; - // int status = lmsControl->GetGFIRCoefficients(LMS_CH_RX, mChannel, 2, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Error reading GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // lmsControl->SetGFIRCoefficients(LMS_CH_RX, mChannel, 2, &coefficients[0], - // coefficients.size()); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR3 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Rx, 2, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Rx, 2, lmsControl); + } + UpdateGUI(); } diff --git a/src/lms7002_wxgui/lms7002_pnlTxTSP_view.cpp b/src/lms7002_wxgui/lms7002_pnlTxTSP_view.cpp index be60b8036..c4dae0389 100644 --- a/src/lms7002_wxgui/lms7002_pnlTxTSP_view.cpp +++ b/src/lms7002_wxgui/lms7002_pnlTxTSP_view.cpp @@ -1570,89 +1570,40 @@ void lms7002_pnlTXTSP_view::OnbtnLoadDCQClick(wxCommandEvent& event) void lms7002_pnlTXTSP_view::onbtnGFIR1Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR1 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 40; - coefficients.resize(maxCoefCount, 0); - // uint16_t ch; - // LMS_ReadParam(lmsControl,LMS7param(MAC),&ch); - // ch = (ch == 2) ? 1 : 0; - // ch += 2*LMS7SuiteAppFrame::m_lmsSelection; - // int status = LMS_GetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR1, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Failed to read GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // status = LMS_SetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR1, &coefficients[0],coefficients.size()); - // if (status != 0) - // wxMessageBox(_("Failed to set GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR1 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Tx, 0, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Tx, 0, lmsControl); + } + UpdateGUI(); } void lms7002_pnlTXTSP_view::onbtnGFIR2Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR2 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 40; - coefficients.resize(maxCoefCount, 0); - // uint16_t ch; - // LMS_ReadParam(lmsControl,LMS7param(MAC),&ch); - // ch = (ch == 2) ? 1 : 0; - // ch += 2*LMS7SuiteAppFrame::m_lmsSelection; - // int status = LMS_GetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR2, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Failed to read GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // status = LMS_SetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR2, &coefficients[0],coefficients.size()); - // if (status != 0) - // wxMessageBox(_("Failed to set GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR2 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Tx, 1, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Tx, 1, lmsControl); + } + UpdateGUI(); } void lms7002_pnlTXTSP_view::onbtnGFIR3Coef(wxCommandEvent& event) { - lms7002_dlgGFIR_Coefficients* dlg = new lms7002_dlgGFIR_Coefficients(this, wxID_ANY, wxT("GFIR3 Coefficients")); - std::vector coefficients; - const int maxCoefCount = 120; - coefficients.resize(maxCoefCount, 0); - // uint16_t ch; - // LMS_ReadParam(lmsControl,LMS7param(MAC),&ch); - // ch = (ch == 2) ? 1 : 0; - // ch += 2*LMS7SuiteAppFrame::m_lmsSelection; - // int status = LMS_GetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR3, &coefficients[0]); - // if (status < 0) - // { - // wxMessageBox(_("Failed to read GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // dlg->Destroy(); - // return; - // } - // dlg->SetCoefficients(coefficients); - // if (dlg->ShowModal() == wxID_OK) - // { - // coefficients = dlg->GetCoefficients(); - // status = LMS_SetGFIRCoeff(lmsControl, LMS_CH_TX, ch, LMS_GFIR3, &coefficients[0],coefficients.size()); - // if (status != 0) - // wxMessageBox(_("Failed to set GFIR coefficients"), _("ERROR"), wxICON_ERROR | wxOK); - // } - dlg->Destroy(); + lms7002_dlgGFIR_Coefficients dlg(this, wxID_ANY, wxT("GFIR3 Coefficients")); + int status = dlg.ReadCoefficients(TRXDir::Tx, 2, lmsControl); + + if (status >= 0 && dlg.ShowModal() == wxID_OK) + { + dlg.WriteCoefficients(TRXDir::Tx, 2, lmsControl); + } + UpdateGUI(); } diff --git a/src/lms7002m/LMS7002M.cpp b/src/lms7002m/LMS7002M.cpp index 8385f9045..4e56de5a4 100644 --- a/src/lms7002m/LMS7002M.cpp +++ b/src/lms7002m/LMS7002M.cpp @@ -2151,55 +2151,33 @@ float_type LMS7002M::GetNCOPhaseOffset_Deg(TRXDir dir, uint8_t index) /** @brief Uploads given FIR coefficients to chip @param dir Transmitter or receiver selection - @param GFIR_index GIR index from 0 to 2 - @param coef array of coefficients + @param gfirIndex GIR index from 0 to 2 + @param coef array of coefficients (normalized from -1 to 1) @param coefCount number of coefficients @return 0-success, other-failure This function does not change GFIR*_L or GFIR*_N parameters, they have to be set manually */ -int LMS7002M::SetGFIRCoefficients(TRXDir dir, uint8_t GFIR_index, const int16_t* coef, uint8_t coefCount) -{ - uint8_t index; - uint8_t coefLimit; - uint16_t startAddr; - if (GFIR_index == 0) - startAddr = 0x0280; - else if (GFIR_index == 1) - startAddr = 0x02C0; - else - startAddr = 0x0300; - - if (dir == TRXDir::Rx) - startAddr += 0x0200; - if (GFIR_index < 2) - coefLimit = 40; - else - coefLimit = 120; - if (coefCount > coefLimit) - return ReportError(ERANGE, "SetGFIRCoefficients(coefCount=%d) - exceeds coefLimit=%d", int(coefCount), int(coefLimit)); - std::vector addresses; - for (index = 0; index < coefCount; ++index) - addresses.push_back(startAddr + index + 24 * (index / 40)); - SPI_write_batch(&addresses[0], (uint16_t*)coef, coefCount, true); - return 0; -} - -int LMS7002M::WriteGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_type* coef, uint8_t coefCount) +int LMS7002M::SetGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_type* coef, uint8_t coefCount) { if (gfirIndex > 2) { - lime::warning("SetGFIRCoefficients: Invalid GFIR index(%i). Will configure GFIR[2]."); + lime::warning("SetGFIRCoefficients: Invalid GFIR index(%i). Will configure GFIR[2].", gfirIndex); gfirIndex = 2; } - const uint16_t startAddr = 0x0280 + (gfirIndex * 64) + (dir == TRXDir::Tx ? 0 : 0x0200); + const uint16_t startAddr = 0x0280 + (gfirIndex * 0x40) + (dir == TRXDir::Tx ? 0 : 0x0200); const uint8_t maxCoefCount = gfirIndex < 2 ? 40 : 120; const uint8_t bankCount = gfirIndex < 2 ? 5 : 15; if (coefCount > maxCoefCount) - return ReportError( - ERANGE, "SetGFIRCoefficients: too many coefficients(%i), GFIR[%i] can have only %i", coefCount, maxCoefCount); + { + return ReportError(ERANGE, + "SetGFIRCoefficients: too many coefficients(%i), GFIR[%i] can have only %i", + coefCount, + gfirIndex, + maxCoefCount); + } uint16_t addrs[120]; int16_t words[120]; @@ -2215,10 +2193,20 @@ int LMS7002M::WriteGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_t uint8_t bankRow = i % bankLength; addrs[i] = startAddr + (bank * 8) + bankRow; addrs[i] += 24 * (bank / 5); + if (i < coefCount) + { words[i] = coef[i] * 32767; + + if (coef[i] < -1 || coef[i] > 1) + { + lime::warning("Coefficient %f is outside of range [-1:1], incorrect value will be written.", coef[i]); + } + } else + { words[i] = 0; + } } LMS7Parameter gfirL_param = LMS7param(GFIR1_L_TXTSP); gfirL_param.address += gfirIndex + (dir == TRXDir::Tx ? 0 : 0x0200); @@ -2227,56 +2215,61 @@ int LMS7002M::WriteGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, const float_t return SPI_write_batch(addrs, (const uint16_t*)words, actualCoefCount, true); } -/** @brief Returns currently loaded FIR coefficients - @param dir Transmitter or receiver selection - @param GFIR_index GIR index from 0 to 2 - @param coef array of returned coefficients - @param coefCount number of coefficients to read - @return 0-success, other-failure +/** @brief Returns currently loaded FIR coefficients. + @param dir Transmitter or receiver selection. + @param GFIR_index GFIR index from 0 to 2. + @param coef Array of returned coefficients (normalized from -1 to 1) + @param coefCount Number of coefficients to read. + @return 0-success, other-failure. */ -int LMS7002M::GetGFIRCoefficients(TRXDir dir, uint8_t GFIR_index, int16_t* coef, uint8_t coefCount) +int LMS7002M::GetGFIRCoefficients(TRXDir dir, uint8_t gfirIndex, float_type* coef, uint8_t coefCount) { int status = -1; - uint8_t index; - uint8_t coefLimit; - uint16_t startAddr; - if (GFIR_index == 0) - startAddr = 0x0280; - else if (GFIR_index == 1) - startAddr = 0x02C0; - else - startAddr = 0x0300; - if (dir == TRXDir::Rx) - startAddr += 0x0200; - if (GFIR_index < 2) - coefLimit = 40; - else - coefLimit = 120; + if (gfirIndex > 2) + { + lime::warning("GetGFIRCoefficients: Invalid GFIR index(%i). Will read GFIR[2].", gfirIndex); + gfirIndex = 2; + } + + const uint16_t startAddr = 0x0280 + (gfirIndex * 0x40) + (dir == TRXDir::Tx ? 0 : 0x0200); + const uint8_t coefLimit = gfirIndex < 2 ? 40 : 120; + if (coefCount > coefLimit) - return ReportError(ERANGE, "GetGFIRCoefficients(coefCount=%d) - exceeds coefLimit=%d", int(coefCount), int(coefLimit)); + { + return ReportError(ERANGE, "GetGFIRCoefficients(coefCount=%d) - exceeds coefLimit=%d", coefCount, coefLimit); + } std::vector addresses; - for (index = 0; index < coefCount; ++index) + for (uint8_t index = 0; index < coefCount; ++index) + { addresses.push_back(startAddr + index + 24 * (index / 40)); - uint16_t spiData[120]; - memset(spiData, 0, 120 * sizeof(uint16_t)); + } + + int16_t spiData[120]; + std::memset(spiData, 0, 120 * sizeof(int16_t)); if (controlPort) { - status = SPI_read_batch(&addresses[0], spiData, coefCount); - for (index = 0; index < coefCount; ++index) - coef[index] = spiData[index]; + status = SPI_read_batch(&addresses[0], reinterpret_cast(spiData), coefCount); + for (uint8_t index = 0; index < coefCount; ++index) + { + coef[index] = spiData[index] / 32767.0; + } } else { const int channel = Get_SPI_Reg_bits(LMS7param(MAC), false) > 1 ? 1 : 0; - for (index = 0; index < coefCount; ++index) - coef[index] = mRegistersMap->GetValue(channel, addresses[index]); + for (uint8_t index = 0; index < coefCount; ++index) + { + uint16_t value = mRegistersMap->GetValue(channel, addresses[index]); + coef[index] = *reinterpret_cast(&value) / 32767.0; + } status = 0; } return status; } + /** @brief Write given data value to whole register @param address SPI address @param data new register value @@ -3416,8 +3409,8 @@ int LMS7002M::SetGFIRFilter(TRXDir dir, unsigned ch, bool enabled, double bandwi Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), div); } - if ((WriteGFIRCoefficients(dir, 0, coef2, L * 5) != 0) || (WriteGFIRCoefficients(dir, 1, coef2, L * 5) != 0) || - (WriteGFIRCoefficients(dir, 2, coef, L * 15) != 0)) + if ((SetGFIRCoefficients(dir, 0, coef2, L * 5) != 0) || (SetGFIRCoefficients(dir, 1, coef2, L * 5) != 0) || + (SetGFIRCoefficients(dir, 2, coef, L * 15) != 0)) return -1; std::stringstream ss; diff --git a/src/parsers/CoefficientFileParser.cpp b/src/parsers/CoefficientFileParser.cpp new file mode 100644 index 000000000..f57624245 --- /dev/null +++ b/src/parsers/CoefficientFileParser.cpp @@ -0,0 +1,260 @@ +/** +@file CoefficientFileParser.cpp +@author Lime Microsystems +@brief Coefficient file parser functions +*/ + +#include "CoefficientFileParser.h" + +#include +#include +#include +#include +#include +#include + +using namespace lime; +using namespace std::literals::string_literals; +using namespace std::literals::string_view_literals; + +void CoefficientFileParser::parseMultilineComments(std::ifstream& file, std::string& token) +{ + std::string_view view = token; + view = view.substr(2); + if (view.empty()) + { + if (file.eof()) + { + token = ""s; + return; + } + + file >> token; + view = token; + } + + uint commentLevelsDeep = 1; + + while (commentLevelsDeep != 0) // Multiline comments can be nested + { + std::size_t startCommentPos = view.find("/*"sv); + std::size_t endCommentPos = view.find("*/"sv); + + // While we're still finding comment starts and ends in this token. + while ((startCommentPos != std::string_view::npos || endCommentPos != std::string_view::npos) && commentLevelsDeep > 0) + { + if (endCommentPos < startCommentPos) // We're out of comment section. + { + commentLevelsDeep--; + + view = view.substr(endCommentPos + 2); + + endCommentPos = view.find("*/"sv); + if (startCommentPos != std::string_view::npos) + { + startCommentPos = view.find("/*"sv); + } + } + else if (startCommentPos < endCommentPos) + { + commentLevelsDeep++; + + view = view.substr(startCommentPos + 2); + + startCommentPos = view.find("/*"sv); + if (endCommentPos != std::string_view::npos) + { + endCommentPos = view.find("*/"sv); + } + } + } + + if (commentLevelsDeep == 0) + { + token = view; + return; + } + + // Keep reading until the end of the comment(s) + if (file.eof()) + { + token = ""s; + return; + } + + file >> token; + view = token; + } +} + +// *************************************************************** +// Get integer value from the file +// Returns: +// 0 upon success, +// -1 if EOF or +// -2 if syntax error +// *************************************************************** +CoefficientFileParser::ErrorCodes CoefficientFileParser::getValue(std::ifstream& file, double& value) +{ + file >> value; + if (!file.fail()) + { + return ErrorCodes::SUCCESS; + } + + if (file.eof()) + { + return ErrorCodes::END_OF_FILE; + } + + file.clear(); + std::string token; + file >> token; + + bool hasValueBeenRead = false; + + while (!hasValueBeenRead) + { + if (token.find(',') == 0) // Treat comma as a whitespace character. + { + token = token.substr(1); + } + else if (token.find("//"sv) == 0) // Standard single line comment + { + file.ignore(std::numeric_limits::max(), '\n'); + + if (file.eof()) + { + return ErrorCodes::END_OF_FILE; + } + + file >> token; + } + else if (token.find("/*"sv) == 0) // Multiline comments + { + parseMultilineComments(file, token); + } + else + { + return ErrorCodes::SYNTAX_ERROR; + } + + if (token.size() == 0) + { + if (file.eof()) + { + return ErrorCodes::END_OF_FILE; + } + + file >> token; + } + + std::stringstream stream(token); + stream >> value; + + if (!stream.fail()) + { + hasValueBeenRead = true; + stream >> token; + + if (stream.fail()) + { + token = ""s; + } + } + } + + // Rewind file by the amount of unparsed characters. + std::size_t charsToUnget = token.size(); + for (std::size_t i = 0; i < charsToUnget; ++i) + { + file.unget(); + } + + return ErrorCodes::SUCCESS; +} + +// *************************************************************** +// Get the coefficients from a file. Return values: +// -2 syntax error within the file +// -3 filename is empty string +// -4 can not open the file +// -5 too many coefficients in the file +// >=0 number of the coefficients read +// *************************************************************** +int CoefficientFileParser::getCoefficients(const std::filesystem::path& filename, std::vector& coefficients, int max) +{ + if (filename.empty()) + { + return static_cast(ErrorCodes::EMPTY_FILENAME); + } + + std::ifstream inputFile(filename); + if (!inputFile.is_open()) + { + return static_cast(ErrorCodes::UNOPENABLE_FILE); + } + + int index = 0; + while (index <= max) + { + double value = 0; + + ErrorCodes returnValue = getValue(inputFile, value); + + switch (returnValue) + { + case ErrorCodes::SUCCESS: + if (index >= max) + { + inputFile.close(); + return static_cast(ErrorCodes::TOO_MANY_COEFFS); + } + + coefficients[index] = value; + index++; + break; + case ErrorCodes::END_OF_FILE: + inputFile.close(); + return index; + case ErrorCodes::SYNTAX_ERROR: + inputFile.close(); + return static_cast(ErrorCodes::SYNTAX_ERROR); + default: + throw std::logic_error("Unexpected return from getValue"s); + } + } + + throw std::logic_error("Unreachable; clearing a warning"s); +} + +// *************************************************************** +// Saves given coefficients to fir file +// *************************************************************** +void CoefficientFileParser::saveToFile(const std::filesystem::path& filename, const std::vector& coefficients) +{ + std::ofstream fout; + fout.open(filename, std::ios::out); + + fout << "/* ******************************************************************"sv << std::endl; + fout << " FILE:\t"sv; + fout << filename.filename().c_str() << std::endl; + + fout << " DESCRIPTION:\t"sv << std::endl; + fout << " DATE:\t"sv << std::endl; + fout << " REVISIONS:\t"sv << std::endl; + fout << " ****************************************************************** */"sv << std::endl << std::endl; + + const std::size_t coefficientCount = coefficients.size(); + for (std::size_t i = 0; i < coefficientCount; ++i) + { + fout << '\t' << std::fixed << coefficients[i]; + + if (i < coefficientCount - 1) // If not last + { + fout << ',' << std::endl; + } + } + + fout.close(); +} diff --git a/src/parsers/CoefficientFileParser.h b/src/parsers/CoefficientFileParser.h new file mode 100644 index 000000000..5fb927c2f --- /dev/null +++ b/src/parsers/CoefficientFileParser.h @@ -0,0 +1,41 @@ +#ifndef COEFFICIENT_FILE_PARSER_H +#define COEFFICIENT_FILE_PARSER_H + +/** +@file CoefficientFileParser.h +@author Lime Microsystems +@brief The FIR coefficient file parser. +*/ + +#include "limesuite/config.h" + +#include +#include +#include +#include + +namespace lime { + +class LIME_API CoefficientFileParser +{ + public: + static int getCoefficients(const std::filesystem::path& filename, std::vector& coefficients, int max); + static void saveToFile(const std::filesystem::path& filename, const std::vector& coefficients); + + private: + enum class ErrorCodes : int8_t { + SUCCESS = 0, + END_OF_FILE = -1, + SYNTAX_ERROR = -2, + EMPTY_FILENAME = -3, + UNOPENABLE_FILE = -4, + TOO_MANY_COEFFS = -5, + }; + + static ErrorCodes getValue(std::ifstream& file, double& value); + static void parseMultilineComments(std::ifstream& file, std::string& token); +}; + +} // namespace lime + +#endif // COEFFICIENT_FILE_PARSER_H diff --git a/src/protocols/ADCUnits.h b/src/protocols/ADCUnits.h index a4d866ca0..ce41b3f95 100644 --- a/src/protocols/ADCUnits.h +++ b/src/protocols/ADCUnits.h @@ -11,10 +11,10 @@ namespace lime { enum eADC_UNITS { RAW, VOLTAGE, CURRENT, RESISTANCE, POWER, TEMPERATURE, ADC_UNITS_COUNT }; -static const std::array ADC_UNITS_TEXT{ "", "V", "A", "Ohm", "W", "C" }; +static const std::array ADC_UNITS_TEXT{ "", "V", "A", "Ohm", "W", "C" }; static const std::string UNKNOWN{ " unknown" }; -static const std::string& adcUnits2string(const unsigned units) +static constexpr const std::string& adcUnits2string(const unsigned units) { if (units < ADC_UNITS_COUNT) { diff --git a/src/protocols/DataPacket.h b/src/protocols/DataPacket.h index 65aae5e35..df81ea875 100644 --- a/src/protocols/DataPacket.h +++ b/src/protocols/DataPacket.h @@ -9,12 +9,12 @@ struct FPGA_RxDataPacket { FPGA_RxDataPacket() { assert(sizeof(FPGA_RxDataPacket) - sizeof(data) == 16); - memset(this, 0, sizeof(FPGA_RxDataPacket)); + std::memset(this, 0, sizeof(FPGA_RxDataPacket)); } inline bool txWasDropped() const { return header0 & (1 << 3); } - inline float RxFIFOFill() { return (header0 & 0x7) * 0.125; } + inline float RxFIFOFill() const { return (header0 & 0x7) * 0.125; } inline uint16_t GetPayloadSize() const { @@ -38,7 +38,7 @@ struct FPGA_TxDataPacket { FPGA_TxDataPacket() { assert(sizeof(FPGA_TxDataPacket) - sizeof(data) == 16); - memset(this, 0, sizeof(FPGA_TxDataPacket)); + std::memset(this, 0, sizeof(FPGA_TxDataPacket)); } inline void ignoreTimestamp(bool enabled) @@ -48,13 +48,13 @@ struct FPGA_TxDataPacket { header0 |= enabled ? mask : 0; //ignore timestamp } - inline bool getIgnoreTimestamp() + inline bool getIgnoreTimestamp() const { constexpr uint8_t mask = 1 << 4; return header0 & mask; //ignore timestamp } - inline void ClearHeader() { memset(this, 0, 16); } + inline void ClearHeader() { std::memset(this, 0, 16); } inline void SetPayloadSize(uint16_t size) { @@ -86,7 +86,7 @@ struct StreamHeader { header0 |= enabled ? mask : 0; //ignore timestamp } - inline bool getIgnoreTimestamp() + inline bool getIgnoreTimestamp() const { constexpr uint8_t mask = 1 << 4; return header0 & mask; //ignore timestamp @@ -95,7 +95,7 @@ struct StreamHeader { inline void Clear() { assert(sizeof(StreamHeader) == 16); - memset(this, 0, sizeof(StreamHeader)); + std::memset(this, 0, sizeof(StreamHeader)); } inline void SetPayloadSize(uint16_t size) diff --git a/src/protocols/LMS64CProtocol.cpp b/src/protocols/LMS64CProtocol.cpp index 92a1ee0d0..7fcdceff3 100644 --- a/src/protocols/LMS64CProtocol.cpp +++ b/src/protocols/LMS64CProtocol.cpp @@ -85,13 +85,13 @@ constexpr size_t LMS64CPacketMemoryWriteView::GetMaxDataSize() namespace LMS64CProtocol { -static const std::array COMMAND_STATUS_TEXT = { +static const std::array COMMAND_STATUS_TEXT = { "Undefined/Failure", "Completed", "Unknown command", "Busy", "Too many blocks", "Error", "Wrong order", "Resource denied" }; static const std::string UNKNOWN{ "Unknown status" }; -static inline const std::string& status2string(const int status) +static constexpr const std::string& status2string(const int status) { if (status >= 0 && status < eCMD_STATUS::STATUS_COUNT) { @@ -101,7 +101,9 @@ static inline const std::string& status2string(const int status) return UNKNOWN; } -static const char ADC_UNITS_PREFIX[] = { ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm' }; +static constexpr std::array ADC_UNITS_PREFIX = { + ' ', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'y', 'z', 'a', 'f', 'p', 'n', 'u', 'm' +}; static int SPI16(ISerialPort& port, uint8_t chipSelect, diff --git a/src/protocols/LMSBoards.h b/src/protocols/LMSBoards.h index 59f3031d6..c512727bc 100644 --- a/src/protocols/LMSBoards.h +++ b/src/protocols/LMSBoards.h @@ -44,7 +44,7 @@ enum eLMS_DEV { LMS_DEV_COUNT }; -const std::array LMS_DEV_NAMES = { "UNKNOWN", +const std::array LMS_DEV_NAMES = { "UNKNOWN", "EVB6", "DigiGreen", "DigiRed", @@ -74,7 +74,7 @@ const std::array LMS_DEV_NAMES = { "UNKNOWN", "LimeSDR XTRX", "LimeSDR MMX8" }; -static inline const std::string& GetDeviceName(const eLMS_DEV device) +static constexpr const std::string& GetDeviceName(const eLMS_DEV device) { if (LMS_DEV_UNKNOWN < device && device < LMS_DEV_COUNT) { @@ -99,7 +99,7 @@ enum eEXP_BOARD { EXP_BOARD_COUNT }; -const std::array EXP_BOARD_NAMES = { +const std::array EXP_BOARD_NAMES = { "UNKNOWN", "UNSUPPORTED", "NOT AVAILABLE", @@ -112,7 +112,7 @@ const std::array EXP_BOARD_NAMES = { "Myriad7 Novena", }; -static inline const std::string& GetExpansionBoardName(const eEXP_BOARD board) +static constexpr const std::string& GetExpansionBoardName(const eEXP_BOARD board) { if (EXP_BOARD_UNKNOWN < board && board < EXP_BOARD_COUNT) { diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index d38fe2d47..48a5589d4 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt @@ -7,6 +7,7 @@ set(LIME_TEST_SUITE_SOURCES boards/LimeSDR_Mini/USB_CSR_Pipe_MiniTest.cpp boards/LimeSDR_X3/SlaveSelectShimTest.cpp comms/PCIe/PCIE_CSR_PipeTest.cpp + parsers/CoefficientFileParserTest.cpp protocols/LMS64CProtocol/CustomParameterReadTest.cpp protocols/LMS64CProtocol/CustomParameterWriteTest.cpp protocols/LMS64CProtocol/DeviceResetTest.cpp diff --git a/src/tests/parsers/CoefficientFileParserTest.cpp b/src/tests/parsers/CoefficientFileParserTest.cpp new file mode 100644 index 000000000..c786a26a1 --- /dev/null +++ b/src/tests/parsers/CoefficientFileParserTest.cpp @@ -0,0 +1,558 @@ +#include +#include + +#include "parsers/CoefficientFileParser.h" + +#include +#include + +using namespace lime; + +TEST(CoefficientFileParser, StandardOutputFile) +{ + const std::string fileContents = R"""(/* ****************************************************************** + FILE: rx2 + DESCRIPTION: + DATE: + REVISIONS: + ****************************************************************** */ + + 1.470962, + 1.203833, + 1.728385, + 0.165471, + 0.581988, + 0.380383, + 1.485763, + 0.278542, + 0.074313, + 1.760674, + 1.387982, + 1.452406, + 1.000000, + 0.366008, + 1.713828, + 1.365612, + 0.437727, + 1.226112, + 0.570177, + 0.308145, + 0.738365, + 0.405255, + 0.957701, + 1.430128, + 1.571398, + 1.124363, + 0.602954, + 0.087985, + 1.410993, + 0.167486, + 1.106784, + 0.144505, + 0.666616, + 1.205695, + 0.804224, + 0.694357, + 0.644124, + 1.283670, + 1.822108, + 0.338786 +)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 1.470962, + 1.203833, + 1.728385, + 0.165471, + 0.581988, + 0.380383, + 1.485763, + 0.278542, + 0.074313, + 1.760674, + 1.387982, + 1.452406, + 1.000000, + 0.366008, + 1.713828, + 1.365612, + 0.437727, + 1.226112, + 0.570177, + 0.308145, + 0.738365, + 0.405255, + 0.957701, + 1.430128, + 1.571398, + 1.124363, + 0.602954, + 0.087985, + 1.410993, + 0.167486, + 1.106784, + 0.144505, + 0.666616, + 1.205695, + 0.804224, + 0.694357, + 0.644124, + 1.283670, + 1.822108, + 0.338786 }; + expectedResult.resize(40, 0); + + std::vector coefficients(40, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 40); + + EXPECT_EQ(actualReturn, 40); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SingleLineComments) +{ + const std::string fileContents = R"""(0.111111 // 0.222222 + 0.333333//0.444444 + 0.555555 // Random characters as well + 0.777777 +)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.333333, 0.555555, 0.777777 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 4); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SinglelineCommentsMultilineCommentIsIgnored) +{ + const std::string fileContents = R"""(0.111111 ///*0.222222 + // /* 0.333333 + 0.444444)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.444444 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 2); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SingleLineCommentFileEnd) +{ + const std::string fileContents = R"""(0.111111 // 0.222222 + 0.333333//0.444444 + 0.555555// Random characters as well)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.333333, 0.555555 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 3); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SingleLineCommentImmediateFileEnd) +{ + const std::string fileContents = R"""(0.111111 //)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 1); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, MultilineCommentsSingleLine) +{ + const std::string fileContents = + R"""(0.111111/*0.222222*/0.333333/* 0.444444*/ 0.555555 /* 0.666666 */ 0.777777/*0.888888*/,0.99)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.333333, 0.555555, 0.777777, 0.99 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 5); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, MultilineCommentsMultiLine) +{ + const std::string fileContents = R"""(0.111111/*0.222222 + */0.333333/* + 0.444444*/ 0.555555 /* + 0.666666 + */ 0.777777)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.333333, 0.555555, 0.777777 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 4); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, MultilineCommentsNested) +{ + const std::string fileContents = R"""(0.111111/*0.222222 + */0.333333/* /* + 0.444444*/*/ 0.555555 /*/**/*//* + 0.666666 + */ 0.777777)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.333333, 0.555555, 0.777777 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 4); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, MultilineCommentsUnclosed) +{ + const std::string fileContents = R"""(0.111111/* 0.222222 + 0.333333)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 1); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, MultilineCommentsUnclosedImmediateEndOfFile) +{ + const std::string fileContents = R"""(/*)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{}; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 0); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, CommasAreWhitespace) +{ + const std::string fileContents = R"""(,,,,,0.111111,,,0.222222 + , , , 0.333333,,,,,,)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111, 0.222222, 0.333333 }; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 3); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, NoFilenameProvided) +{ + const std::string fileName = ""; + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, -3); +} + +TEST(CoefficientFileParser, NonExistentFilenameProvided) +{ + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, -4); +} + +TEST(CoefficientFileParser, EmptyFile) +{ + const std::string fileContents = ""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{}; + expectedResult.resize(10, 0); + + std::vector coefficients(10, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 10); + + EXPECT_EQ(actualReturn, 0); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, TooManyCoefficients) +{ + const std::string fileContents = R"""( 0.111111 -0.222222)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.111111 }; + expectedResult.resize(1, 0); + + std::vector coefficients(1, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 1); + + EXPECT_EQ(actualReturn, -5); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SyntaxError) +{ + const std::string fileContents = R"""(0.123456 These characters are not in a comment)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.123456 }; + expectedResult.resize(1, 0); + + std::vector coefficients(1, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 1); + + EXPECT_EQ(actualReturn, -2); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, EndOfFileWithComma) +{ + const std::string fileContents = R"""(0.123456,)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + std::ofstream outFile(fileName); + outFile << fileContents; + outFile.close(); + + std::vector expectedResult{ 0.123456 }; + expectedResult.resize(1, 0); + + std::vector coefficients(1, 0); + int actualReturn = CoefficientFileParser::getCoefficients(fileName, coefficients, 1); + + EXPECT_EQ(actualReturn, 1); + EXPECT_THAT(coefficients, expectedResult); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SaveFile) +{ + const std::string fileContents = R"""(/* ****************************************************************** + FILE: CoefficientFileParser_SaveFile.fir + DESCRIPTION: + DATE: + REVISIONS: + ****************************************************************** */ + + 0.111111, + -0.222222, + 0.333333)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = testSuiteName + "_" + testName + ".fir"; + + const std::vector input{ 0.111111, -0.222222, 0.333333 }; + + CoefficientFileParser::saveToFile(fileName, input); + + std::ifstream in(fileName); + + std::string actualFileContents; + std::getline(in, actualFileContents, '\0'); + + EXPECT_EQ(actualFileContents, fileContents); + + std::filesystem::remove(fileName); +} + +TEST(CoefficientFileParser, SaveFileInSubfolder) +{ + const std::string fileContents = R"""(/* ****************************************************************** + FILE: CoefficientFileParser_SaveFileInSubfolder.fir + DESCRIPTION: + DATE: + REVISIONS: + ****************************************************************** */ + + 0.111111, + -0.222222, + 0.333333)"""; + + const std::string testSuiteName = ::testing::UnitTest::GetInstance()->current_test_info()->test_suite_name(); + const std::string testName = ::testing::UnitTest::GetInstance()->current_test_info()->name(); + const std::string fileName = "./" + testSuiteName + "_" + testName + ".fir"; // Use this folder as the testing path. + + const std::vector input{ 0.111111, -0.222222, 0.333333 }; + + CoefficientFileParser::saveToFile(fileName, input); + + std::ifstream in(fileName); + + std::string actualFileContents; + std::getline(in, actualFileContents, '\0'); + + EXPECT_EQ(actualFileContents, fileContents); + + std::filesystem::remove(fileName); +}