diff --git a/devices/plutosdr/deviceplutosdrbox.cpp b/devices/plutosdr/deviceplutosdrbox.cpp index 92d48dc57..6ac8dfdd5 100644 --- a/devices/plutosdr/deviceplutosdrbox.cpp +++ b/devices/plutosdr/deviceplutosdrbox.cpp @@ -15,7 +15,6 @@ /////////////////////////////////////////////////////////////////////////////////// #include -#include #include #include #include @@ -23,6 +22,7 @@ #include #include +#include "dsp/wfir.h" #include "deviceplutosdrbox.h" DevicePlutoSDRBox::DevicePlutoSDRBox(const std::string& uri) : @@ -397,13 +397,20 @@ bool DevicePlutoSDRBox::parseSampleRates(const std::string& rateStr, SampleRates } } -void DevicePlutoSDRBox::set_filterBW(DeviceUse use, uint32_t intdec, uint32_t bw) +void DevicePlutoSDRBox::setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain) { SampleRates sampleRates; std::ostringstream ostr; uint32_t nbTaps; - float normalizedBW; + double normalizedBW; + + // set a dummy minimal filter first to get the sample rates right + + formatFIRHeader(ostr, use, intdec, gain); + formatFIRCoefficients(ostr, 16, 0.5); + setFilter(ostr.str()); + ostr.str(""); // reset string stream if (use == USE_RX) { @@ -428,7 +435,27 @@ void DevicePlutoSDRBox::set_filterBW(DeviceUse use, uint32_t intdec, uint32_t bw normalizedBW = ((float) bw) / sampleRates.m_hb1Rate; normalizedBW = normalizedBW < 0.1 ? 0.1 : normalizedBW > 0.9 ? 0.9 : normalizedBW; } + + // set the right filter + + formatFIRHeader(ostr, use, intdec, gain); + formatFIRCoefficients(ostr, nbTaps, normalizedBW); + setFilter(ostr.str()); +} + +void DevicePlutoSDRBox::formatFIRHeader(std::ostringstream& ostr, DeviceUse use, uint32_t intdec, int32_t gain) +{ + ostr << use == USE_RX ? "RX 1" : "TX 1" << " GAIN " << gain << " DEC " << 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); + + for (int i = 0; i < nbTaps; i++) { + ostr << (uint16_t) (fcoeffs[i] * 32768.0) << std::endl; + } } - diff --git a/devices/plutosdr/deviceplutosdrbox.h b/devices/plutosdr/deviceplutosdrbox.h index d6922e3d4..ebac08a7a 100644 --- a/devices/plutosdr/deviceplutosdrbox.h +++ b/devices/plutosdr/deviceplutosdrbox.h @@ -17,6 +17,7 @@ #ifndef DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ #define DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ +#include #include #include #include "deviceplutosdrscan.h" @@ -79,7 +80,7 @@ public: char* txBufferFirst(); bool getRxSampleRates(SampleRates& sampleRates); bool getTxSampleRates(SampleRates& sampleRates); - void set_filterBW(DeviceUse use, uint32_t intdec, uint32_t bw); + void setFIR(DeviceUse use, uint32_t intdec, uint32_t bw, int gain); private: struct iio_context *m_ctx; @@ -93,7 +94,9 @@ private: bool m_valid; bool parseSampleRates(const std::string& rateStr, SampleRates& sampleRates); - void set_filter(const std::string &filterConfigStr); + void set_filter(const std::string& filterConfigStr); + void formatFIRHeader(std::ostringstream& str, DeviceUse use, uint32_t intdec, int32_t gain); + void formatFIRCoefficients(std::ostringstream& str, uint32_t nbTaps, double normalizedBW); }; #endif /* DEVICES_PLUTOSDR_DEVICEPLUTOSDRBOX_H_ */ diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp index e1f19a7a1..dd651492f 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.cpp @@ -242,11 +242,13 @@ void PlutoSDRInput::resumeBuddies() bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool force) { bool forwardChangeOwnDSP = false; - bool forwardChangeAllDSP = false; + bool forwardChangeOtherDSP = false; bool suspendOwnThread = false; bool ownThreadWasRunning = false; bool suspendAllOtherThreads = false; // All others means Tx in fact bool doCalibration = false; + bool firFilterSet = false; + DevicePlutoSDRBox *plutoBox = m_deviceShared.m_deviceParams->getBox(); // determine if buddies threads or own thread need to be suspended @@ -299,7 +301,7 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo // TODO: apply settings (all cases) - // Change affecting device baseband sample rate potentially affecting all buddies device/host sample rate + // Change affecting device sample rate chain potentially affecting other buddies device/host sample rate if ((m_settings.m_devSampleRate != settings.m_devSampleRate) || (m_settings.m_rateGovernor != settings.m_rateGovernor) || (m_settings.m_lpfFIRlog2Decim != settings.m_lpfFIRlog2Decim) || @@ -310,10 +312,71 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo QString rateGovStr; PlutoSDRInputSettings::translateGovernor(settings.m_rateGovernor, rateGovStr); params.push_back(QString(tr("trx_rate_governor=%1").arg(rateGovStr)).toStdString()); - params.push_back(QString(tr("in_voltage_filter_fir_en=%1").arg(settings.m_lpfFIREnable ? 1 : 0)).toStdString()); - forwardChangeAllDSP = true; + 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->set_filterBW(DevicePlutoSDRBox::USE_RX, (1<set_filterBW(DevicePlutoSDRBox::USE_RX, (1<set_params(DevicePlutoSDRBox::DEVICE_PHY, params); // eventually enable/disable FIR + } + + plutoBox->getRxSampleRates(m_deviceSampleRates); // pick up possible new rates + qDebug() << "PlutoSDRInput::applySettings: BBPLL: " << m_deviceSampleRates.m_bbRate + << " ADC: " << m_deviceSampleRates.m_addaConnvRate + << " -HB3-> " << m_deviceSampleRates.m_hb3Rate + << " -HB2-> " << m_deviceSampleRates.m_hb2Rate + << " -HB1-> " << m_deviceSampleRates.m_hb1Rate + << " -FIR-> " << m_deviceSampleRates.m_firRate; + + forwardChangeOtherDSP = true; + forwardChangeOwnDSP = (m_settings.m_devSampleRate != settings.m_devSampleRate); } + if ((m_settings.m_log2Decim != settings.m_log2Decim) || force) + { + if (m_plutoSDRInputThread != 0) + { + m_plutoSDRInputThread->setLog2Decimation(settings.m_log2Decim); + qDebug() << "PlutoSDRInput::applySettings: set soft decimation to " << (1< params; + params.push_back(QString(tr("in_voltage_sampling_frequency=%1").arg(settings.m_centerFrequency)).toStdString()); + plutoBox->set_params(DevicePlutoSDRBox::DEVICE_PHY, params); + + forwardChangeOwnDSP = true; + } + + m_settings = settings; + if (suspendAllOtherThreads) { const std::vector& sinkBuddies = m_deviceAPI->getSinkBuddies(); @@ -336,5 +399,17 @@ bool PlutoSDRInput::applySettings(const PlutoSDRInputSettings& settings, bool fo } } + // TODO: forward changes to other (Tx) DSP + + if (forwardChangeOwnDSP) + { + qDebug("PlutoSDRInput::applySettings: forward change to self"); + + int sampleRate = m_settings.m_devSampleRate/(1<handleMessage(*notif); // forward to file sink + m_deviceAPI->getDeviceInputMessageQueue()->push(notif); + } + return false; } diff --git a/plugins/samplesource/plutosdrinput/plutosdrinput.h b/plugins/samplesource/plutosdrinput/plutosdrinput.h index 388bc0095..e86e3ac63 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinput.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinput.h @@ -86,6 +86,8 @@ public: virtual bool handleMessage(const Message& message); + uint32_t getADCSampleRate() const { return m_deviceSampleRates.m_addaConnvRate; } + private: DeviceSourceAPI *m_deviceAPI; FileRecord *m_fileSink; @@ -95,6 +97,7 @@ public: DevicePlutoSDRShared m_deviceShared; struct iio_buffer *m_plutoRxBuffer; PlutoSDRInputThread *m_plutoSDRInputThread; + DevicePlutoSDRBox::SampleRates m_deviceSampleRates; QMutex m_mutex; bool openDevice(); diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp index 8ad076065..d7545a0df 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.cpp @@ -49,6 +49,7 @@ QByteArray PlutoSDRInputSettings::serialize() const SimpleSerializer s(1); s.writeS32(1, m_LOppmTenths); + s.writeS32(2, m_lpfFIRGain); s.writeU32(3, m_lpfFIRlog2Decim); s.writeU32(4, m_log2Decim); s.writeS32(5, m_fcPos); @@ -82,6 +83,7 @@ bool PlutoSDRInputSettings::deserialize(const QByteArray& data) uint32_t uintval; d.readS32(1, &m_LOppmTenths, 0); + d.readS32(2, &m_lpfFIRGain, 0); d.readU32(3, &uintval, 0); if (uintval > 2) { m_lpfFIRlog2Decim = 2; diff --git a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h index 8a560d8f2..d0a8c92c2 100644 --- a/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h +++ b/plugins/samplesource/plutosdrinput/plutosdrinputsettings.h @@ -72,6 +72,7 @@ struct PlutoSDRInputSettings { 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;