mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-17 23:28:50 -05:00
Remote channel sink: decimation and shift: core changes
This commit is contained in:
parent
07c5bd19b8
commit
111c035c09
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -78,6 +78,7 @@ private:
|
||||
|
||||
void blockApplySettings(bool block);
|
||||
void applySettings(bool force = false);
|
||||
void applyChannelSettings();
|
||||
void displaySettings();
|
||||
void displayRateAndShift();
|
||||
void updateTxDelayTime();
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <dsp/downchannelizer.h>
|
||||
#include "dsp/inthalfbandfilter.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "dsp/hbfilterchainconverter.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QDebug>
|
||||
@ -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<unsigned int>& stageIndexes)
|
||||
void DownChannelizer::applySetting(unsigned int log2Decim, unsigned int filterChainHash)
|
||||
{
|
||||
m_filterChainSetMode = true;
|
||||
std::vector<unsigned int> 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<unsigned int>& stageIndexes)
|
||||
void DownChannelizer::setFilterChain(const std::vector<unsigned int>& stageIndexes)
|
||||
{
|
||||
// filters are described from lower to upper level but the chain is constructed the other way round
|
||||
std::vector<unsigned int>::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()
|
||||
|
@ -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<unsigned int>& getStageIndexes() { return m_stageIndexes; }
|
||||
unsigned int getLog2Decim() const { return m_log2Decim; }
|
||||
unsigned int getFilterChainHash() const { return m_filterChainHash; }
|
||||
|
||||
private:
|
||||
std::vector<unsigned int> 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<FilterStage*> 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<unsigned int>& 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<unsigned int>& stageIndexes); //!< returns offset in ratio of sample rate
|
||||
void setFilterChain(const std::vector<unsigned int>& stageIndexes);
|
||||
void freeFilterChain();
|
||||
void debugFilterChain();
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user