diff --git a/plugins/channelrx/remotesink/remotesink.cpp b/plugins/channelrx/remotesink/remotesink.cpp index bf2e27de6..746ad62b6 100644 --- a/plugins/channelrx/remotesink/remotesink.cpp +++ b/plugins/channelrx/remotesink/remotesink.cpp @@ -44,6 +44,7 @@ MESSAGE_CLASS_DEFINITION(RemoteSink::MsgConfigureRemoteSink, Message) MESSAGE_CLASS_DEFINITION(RemoteSink::MsgSampleRateNotification, Message) +MESSAGE_CLASS_DEFINITION(RemoteSink::MsgConfigureChannelizer, Message) const QString RemoteSink::m_channelIdURI = "sdrangel.channel.remotesink"; const QString RemoteSink::m_channelId = "RemoteSink"; @@ -58,6 +59,7 @@ RemoteSink::RemoteSink(DeviceSourceAPI *deviceAPI) : m_sampleIndex(0), m_dataBlock(0), m_centerFrequency(0), + m_frequencyOffset(0), m_sampleRate(48000), m_nbBlocksFEC(0), m_txDelay(35), @@ -127,7 +129,7 @@ void RemoteSink::feed(const SampleVector::const_iterator& begin, const SampleVec RemoteMetaDataFEC metaData; gettimeofday(&tv, 0); - metaData.m_centerFrequency = m_centerFrequency; + metaData.m_centerFrequency = m_centerFrequency + (m_frequencyOffset/1000); // FIXME: precision issue metaData.m_sampleRate = m_sampleRate; metaData.m_sampleBytes = (SDR_RX_SAMP_SZ <= 16 ? 2 : 4); metaData.m_sampleBits = SDR_RX_SAMP_SZ; @@ -271,12 +273,7 @@ bool RemoteSink::handleMessage(const Message& cmd) } setTxDelay(m_settings.m_txDelay, m_settings.m_nbFECBlocks); - - if (m_guiMessageQueue) - { - MsgSampleRateNotification *msg = MsgSampleRateNotification::create(notif.getSampleRate()); - m_guiMessageQueue->push(msg); - } + m_frequencyOffset = notif.getFrequencyOffset(); return true; } @@ -290,6 +287,12 @@ bool RemoteSink::handleMessage(const Message& cmd) setCenterFrequency(notif.getCenterFrequency()); + if (m_guiMessageQueue) + { + MsgSampleRateNotification *msg = MsgSampleRateNotification::create(notif.getSampleRate()); + m_guiMessageQueue->push(msg); + } + return true; } else if (MsgConfigureRemoteSink::match(cmd)) @@ -300,6 +303,22 @@ bool RemoteSink::handleMessage(const Message& cmd) return true; } + else if (MsgConfigureChannelizer::match(cmd)) + { + MsgConfigureChannelizer& cfg = (MsgConfigureChannelizer&) cmd; + m_settings.m_log2Decim = cfg.getLog2Decim(); + m_settings.m_filterChainHash = cfg.getFilterChainHash(); + + qDebug() << "RemoteSink::handleMessage: MsgConfigureChannelizer:" + << " log2Decim: " << m_settings.m_log2Decim + << " filterChainHash: " << m_settings.m_filterChainHash; + + m_channelizer->set(m_channelizer->getInputMessageQueue(), + m_settings.m_log2Decim, + m_settings.m_filterChainHash); + + return true; + } else { return false; diff --git a/plugins/channelrx/remotesink/remotesink.h b/plugins/channelrx/remotesink/remotesink.h index 6499ec8b9..899fc0f9d 100644 --- a/plugins/channelrx/remotesink/remotesink.h +++ b/plugins/channelrx/remotesink/remotesink.h @@ -31,7 +31,7 @@ #include "dsp/basebandsamplesink.h" #include "channel/channelsinkapi.h" -#include "../remotesink/remotesinksettings.h" +#include "remotesinksettings.h" class QNetworkAccessManager; class QNetworkReply; @@ -86,6 +86,29 @@ public: int m_sampleRate; }; + class MsgConfigureChannelizer : public Message { + MESSAGE_CLASS_DECLARATION + + public: + int getLog2Decim() const { return m_log2Decim; } + int getFilterChainHash() const { return m_filterChainHash; } + + static MsgConfigureChannelizer* create(int sampleRate, int centerFrequency) + { + return new MsgConfigureChannelizer(sampleRate, centerFrequency); + } + + private: + unsigned int m_log2Decim; + unsigned int m_filterChainHash; + + MsgConfigureChannelizer(unsigned int log2Decim, int filterChainHash) : + Message(), + m_log2Decim(log2Decim), + m_filterChainHash(filterChainHash) + { } + }; + RemoteSink(DeviceSourceAPI *deviceAPI); virtual ~RemoteSink(); virtual void destroy() { delete this; } @@ -122,6 +145,7 @@ public: void setTxDelay(int txDelay, int nbBlocksFEC); void setDataAddress(const QString& address) { m_dataAddress = address; } void setDataPort(uint16_t port) { m_dataPort = port; } + void setChannelizer(unsigned int log2Decim, unsigned int filterChainHash); static const QString m_channelIdURI; static const QString m_channelId; @@ -147,6 +171,7 @@ private: QMutex m_dataBlockMutex; uint64_t m_centerFrequency; + int64_t m_frequencyOffset; uint32_t m_sampleRate; int m_nbBlocksFEC; int m_txDelay; diff --git a/plugins/channelrx/remotesink/remotesinkgui.cpp b/plugins/channelrx/remotesink/remotesinkgui.cpp index 56d55c716..38234bb24 100644 --- a/plugins/channelrx/remotesink/remotesinkgui.cpp +++ b/plugins/channelrx/remotesink/remotesinkgui.cpp @@ -86,7 +86,7 @@ bool RemoteSinkGUI::handleMessage(const Message& message) if (RemoteSink::MsgSampleRateNotification::match(message)) { RemoteSink::MsgSampleRateNotification& notif = (RemoteSink::MsgSampleRateNotification&) message; - m_channelMarker.setBandwidth(notif.getSampleRate()); + //m_channelMarker.setBandwidth(notif.getSampleRate()); m_sampleRate = notif.getSampleRate(); updateTxDelayTime(); displayRateAndShift(); @@ -168,6 +168,17 @@ void RemoteSinkGUI::applySettings(bool force) } } +void RemoteSinkGUI::applyChannelSettings() +{ + if (m_doApplySettings) + { + RemoteSink::MsgConfigureChannelizer *msgChan = RemoteSink::MsgConfigureChannelizer::create( + m_settings.m_log2Decim, + m_settings.m_filterChainHash); + m_remoteSink->getInputMessageQueue()->push(msgChan); + } +} + void RemoteSinkGUI::displaySettings() { m_channelMarker.blockSignals(true); @@ -363,6 +374,7 @@ void RemoteSinkGUI::applyPosition() ui->filterChainText->setText(s); displayRateAndShift(); + applyChannelSettings(); } void RemoteSinkGUI::tick() diff --git a/plugins/channelrx/remotesink/remotesinkgui.h b/plugins/channelrx/remotesink/remotesinkgui.h index 2b37290f6..693890a70 100644 --- a/plugins/channelrx/remotesink/remotesinkgui.h +++ b/plugins/channelrx/remotesink/remotesinkgui.h @@ -78,6 +78,7 @@ private: void blockApplySettings(bool block); void applySettings(bool force = false); + void applyChannelSettings(); void displaySettings(); void displayRateAndShift(); void updateTxDelayTime(); diff --git a/sdrbase/dsp/downchannelizer.cpp b/sdrbase/dsp/downchannelizer.cpp index e953c2899..eca3c074d 100644 --- a/sdrbase/dsp/downchannelizer.cpp +++ b/sdrbase/dsp/downchannelizer.cpp @@ -19,6 +19,7 @@ #include #include "dsp/inthalfbandfilter.h" #include "dsp/dspcommands.h" +#include "dsp/hbfilterchainconverter.h" #include #include @@ -27,6 +28,7 @@ MESSAGE_CLASS_DEFINITION(DownChannelizer::MsgChannelizerNotification, Message) MESSAGE_CLASS_DEFINITION(DownChannelizer::MsgSetChannelizer, Message) DownChannelizer::DownChannelizer(BasebandSampleSink* sampleSink) : + m_filterChainSetMode(false), m_sampleSink(sampleSink), m_inputSampleRate(0), m_requestedOutputSampleRate(0), @@ -49,6 +51,12 @@ void DownChannelizer::configure(MessageQueue* messageQueue, int sampleRate, int messageQueue->push(cmd); } +void DownChannelizer::set(MessageQueue* messageQueue, unsigned int log2Decim, unsigned int filterChainHash) +{ + Message* cmd = new MsgSetChannelizer(log2Decim, filterChainHash); + messageQueue->push(cmd); +} + void DownChannelizer::feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly) { if(m_sampleSink == 0) { @@ -119,7 +127,10 @@ bool DownChannelizer::handleMessage(const Message& cmd) DSPSignalNotification& notif = (DSPSignalNotification&) cmd; m_inputSampleRate = notif.getSampleRate(); qDebug() << "DownChannelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate; - applyConfiguration(); + + if (!m_filterChainSetMode) { + applyConfiguration(); + } if (m_sampleSink != 0) { @@ -148,7 +159,7 @@ bool DownChannelizer::handleMessage(const Message& cmd) { MsgSetChannelizer& chan = (MsgSetChannelizer&) cmd; qDebug() << "DownChannelizer::handleMessage: MsgSetChannelizer"; - applySetting(chan.getStageIndexes()); + applySetting(chan.getLog2Decim(), chan.getFilterChainHash()); return true; } @@ -166,6 +177,8 @@ bool DownChannelizer::handleMessage(const Message& cmd) void DownChannelizer::applyConfiguration() { + m_filterChainSetMode = false; + if (m_inputSampleRate == 0) { qDebug() << "DownChannelizer::applyConfiguration: m_inputSampleRate=0 aborting"; @@ -198,22 +211,26 @@ void DownChannelizer::applyConfiguration() } } -void DownChannelizer::applySetting(const std::vector& stageIndexes) +void DownChannelizer::applySetting(unsigned int log2Decim, unsigned int filterChainHash) { + m_filterChainSetMode = true; + std::vector stageIndexes; + m_currentCenterFrequency = m_inputSampleRate * HBFilterChainConverter::convertToIndexes(log2Decim, filterChainHash, stageIndexes); + m_requestedCenterFrequency = m_currentCenterFrequency; + m_mutex.lock(); - freeFilterChain(); - - m_currentCenterFrequency = m_inputSampleRate * setFilterChain(stageIndexes); - + setFilterChain(stageIndexes); m_mutex.unlock(); m_currentOutputSampleRate = m_inputSampleRate / (1 << m_filterStages.size()); m_requestedOutputSampleRate = m_currentOutputSampleRate; - qDebug() << "DownChannelizer::applySetting in=" << m_inputSampleRate - << ", out=" << m_currentOutputSampleRate - << ", fc=" << m_currentCenterFrequency; + qDebug() << "DownChannelizer::applySetting inputSampleRate:" << m_inputSampleRate + << " currentOutputSampleRate: " << m_currentOutputSampleRate + << " currentCenterFrequency: " << m_currentCenterFrequency + << " nb_filters: " << stageIndexes.size() + << " nb_stages: " << m_filterStages.size(); if (m_sampleSink != 0) { @@ -317,36 +334,24 @@ Real DownChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanSta return ofs; } -double DownChannelizer::setFilterChain(const std::vector& stageIndexes) +void DownChannelizer::setFilterChain(const std::vector& stageIndexes) { // filters are described from lower to upper level but the chain is constructed the other way round std::vector::const_reverse_iterator rit = stageIndexes.rbegin(); - double ofs = 0.0, ofs_stage = 0.25; // Each index is a base 3 number with 0 = low, 1 = center, 2 = high // Functions at upper level will convert a number to base 3 to describe the filter chain. Common converting // algorithms will go from LSD to MSD. This explains the reverse order. for (; rit != stageIndexes.rend(); ++rit) { - if (*rit == 0) - { + if (*rit == 0) { m_filterStages.push_back(new FilterStage(FilterStage::ModeLowerHalf)); - ofs -= ofs_stage; - } - else if (*rit == 1) - { + } else if (*rit == 1) { m_filterStages.push_back(new FilterStage(FilterStage::ModeCenter)); - } - else if (*rit == 2) - { + } else if (*rit == 2) { m_filterStages.push_back(new FilterStage(FilterStage::ModeUpperHalf)); - ofs += ofs_stage; } - - ofs_stage /= 2; } - - return ofs; } void DownChannelizer::freeFilterChain() diff --git a/sdrbase/dsp/downchannelizer.h b/sdrbase/dsp/downchannelizer.h index 54a067619..d256ecf2e 100644 --- a/sdrbase/dsp/downchannelizer.h +++ b/sdrbase/dsp/downchannelizer.h @@ -61,20 +61,25 @@ public: MESSAGE_CLASS_DECLARATION public: - MsgSetChannelizer() : - Message() + MsgSetChannelizer(unsigned int log2Decim, unsigned int filterChainHash) : + Message(), + m_log2Decim(log2Decim), + m_filterChainHash(filterChainHash) { } - std::vector& getStageIndexes() { return m_stageIndexes; } + unsigned int getLog2Decim() const { return m_log2Decim; } + unsigned int getFilterChainHash() const { return m_filterChainHash; } private: - std::vector m_stageIndexes; + unsigned int m_log2Decim; + unsigned int m_filterChainHash; }; DownChannelizer(BasebandSampleSink* sampleSink); virtual ~DownChannelizer(); void configure(MessageQueue* messageQueue, int sampleRate, int centerFrequency); + void set(MessageQueue* messageQueue, unsigned int log2Decim, unsigned int filterChainHash); int getInputSampleRate() const { return m_inputSampleRate; } int getRequestedCenterFrequency() const { return m_requestedCenterFrequency; } @@ -113,6 +118,7 @@ protected: }; typedef std::list FilterStages; FilterStages m_filterStages; + bool m_filterChainSetMode; BasebandSampleSink* m_sampleSink; //!< Demodulator int m_inputSampleRate; int m_requestedOutputSampleRate; @@ -123,10 +129,10 @@ protected: QMutex m_mutex; void applyConfiguration(); - void applySetting(const std::vector& stageIndexes); + void applySetting(unsigned int log2Decim, unsigned int filterChainHash); bool signalContainsChannel(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd) const; Real createFilterChain(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd); - double setFilterChain(const std::vector& stageIndexes); //!< returns offset in ratio of sample rate + void setFilterChain(const std::vector& stageIndexes); void freeFilterChain(); void debugFilterChain(); diff --git a/sdrbase/dsp/hbfilterchainconverter.cpp b/sdrbase/dsp/hbfilterchainconverter.cpp index 3afa37484..0cb7a58cc 100644 --- a/sdrbase/dsp/hbfilterchainconverter.cpp +++ b/sdrbase/dsp/hbfilterchainconverter.cpp @@ -56,6 +56,7 @@ double HBFilterChainConverter::convertToIndexes(unsigned int log2, unsigned int // continue shift with leading zeroes. ix has the number of leading zeroes. for (unsigned int i = 0; i < ix; i++) { + chainIndexes.push_back(0); shift -= shift_stage; shift_stage *= 2; }