mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-05-24 03:02:29 -04:00
Up channelizer: implemented direct setting of filter chain
This commit is contained in:
parent
3a5bc0ac3a
commit
e55f33ffc9
@ -25,6 +25,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
MESSAGE_CLASS_DEFINITION(UpChannelizer::MsgChannelizerNotification, Message)
|
MESSAGE_CLASS_DEFINITION(UpChannelizer::MsgChannelizerNotification, Message)
|
||||||
|
MESSAGE_CLASS_DEFINITION(UpChannelizer::MsgSetChannelizer, Message)
|
||||||
|
|
||||||
UpChannelizer::UpChannelizer(BasebandSampleSource* sampleSource) :
|
UpChannelizer::UpChannelizer(BasebandSampleSource* sampleSource) :
|
||||||
m_sampleSource(sampleSource),
|
m_sampleSource(sampleSource),
|
||||||
@ -157,6 +158,14 @@ bool UpChannelizer::handleMessage(const Message& cmd)
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (MsgSetChannelizer::match(cmd))
|
||||||
|
{
|
||||||
|
MsgSetChannelizer& chan = (MsgSetChannelizer&) cmd;
|
||||||
|
qDebug() << "UpChannelizer::handleMessage: MsgSetChannelizer";
|
||||||
|
applySetting(chan.getStageIndexes());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
@ -208,6 +217,30 @@ void UpChannelizer::applyConfiguration()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UpChannelizer::applySetting(const std::vector<unsigned int>& stageIndexes)
|
||||||
|
{
|
||||||
|
m_mutex.lock();
|
||||||
|
|
||||||
|
freeFilterChain();
|
||||||
|
|
||||||
|
m_currentCenterFrequency = m_outputSampleRate * setFilterChain(stageIndexes);
|
||||||
|
|
||||||
|
m_mutex.unlock();
|
||||||
|
|
||||||
|
m_currentInputSampleRate = m_outputSampleRate / (1 << m_filterStages.size());
|
||||||
|
m_requestedInputSampleRate = m_currentInputSampleRate;
|
||||||
|
|
||||||
|
qDebug() << "UpChannelizer::applySetting in=" << m_outputSampleRate
|
||||||
|
<< ", out=" << m_currentInputSampleRate
|
||||||
|
<< ", fc=" << m_currentCenterFrequency;
|
||||||
|
|
||||||
|
if (m_sampleSource != 0)
|
||||||
|
{
|
||||||
|
MsgChannelizerNotification *notif = MsgChannelizerNotification::create(m_outputSampleRate, m_currentInputSampleRate, m_currentCenterFrequency);
|
||||||
|
m_sampleSource->getInputMessageQueue()->push(notif);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_SSE4_1
|
#ifdef USE_SSE4_1
|
||||||
UpChannelizer::FilterStage::FilterStage(Mode mode) :
|
UpChannelizer::FilterStage::FilterStage(Mode mode) :
|
||||||
m_filter(new IntHalfbandFilterEO1<UPCHANNELIZER_HB_FILTER_ORDER>),
|
m_filter(new IntHalfbandFilterEO1<UPCHANNELIZER_HB_FILTER_ORDER>),
|
||||||
@ -266,21 +299,17 @@ bool UpChannelizer::signalContainsChannel(Real sigStart, Real sigEnd, Real chanS
|
|||||||
Real UpChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd)
|
Real UpChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd)
|
||||||
{
|
{
|
||||||
Real sigBw = sigEnd - sigStart;
|
Real sigBw = sigEnd - sigStart;
|
||||||
Real safetyMargin = sigBw / 20;
|
|
||||||
Real rot = sigBw / 4;
|
Real rot = sigBw / 4;
|
||||||
Sample s;
|
Sample s;
|
||||||
|
|
||||||
safetyMargin = 0;
|
|
||||||
|
|
||||||
qDebug() << "UpChannelizer::createFilterChain: start:"
|
qDebug() << "UpChannelizer::createFilterChain: start:"
|
||||||
<< " sig: [" << sigStart << ":" << sigEnd << "]"
|
<< " sig: [" << sigStart << ":" << sigEnd << "]"
|
||||||
<< " BW: " << sigBw
|
<< " BW: " << sigBw
|
||||||
<< " chan: [" << chanStart << ":" << chanEnd << "]"
|
<< " chan: [" << chanStart << ":" << chanEnd << "]"
|
||||||
<< " rot: " << rot
|
<< " rot: " << rot;
|
||||||
<< " safety: " << safetyMargin;
|
|
||||||
|
|
||||||
// check if it fits into the left half
|
// check if it fits into the left half
|
||||||
if(signalContainsChannel(sigStart + safetyMargin, sigStart + sigBw / 2.0 - safetyMargin, chanStart, chanEnd))
|
if(signalContainsChannel(sigStart, sigStart + sigBw / 2.0, chanStart, chanEnd))
|
||||||
{
|
{
|
||||||
qDebug() << "UpChannelizer::createFilterChain: take left half (rotate by +1/4 and decimate by 2):"
|
qDebug() << "UpChannelizer::createFilterChain: take left half (rotate by +1/4 and decimate by 2):"
|
||||||
<< " [" << m_filterStages.size() << "]"
|
<< " [" << m_filterStages.size() << "]"
|
||||||
@ -291,7 +320,7 @@ Real UpChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanStart
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check if it fits into the right half
|
// check if it fits into the right half
|
||||||
if(signalContainsChannel(sigEnd - sigBw / 2.0f + safetyMargin, sigEnd - safetyMargin, chanStart, chanEnd))
|
if(signalContainsChannel(sigEnd - sigBw / 2.0f, sigEnd, chanStart, chanEnd))
|
||||||
{
|
{
|
||||||
qDebug() << "UpChannelizer::createFilterChain: take right half (rotate by -1/4 and decimate by 2):"
|
qDebug() << "UpChannelizer::createFilterChain: take right half (rotate by -1/4 and decimate by 2):"
|
||||||
<< " [" << m_filterStages.size() << "]"
|
<< " [" << m_filterStages.size() << "]"
|
||||||
@ -303,7 +332,7 @@ Real UpChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanStart
|
|||||||
|
|
||||||
// check if it fits into the center
|
// check if it fits into the center
|
||||||
// Was: if(signalContainsChannel(sigStart + rot + safetyMargin, sigStart + rot + sigBw / 2.0f - safetyMargin, chanStart, chanEnd)) {
|
// Was: if(signalContainsChannel(sigStart + rot + safetyMargin, sigStart + rot + sigBw / 2.0f - safetyMargin, chanStart, chanEnd)) {
|
||||||
if(signalContainsChannel(sigStart + rot + safetyMargin, sigEnd - rot - safetyMargin, chanStart, chanEnd))
|
if(signalContainsChannel(sigStart + rot, sigEnd - rot, chanStart, chanEnd))
|
||||||
{
|
{
|
||||||
qDebug() << "UpChannelizer::createFilterChain: take center half (decimate by 2):"
|
qDebug() << "UpChannelizer::createFilterChain: take center half (decimate by 2):"
|
||||||
<< " [" << m_filterStages.size() << "]"
|
<< " [" << m_filterStages.size() << "]"
|
||||||
@ -324,6 +353,38 @@ Real UpChannelizer::createFilterChain(Real sigStart, Real sigEnd, Real chanStart
|
|||||||
return ofs;
|
return ofs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double UpChannelizer::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)
|
||||||
|
{
|
||||||
|
m_filterStages.push_back(new FilterStage(FilterStage::ModeLowerHalf));
|
||||||
|
ofs -= ofs_stage;
|
||||||
|
}
|
||||||
|
else if (*rit == 1)
|
||||||
|
{
|
||||||
|
m_filterStages.push_back(new FilterStage(FilterStage::ModeCenter));
|
||||||
|
}
|
||||||
|
else if (*rit == 2)
|
||||||
|
{
|
||||||
|
m_filterStages.push_back(new FilterStage(FilterStage::ModeUpperHalf));
|
||||||
|
ofs += ofs_stage;
|
||||||
|
}
|
||||||
|
|
||||||
|
ofs_stage /= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ofs;
|
||||||
|
}
|
||||||
|
|
||||||
void UpChannelizer::freeFilterChain()
|
void UpChannelizer::freeFilterChain()
|
||||||
{
|
{
|
||||||
for(FilterStages::iterator it = m_filterStages.begin(); it != m_filterStages.end(); ++it)
|
for(FilterStages::iterator it = m_filterStages.begin(); it != m_filterStages.end(); ++it)
|
||||||
|
@ -63,6 +63,20 @@ public:
|
|||||||
qint64 m_frequencyOffset;
|
qint64 m_frequencyOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SDRBASE_API MsgSetChannelizer : public Message {
|
||||||
|
MESSAGE_CLASS_DECLARATION
|
||||||
|
|
||||||
|
public:
|
||||||
|
MsgSetChannelizer() :
|
||||||
|
Message()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
std::vector<unsigned int>& getStageIndexes() { return m_stageIndexes; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::vector<unsigned int> m_stageIndexes;
|
||||||
|
};
|
||||||
|
|
||||||
UpChannelizer(BasebandSampleSource* sampleSink);
|
UpChannelizer(BasebandSampleSource* sampleSink);
|
||||||
virtual ~UpChannelizer();
|
virtual ~UpChannelizer();
|
||||||
|
|
||||||
@ -115,8 +129,10 @@ protected:
|
|||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
|
|
||||||
void applyConfiguration();
|
void applyConfiguration();
|
||||||
|
void applySetting(const std::vector<unsigned int>& stageIndexes);
|
||||||
bool signalContainsChannel(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd) const;
|
bool signalContainsChannel(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd) const;
|
||||||
Real createFilterChain(Real sigStart, Real sigEnd, Real chanStart, Real chanEnd);
|
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 freeFilterChain();
|
void freeFilterChain();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user