From aa047c77cc815c76847194ee162beb35507d3547 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 9 Sep 2017 03:09:17 +0200 Subject: [PATCH] PluoSDR: debug (1) --- devices/plutosdr/deviceplutosdr.cpp | 2 +- devices/plutosdr/deviceplutosdrbox.cpp | 168 ++++++++--- devices/plutosdr/deviceplutosdrbox.h | 20 +- .../plutosdrinput/plutosdrinput.cpp | 94 +++--- .../plutosdrinput/plutosdrinput.h | 3 + .../plutosdrinput/plutosdrinputgui.cpp | 274 +++++++++++++++++- .../plutosdrinput/plutosdrinputgui.h | 29 ++ .../plutosdrinput/plutosdrinputgui.ui | 65 +---- .../plutosdrinput/plutosdrinputsettings.cpp | 32 +- .../plutosdrinput/plutosdrinputsettings.h | 23 +- 10 files changed, 523 insertions(+), 187 deletions(-) diff --git a/devices/plutosdr/deviceplutosdr.cpp b/devices/plutosdr/deviceplutosdr.cpp index a0792218e..d5cddc6c8 100644 --- a/devices/plutosdr/deviceplutosdr.cpp +++ b/devices/plutosdr/deviceplutosdr.cpp @@ -19,7 +19,7 @@ const uint64_t DevicePlutoSDR::loLowLimitFreq = 70000000UL; // 70 MHz: take AD9364 specs const uint64_t DevicePlutoSDR::loHighLimitFreq = 6000000000UL; // 6 GHz: take AD9364 specs -const uint32_t DevicePlutoSDR::srLowLimitFreq = 200000; // 200 kS/s +const uint32_t DevicePlutoSDR::srLowLimitFreq = 2100000; // 2.1 MS/s empirical const uint32_t DevicePlutoSDR::srHighLimitFreq = 20000000; // 20 MS/s: take AD9363 speces const uint32_t DevicePlutoSDR::bbLPRxLowLimitFreq = 200000; // 200 kHz diff --git a/devices/plutosdr/deviceplutosdrbox.cpp b/devices/plutosdr/deviceplutosdrbox.cpp index 48065b571..d59e168ad 100644 --- a/devices/plutosdr/deviceplutosdrbox.cpp +++ b/devices/plutosdr/deviceplutosdrbox.cpp @@ -79,6 +79,7 @@ void DevicePlutoSDRBox::set_params(DeviceType devType, const char *attr = 0; std::size_t pos; int ret; + int type; pos = it->find('='); @@ -101,15 +102,35 @@ void DevicePlutoSDRBox::set_params(DeviceType devType, if (chn) { ret = iio_channel_attr_write(chn, attr, val.c_str()); + type = 0; } else if (iio_device_find_attr(dev, attr)) { ret = iio_device_attr_write(dev, attr, val.c_str()); + type = 1; } else { ret = iio_device_debug_attr_write(dev, attr, val.c_str()); + type = 2; } if (ret < 0) { - std::cerr << "DevicePlutoSDRBox::set_params: Unable to write attribute " << key << ": " << ret << std::endl; + std::string item; + + switch (type) + { + case 0: + item = "channel"; + break; + case 1: + item = "device"; + break; + case 2: + item = "debug"; + break; + default: + item = "unknown"; + break; + } + std::cerr << "DevicePlutoSDRBox::set_params: Unable to write " << item << " attribute " << key << "=" << val << ": " << ret << std::endl; } } } @@ -352,6 +373,7 @@ bool DevicePlutoSDRBox::getRxSampleRates(SampleRates& sampleRates) std::string srStr; if (get_param(DEVICE_PHY, "rx_path_rates", srStr)) { + qDebug("DevicePlutoSDRBox::getRxSampleRates: %s", srStr.c_str()); return parseSampleRates(srStr, sampleRates); } else { return false; @@ -382,12 +404,12 @@ bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates { try { - sampleRates.m_bbRate = boost::lexical_cast(desc_match[1]) + 1; - sampleRates.m_addaConnvRate = boost::lexical_cast(desc_match[2]) + 1; - sampleRates.m_hb3Rate = boost::lexical_cast(desc_match[3]) + 1; - sampleRates.m_hb2Rate = boost::lexical_cast(desc_match[4]) + 1; - sampleRates.m_hb1Rate = boost::lexical_cast(desc_match[5]) + 1; - sampleRates.m_firRate = boost::lexical_cast(desc_match[6]) + 1; + sampleRates.m_bbRate = boost::lexical_cast(desc_match[1]); + sampleRates.m_addaConnvRate = boost::lexical_cast(desc_match[2]); + sampleRates.m_hb3Rate = boost::lexical_cast(desc_match[3]); + sampleRates.m_hb2Rate = boost::lexical_cast(desc_match[4]); + sampleRates.m_hb1Rate = boost::lexical_cast(desc_match[5]); + sampleRates.m_firRate = boost::lexical_cast(desc_match[6]); return true; } catch (const boost::bad_lexical_cast &e) @@ -402,65 +424,106 @@ bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates } } -void DevicePlutoSDRBox::setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain) +void DevicePlutoSDRBox::setSampleRate(uint32_t sampleRate) +{ + char buff[100]; + std::vector params; + snprintf(buff, sizeof(buff), "in_voltage_sampling_frequency=%d", sampleRate); + params.push_back(std::string(buff)); + snprintf(buff, sizeof(buff), "out_voltage_sampling_frequency=%d", sampleRate); + params.push_back(std::string(buff)); + set_params(DEVICE_PHY, params); // set end point frequency first + m_devSampleRate = sampleRate; +} + +void DevicePlutoSDRBox::setFIR(uint32_t log2IntDec, uint32_t bw, int gain) { SampleRates sampleRates; std::ostringstream ostr; uint32_t nbTaps; double normalizedBW; + uint32_t intdec = 1<<(log2IntDec > 2 ? 2 : log2IntDec); // set a dummy minimal filter first to get the sample rates right - formatFIRHeader(ostr, use, intdec, gain); + setFIREnable(false); // disable first + + formatFIRHeader(ostr, intdec, gain); formatFIRCoefficients(ostr, 16, 0.5); setFilter(ostr.str()); ostr.str(""); // reset string stream - if (use == USE_RX) - { - if (!getRxSampleRates(sampleRates)) { - return; - } + setFIREnable(true); // re-enable - uint32_t nbGroups = sampleRates.m_addaConnvRate / 16; - nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8; - normalizedBW = ((float) bw) / sampleRates.m_hb1Rate; - normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW; + if (!getRxSampleRates(sampleRates)) { + return; } - else - { - if (!getTxSampleRates(sampleRates)) { - return; - } - uint32_t nbGroups = sampleRates.m_addaConnvRate / 16; - nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8; - nbTaps = intdec == 1 ? (nbTaps > 64 ? 64 : nbTaps) : nbTaps; - normalizedBW = ((float) bw) / sampleRates.m_hb1Rate; - normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW; - } + setFIREnable(false); // disable again + + uint32_t nbGroups = sampleRates.m_addaConnvRate / 16; + nbTaps = nbGroups*8 > 128 ? 128 : nbGroups*8; + nbTaps = intdec == 1 ? (nbTaps > 64 ? 64 : nbTaps) : nbTaps; + normalizedBW = ((float) bw) / sampleRates.m_hb1Rate; + normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW; + + qDebug("DevicePlutoSDRBox::setFIR: intdec: %u gain: %d nbTaps: %u BWin: %u BW: %f (%f)", + intdec, + gain, + nbTaps, + bw, + normalizedBW*sampleRates.m_hb1Rate, + normalizedBW); // set the right filter - formatFIRHeader(ostr, use, intdec, gain); + formatFIRHeader(ostr, intdec, gain); formatFIRCoefficients(ostr, nbTaps, normalizedBW); setFilter(ostr.str()); + + m_lpfFIRlog2Decim = log2IntDec; + m_lpfFIRBW = bw; + m_lpfFIRGain = gain; } -void DevicePlutoSDRBox::formatFIRHeader(std::ostringstream& ostr, DeviceUse use, uint32_t intdec, int32_t gain) +void DevicePlutoSDRBox::setFIREnable(bool enable) { - ostr << (use == USE_RX ? "RX 1" : "TX 1") << " GAIN " << gain << " DEC " << intdec << std::endl; + char buff[100]; + std::vector params; + snprintf(buff, sizeof(buff), "in_out_voltage_filter_fir_en=%d", enable ? 1 : 0); + params.push_back(std::string(buff)); + set_params(DEVICE_PHY, params); + m_lpfFIREnable = enable; +} + +void DevicePlutoSDRBox::setLOPPMTenths(int ppmTenths) +{ + char buff[100]; + std::vector params; + int64_t newXO = m_xoInitial + ((m_xoInitial*ppmTenths) / 10000000L); + snprintf(buff, sizeof(buff), "xo_correction=%ld", newXO); + params.push_back(std::string(buff)); + set_params(DEVICE_PHY, params); + m_LOppmTenths = ppmTenths; +} + +void DevicePlutoSDRBox::formatFIRHeader(std::ostringstream& ostr,uint32_t intdec, int32_t gain) +{ + ostr << "RX 3 GAIN " << gain << " DEC " << intdec << std::endl; + ostr << "TX 3 GAIN " << gain << " INT " << intdec << std::endl; } void DevicePlutoSDRBox::formatFIRCoefficients(std::ostringstream& ostr, uint32_t nbTaps, double normalizedBW) { double *fcoeffs = new double[nbTaps]; - WFIR::BasicFIR(fcoeffs, nbTaps, WFIR::LPF, 0.0, normalizedBW, WFIR::wtBLACKMAN_HARRIS, 0.0); + WFIR::BasicFIR(fcoeffs, nbTaps, WFIR::LPF, normalizedBW, 0.0, WFIR::wtBLACKMAN_HARRIS, 0.0); for (unsigned int i = 0; i < nbTaps; i++) { - ostr << (uint16_t) (fcoeffs[i] * 32768.0) << std::endl; + ostr << (int16_t) (fcoeffs[i] * 32768.0) << ", " << (int16_t) (fcoeffs[i] * 32768.0) << std::endl; } + + delete[] fcoeffs; } void DevicePlutoSDRBox::getXO() @@ -477,4 +540,41 @@ void DevicePlutoSDRBox::getXO() } } +bool DevicePlutoSDRBox::getRSSI(std::string& rssiStr, unsigned int chan) +{ + chan = chan % 2; + char buff[20]; + snprintf(buff, sizeof(buff), "in_voltage%d_rssi", chan); + return get_param(DEVICE_PHY, buff, rssiStr); +} + +bool DevicePlutoSDRBox::fetchTemp() +{ + std::string temp_mC_str; + + if (get_param(DEVICE_PHY, "in_temp0_input", temp_mC_str)) + { + try + { + uint32_t temp_mC = boost::lexical_cast(temp_mC_str); + m_temp = temp_mC / 1000.0; + return true; + } + catch (const boost::bad_lexical_cast &e) + { + std::cerr << "PlutoSDRDevice::getTemp: bad conversion to numeric" << std::endl; + return false; + } + } + else + { + return false; + } +} + +bool DevicePlutoSDRBox::getRateGovernors(std::string& rateGovernors) +{ + return get_param(DEVICE_PHY, "trx_rate_governor", rateGovernors); +} + diff --git a/devices/plutosdr/deviceplutosdrbox.h b/devices/plutosdr/deviceplutosdrbox.h index c0938ac38..5fefef1a3 100644 --- a/devices/plutosdr/deviceplutosdrbox.h +++ b/devices/plutosdr/deviceplutosdrbox.h @@ -52,6 +52,13 @@ public: uint32_t m_firRate; //!< Rate of FIR filter (Rx: out, Tx: in) - this is the host/device communication sample rate }; + uint64_t m_devSampleRate; //!< Host interface sample rate + int32_t m_LOppmTenths; //!< XO correction + bool m_lpfFIREnable; //!< enable digital lowpass FIR filter + float m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz) + uint32_t m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2) + int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB) + DevicePlutoSDRBox(const std::string& uri); ~DevicePlutoSDRBox(); bool isValid() const { return m_valid; } @@ -80,8 +87,14 @@ public: char* txBufferFirst(); bool getRxSampleRates(SampleRates& sampleRates); bool getTxSampleRates(SampleRates& sampleRates); - void setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain); - int64_t getInitialXO() const { return m_xoInitial; } + void setSampleRate(uint32_t sampleRate); + void setFIR(uint32_t intdec, uint32_t bw, int gain); + void setFIREnable(bool enable); + void setLOPPMTenths(int ppmTenths); + bool getRSSI(std::string& rssiStr, unsigned int chan); + bool fetchTemp(); + float getTemp() const { return m_temp; } + bool getRateGovernors(std::string& rateGovernors); private: struct iio_context *m_ctx; @@ -94,10 +107,11 @@ private: struct iio_buffer *m_txBuf; bool m_valid; int64_t m_xoInitial; + float m_temp; bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates); void setFilter(const std::string& filterConfigStr); - void formatFIRHeader(std::ostringstream& str, DeviceUse use, uint32_t intdec, int32_t gain); + void formatFIRHeader(std::ostringstream& str, uint32_t intdec, int32_t gain); void formatFIRCoefficients(std::ostringstream& str, uint32_t nbTaps, double normalizedBW); void getXO(); }; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index e8f6be5ae..021e083c1 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -28,6 +28,7 @@ #define PLUTOSDR_BLOCKSIZE (1024*1024) //complex samples per buffer (must be multiple of 64) +MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgConfigurePlutoSDR, Message) MESSAGE_CLASS_DEFINITION(PlutoSDRInput::MsgFileRecord, Message) PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) : @@ -38,17 +39,23 @@ PlutoSDRInput::PlutoSDRInput(DeviceSourceAPI *deviceAPI) : m_plutoRxBuffer(0), m_plutoSDRInputThread(0) { + suspendBuddies(); + openDevice(); + resumeBuddies(); + char recFileNameCStr[30]; sprintf(recFileNameCStr, "test_%d.sdriq", m_deviceAPI->getDeviceUID()); m_fileSink = new FileRecord(std::string(recFileNameCStr)); m_deviceAPI->addSink(m_fileSink); } - PlutoSDRInput::~PlutoSDRInput() { m_deviceAPI->removeSink(m_fileSink); delete m_fileSink; + suspendBuddies(); + closeDevice(); + resumeBuddies(); } bool PlutoSDRInput::start() @@ -247,20 +254,21 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo bool suspendOwnThread = false; bool ownThreadWasRunning = false; bool suspendAllOtherThreads = false; // All others means Tx in fact - bool firFilterSet = false; DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); // determine if buddies threads or own thread need to be suspended - // change of global baseband sample rate affecting all buddies can occur if + // changes affecting all buddies can occur if // - device to host sample rate is changed - // - rate governor is changed - // - FIR filter decimation is changed // - FIR filter is enabled or disabled + // - FIR filter is changed + // - LO correction is changed if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || - (m_settings.m_rateGovernor != settings.m_rateGovernor) || + (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || - (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) + (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) || + (settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) || + (m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { suspendAllOtherThreads = true; suspendOwnThread = true; @@ -307,47 +315,16 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo m_deviceAPI->configureCorrections(settings.m_dcBlock, m_settings.m_iqCorrection); } - // Change affecting device sample rate chain potentially affecting other buddies device/host sample rate + // Change affecting device sample rate chain and other buddies if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || - (m_settings.m_rateGovernor != settings.m_rateGovernor) || + (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || - (m_settings.m_lpfFIREnable != settings.m_lpfFIREnable) || force) + (settings.m_lpfFIRBW != m_settings.m_lpfFIRBW) || + (settings.m_lpfFIRGain != m_settings.m_lpfFIRGain) || force) { - std::vector params; - params.push_back(QString(tr("in_voltage_sampling_frequency=%1").arg(settings.m_devSampleRate)).toStdString()); - QString rateGovStr; - PlutoSDRInputSettings::translateGovernor(settings.m_rateGovernor, rateGovStr); - params.push_back(QString(tr("trx_rate_governor=%1").arg(rateGovStr)).toStdString()); - plutoBox->set_params(DevicePlutoSDRBox::DEVICE_PHY, params); // set end point frequency and rate governor first - - // Unless unconditionally forced to change settings change FIR settings if FIR is enabled AND - // - FIR was not enabled before OR - // - Host interface sample rate has changed OR - // - Decimation chain rate governor has changed OR - // - FIR decimation has changed - if ((settings.m_lpfFIREnable && (!m_settings.m_lpfFIREnable - || (m_settings.m_devSampleRate != settings.m_devSampleRate) - || (m_settings.m_rateGovernor != settings.m_rateGovernor) - || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim))) || force) - { - plutoBox->setFIR(DevicePlutoSDRBox::USE_RX, (1<setFIR(DevicePlutoSDRBox::USE_RX, (1<set_params(DevicePlutoSDRBox::DEVICE_PHY, params); // eventually enable/disable FIR - } + plutoBox->setSampleRate(settings.m_devSampleRate); // set end point frequency first + plutoBox->setFIR(settings.m_lpfFIRlog2Decim, settings.m_lpfFIRBW, settings.m_lpfFIRGain); + plutoBox->setFIREnable(settings.m_lpfFIREnable); // eventually enable/disable FIR plutoBox->getRxSampleRates(m_deviceSampleRates); // pick up possible new rates qDebug() << "PlutoSDRInput::applySettings: BBPLL: " << m_deviceSampleRates.m_bbRate @@ -386,9 +363,7 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo if ((m_settings.m_LOppmTenths != settings.m_LOppmTenths) || force) { - int64_t newXO = plutoBox->getInitialXO() + ((plutoBox->getInitialXO()*settings.m_LOppmTenths) / 10000000L); - params.push_back(QString(tr("xo_correction=%1").arg(newXO)).toStdString()); - paramsToSet = true; + plutoBox->setLOPPMTenths(settings.m_LOppmTenths); } if ((m_settings.m_centerFrequency != settings.m_centerFrequency) || force) @@ -476,5 +451,26 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo m_deviceAPI->getDeviceInputMessageQueue()->push(notif); } - return false; + return true; +} + +void PlutoSDRInput::getRSSI(std::string& rssiStr) +{ + DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); + + if (!plutoBox->getRSSI(rssiStr, 0)) { + rssiStr = "xxx dB"; + } +} + +bool PlutoSDRInput::fetchTemperature() +{ + DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); + return plutoBox->fetchTemp(); +} + +float PlutoSDRInput::getTemperature() +{ + DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); + return plutoBox->getTemp(); } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.h b/plugins/samplesource/plutosdrinput/plutosdrinput.h index e86e3ac63..c6a6a17aa 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.h @@ -87,6 +87,9 @@ public: virtual bool handleMessage(const Message& message); uint32_t getADCSampleRate() const { return m_deviceSampleRates.m_addaConnvRate; } + void getRSSI(std::string& rssiStr); + bool fetchTemperature(); + float getTemperature(); private: DeviceSourceAPI *m_deviceAPI; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp index 0d4d24668..3babafe47 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.cpp @@ -15,7 +15,12 @@ /////////////////////////////////////////////////////////////////////////////////// #include +#include +#include +#include "dsp/dspengine.h" +#include "dsp/dspcommands.h" +#include "gui/glspectrum.h" #include "device/devicesourceapi.h" #include "plutosdr/deviceplutosdr.h" #include "plutosdrinput.h" @@ -31,7 +36,9 @@ PlutoSDRInputGui::PlutoSDRInputGui(DeviceSourceAPI *deviceAPI, QWidget* parent) m_sampleSource(NULL), m_sampleRate(0), m_deviceCenterFrequency(0), - m_lastEngineState((DSPDeviceSourceEngine::State)-1) + m_lastEngineState((DSPDeviceSourceEngine::State)-1), + m_doApplySettings(true), + m_statusCounter(0) { m_sampleSource = new PlutoSDRInput(m_deviceAPI); m_deviceAPI->setSource(m_sampleSource); @@ -49,9 +56,12 @@ PlutoSDRInputGui::PlutoSDRInputGui(DeviceSourceAPI *deviceAPI, QWidget* parent) ui->lpFIR->setColorMapper(ColorMapper(ColorMapper::GrayYellow)); ui->lpFIR->setValueRange(5, 1U, 56000U); // will be dynamically recalculated - ui->hwDecimLabel->setText(QString::fromUtf8("H\u2193")); ui->swDecimLabel->setText(QString::fromUtf8("S\u2193")); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); m_statusTimer.start(500); @@ -103,9 +113,10 @@ bool PlutoSDRInputGui::deserialize(const QByteArray& data) { if(m_settings.deserialize(data)) { -// displaySettings(); -// m_forceSettings = true; -// sendSettings(); + blockApplySettings(true); + displaySettings(); + blockApplySettings(false); + sendSettings(true); return true; } else @@ -115,7 +126,258 @@ bool PlutoSDRInputGui::deserialize(const QByteArray& data) } } -bool PlutoSDRInputGui::handleMessage(const Message& message) +bool PlutoSDRInputGui::handleMessage(const Message& message __attribute__((unused))) { return false; } + +void PlutoSDRInputGui::on_startStop_toggled(bool checked) +{ + if (checked) + { + if (m_deviceAPI->initAcquisition()) + { + m_deviceAPI->startAcquisition(); + DSPEngine::instance()->startAudioOutput(); + } + } + else + { + m_deviceAPI->stopAcquisition(); + DSPEngine::instance()->stopAudioOutput(); + } +} + +void PlutoSDRInputGui::on_record_toggled(bool checked) +{ + if (checked) { + ui->record->setStyleSheet("QToolButton { background-color : red; }"); + } else { + ui->record->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + } + + PlutoSDRInput::MsgFileRecord* message = PlutoSDRInput::MsgFileRecord::create(checked); + m_sampleSource->getInputMessageQueue()->push(message); +} + +void PlutoSDRInputGui::on_centerFrequency_changed(quint64 value) +{ + m_settings.m_centerFrequency = value * 1000; + sendSettings(); +} + +void PlutoSDRInputGui::on_loPPM_valueChanged(int value) +{ + m_settings.m_LOppmTenths = value; + sendSettings(); +} + +void PlutoSDRInputGui::on_dcOffset_toggled(bool checked) +{ + m_settings.m_dcBlock = checked; + sendSettings(); +} + +void PlutoSDRInputGui::on_iqImbalance_toggled(bool checked) +{ + m_settings.m_iqCorrection = checked; + sendSettings(); +} + +void PlutoSDRInputGui::on_swDecim_currentIndexChanged(int index) +{ + m_settings.m_log2Decim = index > 6 ? 6 : index; + sendSettings(); +} + +void PlutoSDRInputGui::on_fcPos_currentIndexChanged(int index) +{ + m_settings.m_fcPos = (PlutoSDRInputSettings::fcPos_t) (index > 2 ? 2 : index); + sendSettings(); +} + +void PlutoSDRInputGui::on_sampleRate_changed(quint64 value) +{ + m_settings.m_devSampleRate = value; + sendSettings(); +} + +void PlutoSDRInputGui::on_lpf_changed(quint64 value) +{ + m_settings.m_lpfBW = value * 1000; + sendSettings(); +} + +void PlutoSDRInputGui::on_lpFIREnable_toggled(bool checked) +{ + m_settings.m_lpfFIREnable = checked; + sendSettings(); +} + +void PlutoSDRInputGui::on_lpFIR_changed(quint64 value) +{ + m_settings.m_lpfFIRBW = value * 1000; + sendSettings(); +} + +void PlutoSDRInputGui::on_lpFIRDecimation_currentIndexChanged(int index) +{ + m_settings.m_lpfFIRlog2Decim = index > 2 ? 2 : index; + sendSettings(); +} + +void PlutoSDRInputGui::on_lpFIRGain_currentIndexChanged(int index) +{ + m_settings.m_lpfFIRGain = 6*(index > 1 ? 1 : index) - 6; + sendSettings(); +} + +void PlutoSDRInputGui::on_gainMode_currentIndexChanged(int index) +{ + m_settings.m_gainMode = (PlutoSDRInputSettings::GainMode) (index < PlutoSDRInputSettings::GAIN_END ? index : 0); + sendSettings(); +} + +void PlutoSDRInputGui::on_gain_valueChanged(int value) +{ + m_settings.m_gain = value; + sendSettings(); +} + +void PlutoSDRInputGui::on_antenna_currentIndexChanged(int index) +{ + m_settings.m_antennaPath = (PlutoSDRInputSettings::RFPath) (index < PlutoSDRInputSettings::RFPATH_END ? index : 0); + sendSettings(); +} + +void PlutoSDRInputGui::displaySettings() +{ + ui->centerFrequency->setValue(m_settings.m_centerFrequency / 1000); + ui->sampleRate->setValue(m_settings.m_devSampleRate); + + ui->dcOffset->setChecked(m_settings.m_dcBlock); + ui->iqImbalance->setChecked(m_settings.m_iqCorrection); + + ui->swDecim->setCurrentIndex(m_settings.m_log2Decim); + + ui->lpf->setValue(m_settings.m_lpfBW / 1000); + + ui->lpFIREnable->setChecked(m_settings.m_lpfFIREnable); + ui->lpFIR->setValue(m_settings.m_lpfFIRBW / 1000); + ui->lpFIRDecimation->setCurrentIndex(m_settings.m_lpfFIRlog2Decim); + ui->lpFIRGain->setCurrentIndex((m_settings.m_lpfFIRGain + 6)/6); + + ui->gainMode->setCurrentIndex((int) m_settings.m_gainMode); + ui->gain->setValue(m_settings.m_gain); + ui->gainText->setText(tr("%1").arg(m_settings.m_gain)); + + ui->antenna->setCurrentIndex((int) m_settings.m_antennaPath); +} + +void PlutoSDRInputGui::sendSettings(bool forceSettings) +{ + m_forceSettings = forceSettings; + if(!m_updateTimer.isActive()) { m_updateTimer.start(100); } +} + +void PlutoSDRInputGui::updateHardware() +{ + if (m_doApplySettings) + { + qDebug() << "PlutoSDRInputGui::updateHardware"; + PlutoSDRInput::MsgConfigurePlutoSDR* message = PlutoSDRInput::MsgConfigurePlutoSDR::create(m_settings, m_forceSettings); + m_sampleSource->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); + } +} + +void PlutoSDRInputGui::blockApplySettings(bool block) +{ + m_doApplySettings = !block; +} + +void PlutoSDRInputGui::updateStatus() +{ + int state = m_deviceAPI->state(); + + if(m_lastEngineState != state) + { + switch(state) + { + case DSPDeviceSourceEngine::StNotStarted: + ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); + break; + case DSPDeviceSourceEngine::StIdle: + ui->startStop->setStyleSheet("QToolButton { background-color : blue; }"); + break; + case DSPDeviceSourceEngine::StRunning: + ui->startStop->setStyleSheet("QToolButton { background-color : green; }"); + break; + case DSPDeviceSourceEngine::StError: + ui->startStop->setStyleSheet("QToolButton { background-color : red; }"); + QMessageBox::information(this, tr("Message"), m_deviceAPI->errorMessage()); + break; + default: + break; + } + + m_lastEngineState = state; + } + + if (m_statusCounter % 2 == 0) // 1s + { + uint32_t adcRate = ((PlutoSDRInput *) m_sampleSource)->getADCSampleRate(); + + if (adcRate < 100000000) { + ui->adcRateLabel->setText(tr("%1k").arg(QString::number(adcRate / 1000.0f, 'g', 5))); + } else { + ui->adcRateLabel->setText(tr("%1M").arg(QString::number(adcRate / 1000000.0f, 'g', 5))); + } + } + + if (m_statusCounter % 4 == 0) // 2s + { + std::string rssiStr; + ((PlutoSDRInput *) m_sampleSource)->getRSSI(rssiStr); + ui->rssiText->setText(QString::fromStdString(rssiStr)); + } + + if (m_statusCounter % 10 == 0) // 5s + { + if (m_deviceAPI->isBuddyLeader()) { + ((PlutoSDRInput *) m_sampleSource)->fetchTemperature(); + } + + ui->temperatureText->setText(tr("%1C").arg(QString::number(((PlutoSDRInput *) m_sampleSource)->getTemperature(), 'f', 0))); + } + + m_statusCounter++; +} + +void PlutoSDRInputGui::handleDSPMessages() +{ + Message* message; + + while ((message = m_deviceAPI->getDeviceOutputMessageQueue()->pop()) != 0) + { + if (DSPSignalNotification::match(*message)) + { + qDebug("LimeSDRInputGUI::handleMessagesToGUI: message: %s", message->getIdentifier()); + DSPSignalNotification* notif = (DSPSignalNotification*) message; + m_sampleRate = notif->getSampleRate(); + m_deviceCenterFrequency = notif->getCenterFrequency(); + qDebug("LimeSDRInputGUI::handleMessagesToGUI: SampleRate: %d, CenterFrequency: %llu", notif->getSampleRate(), notif->getCenterFrequency()); + updateSampleRateAndFrequency(); + + delete message; + } + } +} + +void PlutoSDRInputGui::updateSampleRateAndFrequency() +{ + m_deviceAPI->getSpectrum()->setSampleRate(m_sampleRate); + m_deviceAPI->getSpectrum()->setCenterFrequency(m_deviceCenterFrequency); + ui->deviceRateLabel->setText(tr("%1k").arg(QString::number(m_sampleRate / 1000.0f, 'g', 5))); +} diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h index 79fb70d2b..679853de9 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.h @@ -60,6 +60,35 @@ private: int m_sampleRate; quint64 m_deviceCenterFrequency; //!< Center frequency in device int m_lastEngineState; + bool m_doApplySettings; + uint32_t m_statusCounter; + + void displaySettings(); + void sendSettings(bool forceSettings = false); + void blockApplySettings(bool block); + void updateSampleRateAndFrequency(); + +private slots: + void on_startStop_toggled(bool checked); + void on_record_toggled(bool checked); + void on_centerFrequency_changed(quint64 value); + void on_loPPM_valueChanged(int value); + void on_dcOffset_toggled(bool checked); + void on_iqImbalance_toggled(bool checked); + void on_swDecim_currentIndexChanged(int index); + void on_fcPos_currentIndexChanged(int index); + void on_sampleRate_changed(quint64 value); + void on_lpf_changed(quint64 value); + void on_lpFIREnable_toggled(bool checked); + void on_lpFIR_changed(quint64 value); + void on_lpFIRDecimation_currentIndexChanged(int index); + void on_lpFIRGain_currentIndexChanged(int index); + void on_gainMode_currentIndexChanged(int index); + void on_gain_valueChanged(int value); + void on_antenna_currentIndexChanged(int index); + void updateHardware(); + void updateStatus(); + void handleDSPMessages(); }; #endif /* PLUGINS_SAMPLESOURCE_PLUTOSDRINPUT_PLUTOSDRINPUTGUI_H_ */ diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui index 49ffff8cc..648beb56a 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui +++ b/plugins/samplesource/plutosdrinput/plutosdrinputgui.ui @@ -301,42 +301,6 @@ 2 - - - - Hw - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - - - - - 50 - 16777215 - - - - Hardware decimation governor - - - 0 - - - - 2 - - - - - 3 - - - - @@ -613,14 +577,14 @@ - + kHz - + 50 @@ -648,7 +612,7 @@ - + 50 @@ -658,11 +622,6 @@ FIR gain (dB) - - - -12 - - -6 @@ -673,11 +632,6 @@ 0 - - - +6 - - @@ -704,7 +658,7 @@ 2 - + 54 @@ -922,8 +876,17 @@ + + + 65 + 0 + + - -100.0 dB + 100.00 dB + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp index 24de677e6..0563403c3 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp @@ -31,13 +31,12 @@ void PlutoSDRInputSettings::resetToDefaults() m_fcPos = FC_POS_CENTER; m_LOppmTenths = 0; m_log2Decim = 0; - m_devSampleRate = 1536 * 1000; - m_rateGovernor = RATEGOV_NORMAL; + m_devSampleRate = 2500 * 1000; m_dcBlock = false; m_iqCorrection = false; m_lpfBW = 1500000.0f; m_lpfFIREnable = false; - m_lpfFIRBW = 500000.0f; + m_lpfFIRBW = 500000U; m_lpfFIRlog2Decim = 0; m_gain = 40; m_antennaPath = RFPATH_A_BAL; @@ -53,12 +52,11 @@ QByteArray PlutoSDRInputSettings::serialize() const s.writeU32(3, m_lpfFIRlog2Decim); s.writeU32(4, m_log2Decim); s.writeS32(5, m_fcPos); - s.writeS32(6, m_rateGovernor); s.writeBool(7, m_dcBlock); s.writeBool(8, m_iqCorrection); s.writeFloat(9, m_lpfBW); s.writeBool(10, m_lpfFIREnable); - s.writeFloat(11, m_lpfFIRBW); + s.writeU32(11, m_lpfFIRBW); s.writeU64(12, m_devSampleRate); s.writeU32(13, m_gain); s.writeS32(14, (int) m_antennaPath); @@ -97,17 +95,11 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data) } else { m_fcPos = (fcPos_t) intval; } - d.readS32(6, &intval, 0); - if ((intval >= 0) && (intval < (int) RATEGOV_END)) { - m_rateGovernor = (RateGovernor) intval; - } else { - m_rateGovernor = RATEGOV_NORMAL; - } d.readBool(7, &m_dcBlock, false); d.readBool(8, &m_iqCorrection, false); d.readFloat(9, &m_lpfBW, 1500000.0f); d.readBool(10, &m_lpfFIREnable, false); - d.readFloat(11, &m_lpfFIRBW, 500000.0f); + d.readU32(11, &m_lpfFIRBW, 500000U); d.readU64(12, &m_devSampleRate, 1536000U); d.readU32(13, &m_gain, 40); d.readS32(14, &intval, 0); @@ -132,22 +124,6 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data) } } -void PlutoSDRInputSettings::translateGovernor(RateGovernor gov, QString& s) -{ - switch(gov) - { - case RATEGOV_NORMAL: - s = "normal"; - break; - case RATEGOV_HIGHOSR: - s = "highest_osr"; - break; - default: - s = "highest_osr"; - break; - } -} - void PlutoSDRInputSettings::translateRFPath(RFPath path, QString& s) { switch(path) diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h index 7a0f6ba02..36bb2b14b 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h @@ -52,27 +52,21 @@ struct PlutoSDRInputSettings { GAIN_END } GainMode; - typedef enum { - RATEGOV_NORMAL, - RATEGOV_HIGHOSR, - RATEGOV_END - } RateGovernor; - // global settings to be saved quint64 m_centerFrequency; - quint64 m_devSampleRate; - RateGovernor m_rateGovernor; - // channel settings + // common device settings + quint64 m_devSampleRate; //!< Host interface sample rate + qint32 m_LOppmTenths; //!< XO correction + bool m_lpfFIREnable; //!< enable digital lowpass FIR filter + quint32 m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz) + quint32 m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2) + int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB) + // individual channel settings fcPos_t m_fcPos; - qint32 m_LOppmTenths; bool m_dcBlock; bool m_iqCorrection; quint32 m_log2Decim; float m_lpfBW; //!< analog lowpass filter bandwidth (Hz) - bool m_lpfFIREnable; //!< enable digital lowpass FIR filter - float m_lpfFIRBW; //!< digital lowpass FIR filter bandwidth (Hz) - quint32 m_lpfFIRlog2Decim; //!< digital lowpass FIR filter log2 of decimation factor (0..2) - int m_lpfFIRGain; //!< digital lowpass FIR filter gain (dB) uint32_t m_gain; //!< "hardware" gain RFPath m_antennaPath; GainMode m_gainMode; @@ -82,7 +76,6 @@ struct PlutoSDRInputSettings { void resetToDefaults(); QByteArray serialize() const; bool deserialize(const QByteArray& data); - static void translateGovernor(RateGovernor gov, QString& s); static void translateRFPath(RFPath path, QString& s); static void translateGainMode(GainMode mod, QString& s); };