mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-09-27 15:26:33 -04:00
Remote channel sink: decimation and shift: GUI changes
This commit is contained in:
parent
e55f33ffc9
commit
07c5bd19b8
1
debian/changelog
vendored
1
debian/changelog
vendored
@ -1,5 +1,6 @@
|
|||||||
sdrangel (4.5.6-1) unstable; urgency=medium
|
sdrangel (4.5.6-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* Remote channel sink: implemented decimation with possible center shift. Issue #331
|
||||||
* Remote input: fixed version display
|
* Remote input: fixed version display
|
||||||
* DSD demod: save PLL enable and autio mute in preset
|
* DSD demod: save PLL enable and autio mute in preset
|
||||||
|
|
||||||
|
@ -15,13 +15,15 @@
|
|||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
///////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#include "remotesinkgui.h"
|
#include <QLocale>
|
||||||
|
|
||||||
#include "device/devicesourceapi.h"
|
#include "device/devicesourceapi.h"
|
||||||
#include "device/deviceuiset.h"
|
#include "device/deviceuiset.h"
|
||||||
#include "gui/basicchannelsettingsdialog.h"
|
#include "gui/basicchannelsettingsdialog.h"
|
||||||
|
#include "dsp/hbfilterchainconverter.h"
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
|
#include "remotesinkgui.h"
|
||||||
#include "remotesink.h"
|
#include "remotesink.h"
|
||||||
#include "ui_remotesinkgui.h"
|
#include "ui_remotesinkgui.h"
|
||||||
|
|
||||||
@ -87,6 +89,7 @@ bool RemoteSinkGUI::handleMessage(const Message& message)
|
|||||||
m_channelMarker.setBandwidth(notif.getSampleRate());
|
m_channelMarker.setBandwidth(notif.getSampleRate());
|
||||||
m_sampleRate = notif.getSampleRate();
|
m_sampleRate = notif.getSampleRate();
|
||||||
updateTxDelayTime();
|
updateTxDelayTime();
|
||||||
|
displayRateAndShift();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (RemoteSink::MsgConfigureRemoteSink::match(message))
|
else if (RemoteSink::MsgConfigureRemoteSink::match(message))
|
||||||
@ -171,6 +174,7 @@ void RemoteSinkGUI::displaySettings()
|
|||||||
m_channelMarker.setCenterFrequency(0);
|
m_channelMarker.setCenterFrequency(0);
|
||||||
m_channelMarker.setTitle(m_settings.m_title);
|
m_channelMarker.setTitle(m_settings.m_title);
|
||||||
m_channelMarker.setBandwidth(m_sampleRate); // TODO
|
m_channelMarker.setBandwidth(m_sampleRate); // TODO
|
||||||
|
m_channelMarker.setMovable(false); // do not let user move the center arbitrarily
|
||||||
m_channelMarker.blockSignals(false);
|
m_channelMarker.blockSignals(false);
|
||||||
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
|
m_channelMarker.setColor(m_settings.m_rgbColor); // activate signal on the last setting only
|
||||||
|
|
||||||
@ -178,6 +182,8 @@ void RemoteSinkGUI::displaySettings()
|
|||||||
setWindowTitle(m_channelMarker.getTitle());
|
setWindowTitle(m_channelMarker.getTitle());
|
||||||
|
|
||||||
blockApplySettings(true);
|
blockApplySettings(true);
|
||||||
|
ui->decimationFactor->setCurrentIndex(m_settings.m_log2Decim);
|
||||||
|
ui->position->setValue(m_settings.m_filterChainHash);
|
||||||
ui->dataAddress->setText(m_settings.m_dataAddress);
|
ui->dataAddress->setText(m_settings.m_dataAddress);
|
||||||
ui->dataPort->setText(tr("%1").arg(m_settings.m_dataPort));
|
ui->dataPort->setText(tr("%1").arg(m_settings.m_dataPort));
|
||||||
QString s = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
QString s = QString::number(128 + m_settings.m_nbFECBlocks, 'f', 0);
|
||||||
@ -186,9 +192,21 @@ void RemoteSinkGUI::displaySettings()
|
|||||||
ui->txDelayText->setText(tr("%1%").arg(m_settings.m_txDelay));
|
ui->txDelayText->setText(tr("%1%").arg(m_settings.m_txDelay));
|
||||||
ui->txDelay->setValue(m_settings.m_txDelay);
|
ui->txDelay->setValue(m_settings.m_txDelay);
|
||||||
updateTxDelayTime();
|
updateTxDelayTime();
|
||||||
|
applyDecimation();
|
||||||
blockApplySettings(false);
|
blockApplySettings(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::displayRateAndShift()
|
||||||
|
{
|
||||||
|
int shift = m_shiftFrequencyFactor * m_sampleRate;
|
||||||
|
double channelSampleRate = ((double) m_sampleRate) / (1<<m_settings.m_log2Decim);
|
||||||
|
QLocale loc;
|
||||||
|
ui->offsetFrequencyText->setText(tr("%1 Hz").arg(loc.toString(shift)));
|
||||||
|
ui->channelRateText->setText(tr("%1k").arg(QString::number(channelSampleRate / 1000.0, 'g', 5)));
|
||||||
|
m_channelMarker.setCenterFrequency(shift);
|
||||||
|
m_channelMarker.setBandwidth(channelSampleRate);
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSinkGUI::leaveEvent(QEvent*)
|
void RemoteSinkGUI::leaveEvent(QEvent*)
|
||||||
{
|
{
|
||||||
m_channelMarker.setHighlighted(false);
|
m_channelMarker.setHighlighted(false);
|
||||||
@ -244,6 +262,18 @@ void RemoteSinkGUI::onMenuDialogCalled(const QPoint &p)
|
|||||||
applySettings();
|
applySettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::on_decimationFactor_currentIndexChanged(int index)
|
||||||
|
{
|
||||||
|
m_settings.m_log2Decim = index;
|
||||||
|
applyDecimation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::on_position_valueChanged(int value)
|
||||||
|
{
|
||||||
|
m_settings.m_filterChainHash = value;
|
||||||
|
applyPosition();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSinkGUI::on_dataAddress_returnPressed()
|
void RemoteSinkGUI::on_dataAddress_returnPressed()
|
||||||
{
|
{
|
||||||
m_settings.m_dataAddress = ui->dataAddress->text();
|
m_settings.m_dataAddress = ui->dataAddress->text();
|
||||||
@ -312,6 +342,29 @@ void RemoteSinkGUI::updateTxDelayTime()
|
|||||||
ui->txDelayTime->setText(tr("%1µs").arg(QString::number(delay*1e6, 'f', 0)));
|
ui->txDelayTime->setText(tr("%1µs").arg(QString::number(delay*1e6, 'f', 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::applyDecimation()
|
||||||
|
{
|
||||||
|
uint32_t maxHash = 1;
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < m_settings.m_log2Decim; i++) {
|
||||||
|
maxHash *= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->position->setMaximum(maxHash-1);
|
||||||
|
m_settings.m_filterChainHash = ui->position->value();
|
||||||
|
applyPosition();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteSinkGUI::applyPosition()
|
||||||
|
{
|
||||||
|
ui->filterChainIndex->setText(tr("%1").arg(m_settings.m_filterChainHash));
|
||||||
|
QString s;
|
||||||
|
m_shiftFrequencyFactor = HBFilterChainConverter::convertToString(m_settings.m_log2Decim, m_settings.m_filterChainHash, s);
|
||||||
|
ui->filterChainText->setText(s);
|
||||||
|
|
||||||
|
displayRateAndShift();
|
||||||
|
}
|
||||||
|
|
||||||
void RemoteSinkGUI::tick()
|
void RemoteSinkGUI::tick()
|
||||||
{
|
{
|
||||||
if (++m_tickCount == 20) { // once per second
|
if (++m_tickCount == 20) { // once per second
|
||||||
|
@ -64,6 +64,7 @@ private:
|
|||||||
RemoteSinkSettings m_settings;
|
RemoteSinkSettings m_settings;
|
||||||
int m_sampleRate;
|
int m_sampleRate;
|
||||||
quint64 m_deviceCenterFrequency; //!< Center frequency in device
|
quint64 m_deviceCenterFrequency; //!< Center frequency in device
|
||||||
|
double m_shiftFrequencyFactor; //!< Channel frequency shift factor
|
||||||
bool m_doApplySettings;
|
bool m_doApplySettings;
|
||||||
|
|
||||||
RemoteSink* m_remoteSink;
|
RemoteSink* m_remoteSink;
|
||||||
@ -78,13 +79,19 @@ private:
|
|||||||
void blockApplySettings(bool block);
|
void blockApplySettings(bool block);
|
||||||
void applySettings(bool force = false);
|
void applySettings(bool force = false);
|
||||||
void displaySettings();
|
void displaySettings();
|
||||||
|
void displayRateAndShift();
|
||||||
void updateTxDelayTime();
|
void updateTxDelayTime();
|
||||||
|
|
||||||
void leaveEvent(QEvent*);
|
void leaveEvent(QEvent*);
|
||||||
void enterEvent(QEvent*);
|
void enterEvent(QEvent*);
|
||||||
|
|
||||||
|
void applyDecimation();
|
||||||
|
void applyPosition();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void handleSourceMessages();
|
void handleSourceMessages();
|
||||||
|
void on_decimationFactor_currentIndexChanged(int index);
|
||||||
|
void on_position_valueChanged(int value);
|
||||||
void on_dataAddress_returnPressed();
|
void on_dataAddress_returnPressed();
|
||||||
void on_dataPort_returnPressed();
|
void on_dataPort_returnPressed();
|
||||||
void on_dataApplyButton_clicked(bool checked);
|
void on_dataApplyButton_clicked(bool checked);
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>320</width>
|
<width>320</width>
|
||||||
<height>100</height>
|
<height>157</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
@ -43,7 +43,7 @@
|
|||||||
<x>10</x>
|
<x>10</x>
|
||||||
<y>10</y>
|
<y>10</y>
|
||||||
<width>301</width>
|
<width>301</width>
|
||||||
<height>81</height>
|
<height>141</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -65,6 +65,188 @@
|
|||||||
<property name="bottomMargin">
|
<property name="bottomMargin">
|
||||||
<number>2</number>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="decimationLayer">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>3</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="decimationStageLayer">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="decimationLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Dec</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="decimationFactor">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>55</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Decimation factor</string>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>1</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>2</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>4</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>8</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>16</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>32</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>64</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="channelRateText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Effective channel rate (kS/s)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>0000k</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filterChainText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>50</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Filter chain stages left to right (L: low, C: center, H: high) </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>LLLLLL</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_2">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="offsetFrequencyText">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>85</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Offset frequency with thousands separator (Hz)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>-9,999,999 Hz</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="decimationShiftLayer">
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>10</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="positionLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Pos</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSlider" name="position">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Center frequency position</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>2</number>
|
||||||
|
</property>
|
||||||
|
<property name="pageStep">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="filterChainIndex">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Filter chain hash code</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>000</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="dataAddressLayout">
|
<layout class="QHBoxLayout" name="dataAddressLayout">
|
||||||
<item>
|
<item>
|
||||||
@ -292,19 +474,6 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
const PluginDescriptor RemoteSinkPlugin::m_pluginDescriptor = {
|
const PluginDescriptor RemoteSinkPlugin::m_pluginDescriptor = {
|
||||||
QString("Remote channel sink"),
|
QString("Remote channel sink"),
|
||||||
QString("4.5.2"),
|
QString("4.5.6"),
|
||||||
QString("(c) Edouard Griffiths, F4EXB"),
|
QString("(c) Edouard Griffiths, F4EXB"),
|
||||||
QString("https://github.com/f4exb/sdrangel"),
|
QString("https://github.com/f4exb/sdrangel"),
|
||||||
true,
|
true,
|
||||||
|
@ -42,6 +42,8 @@ void RemoteSinkSettings::resetToDefaults()
|
|||||||
m_dataPort = 9090;
|
m_dataPort = 9090;
|
||||||
m_rgbColor = QColor(140, 4, 4).rgb();
|
m_rgbColor = QColor(140, 4, 4).rgb();
|
||||||
m_title = "Remote sink";
|
m_title = "Remote sink";
|
||||||
|
m_log2Decim = 0;
|
||||||
|
m_filterChainHash = 0;
|
||||||
m_channelMarker = nullptr;
|
m_channelMarker = nullptr;
|
||||||
m_useReverseAPI = false;
|
m_useReverseAPI = false;
|
||||||
m_reverseAPIAddress = "127.0.0.1";
|
m_reverseAPIAddress = "127.0.0.1";
|
||||||
@ -64,6 +66,8 @@ QByteArray RemoteSinkSettings::serialize() const
|
|||||||
s.writeU32(9, m_reverseAPIPort);
|
s.writeU32(9, m_reverseAPIPort);
|
||||||
s.writeU32(10, m_reverseAPIDeviceIndex);
|
s.writeU32(10, m_reverseAPIDeviceIndex);
|
||||||
s.writeU32(11, m_reverseAPIChannelIndex);
|
s.writeU32(11, m_reverseAPIChannelIndex);
|
||||||
|
s.writeU32(12, m_log2Decim);
|
||||||
|
s.writeU32(13, m_filterChainHash);
|
||||||
|
|
||||||
return s.final();
|
return s.final();
|
||||||
}
|
}
|
||||||
@ -117,6 +121,9 @@ bool RemoteSinkSettings::deserialize(const QByteArray& data)
|
|||||||
m_reverseAPIDeviceIndex = tmp > 99 ? 99 : tmp;
|
m_reverseAPIDeviceIndex = tmp > 99 ? 99 : tmp;
|
||||||
d.readU32(11, &tmp, 0);
|
d.readU32(11, &tmp, 0);
|
||||||
m_reverseAPIChannelIndex = tmp > 99 ? 99 : tmp;
|
m_reverseAPIChannelIndex = tmp > 99 ? 99 : tmp;
|
||||||
|
d.readU32(12, &tmp, 0);
|
||||||
|
m_log2Decim = tmp > 6 ? 6 : tmp;
|
||||||
|
d.readU32(13, &m_filterChainHash, 0);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -37,6 +37,8 @@ struct RemoteSinkSettings
|
|||||||
uint16_t m_dataPort;
|
uint16_t m_dataPort;
|
||||||
quint32 m_rgbColor;
|
quint32 m_rgbColor;
|
||||||
QString m_title;
|
QString m_title;
|
||||||
|
uint32_t m_log2Decim;
|
||||||
|
uint32_t m_filterChainHash;
|
||||||
bool m_useReverseAPI;
|
bool m_useReverseAPI;
|
||||||
QString m_reverseAPIAddress;
|
QString m_reverseAPIAddress;
|
||||||
uint16_t m_reverseAPIPort;
|
uint16_t m_reverseAPIPort;
|
||||||
|
@ -46,6 +46,7 @@ set(sdrbase_SOURCES
|
|||||||
dsp/filerecord.cpp
|
dsp/filerecord.cpp
|
||||||
dsp/freqlockcomplex.cpp
|
dsp/freqlockcomplex.cpp
|
||||||
dsp/interpolator.cpp
|
dsp/interpolator.cpp
|
||||||
|
dsp/hbfilterchainconverter.cpp
|
||||||
dsp/hbfiltertraits.cpp
|
dsp/hbfiltertraits.cpp
|
||||||
dsp/lowpass.cpp
|
dsp/lowpass.cpp
|
||||||
dsp/nco.cpp
|
dsp/nco.cpp
|
||||||
@ -148,6 +149,7 @@ set(sdrbase_HEADERS
|
|||||||
dsp/filerecord.h
|
dsp/filerecord.h
|
||||||
dsp/freqlockcomplex.h
|
dsp/freqlockcomplex.h
|
||||||
dsp/gfft.h
|
dsp/gfft.h
|
||||||
|
dsp/hbfilterchainconverter.h
|
||||||
dsp/iirfilter.h
|
dsp/iirfilter.h
|
||||||
dsp/interpolator.h
|
dsp/interpolator.h
|
||||||
dsp/hbfiltertraits.h
|
dsp/hbfiltertraits.h
|
||||||
|
118
sdrbase/dsp/hbfilterchainconverter.cpp
Normal file
118
sdrbase/dsp/hbfilterchainconverter.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2019 F4EXB //
|
||||||
|
// written by Edouard Griffiths //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// (at your option) any later version. //
|
||||||
|
// //
|
||||||
|
// This program is distributed in the hope that it will be useful, //
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||||
|
// GNU General Public License V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include "hbfilterchainconverter.h"
|
||||||
|
|
||||||
|
double HBFilterChainConverter::convertToIndexes(unsigned int log2, unsigned int chainHash, std::vector<unsigned int>& chainIndexes)
|
||||||
|
{
|
||||||
|
chainIndexes.clear();
|
||||||
|
|
||||||
|
if (log2 == 0) {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int s = 1;
|
||||||
|
unsigned int d = 1;
|
||||||
|
unsigned int u = chainHash;
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < log2; i++)
|
||||||
|
{
|
||||||
|
s *= 3;
|
||||||
|
d *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
u %= s; // scale
|
||||||
|
unsigned int ix = log2;
|
||||||
|
double shift = 0.0;
|
||||||
|
double shift_stage = 1.0 / (1<<(log2+1));
|
||||||
|
|
||||||
|
// base3 conversion
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = u % 3;
|
||||||
|
chainIndexes.push_back(r);
|
||||||
|
shift += (r-1)*shift_stage;
|
||||||
|
shift_stage *= 2;
|
||||||
|
u /= 3;
|
||||||
|
ix--;
|
||||||
|
} while (u);
|
||||||
|
|
||||||
|
// continue shift with leading zeroes. ix has the number of leading zeroes.
|
||||||
|
for (unsigned int i = 0; i < ix; i++)
|
||||||
|
{
|
||||||
|
shift -= shift_stage;
|
||||||
|
shift_stage *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shift;
|
||||||
|
}
|
||||||
|
|
||||||
|
double HBFilterChainConverter::convertToString(unsigned int log2, unsigned int chainHash, QString& chainString)
|
||||||
|
{
|
||||||
|
if (log2 == 0)
|
||||||
|
{
|
||||||
|
chainString = "C";
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int s = 1;
|
||||||
|
unsigned int d = 1;
|
||||||
|
unsigned int u = chainHash;
|
||||||
|
chainString = "";
|
||||||
|
|
||||||
|
for (unsigned int i = 0; i < log2; i++)
|
||||||
|
{
|
||||||
|
s *= 3;
|
||||||
|
d *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
u %= s; // scale
|
||||||
|
unsigned int ix = log2;
|
||||||
|
double shift = 0.0;
|
||||||
|
double shift_stage = 1.0 / (1<<(log2+1));
|
||||||
|
|
||||||
|
// base3 conversion
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int r = u % 3;
|
||||||
|
|
||||||
|
if (r == 0) {
|
||||||
|
chainString = "L" + chainString;
|
||||||
|
} else if (r == 1) {
|
||||||
|
chainString = "C" + chainString;
|
||||||
|
} else if (r == 2) {
|
||||||
|
chainString = "H" + chainString;
|
||||||
|
}
|
||||||
|
|
||||||
|
shift += (r-1)*shift_stage;
|
||||||
|
shift_stage *= 2;
|
||||||
|
u /= 3;
|
||||||
|
ix--;
|
||||||
|
} while (u);
|
||||||
|
|
||||||
|
// continue shift with leading zeroes. ix has the number of leading zeroes.
|
||||||
|
for (unsigned int i = 0; i < ix; i++)
|
||||||
|
{
|
||||||
|
chainString = "L" + chainString;
|
||||||
|
shift -= shift_stage;
|
||||||
|
shift_stage *= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return shift;
|
||||||
|
}
|
39
sdrbase/dsp/hbfilterchainconverter.h
Normal file
39
sdrbase/dsp/hbfilterchainconverter.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Copyright (C) 2019 F4EXB //
|
||||||
|
// written by Edouard Griffiths //
|
||||||
|
// //
|
||||||
|
// This program is free software; you can redistribute it and/or modify //
|
||||||
|
// it under the terms of the GNU General Public License as published by //
|
||||||
|
// the Free Software Foundation as version 3 of the License, or //
|
||||||
|
// (at your option) any later version. //
|
||||||
|
// //
|
||||||
|
// This program is distributed in the hope that it will be useful, //
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||||
|
// GNU General Public License V3 for more details. //
|
||||||
|
// //
|
||||||
|
// You should have received a copy of the GNU General Public License //
|
||||||
|
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||||
|
///////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef SDRBASE_DSP_HBFILTERCHAINCONVERTER_H
|
||||||
|
#define SDRBASE_DSP_HBFILTERCHAINCONVERTER_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "export.h"
|
||||||
|
|
||||||
|
class QString;
|
||||||
|
|
||||||
|
class SDRBASE_API HBFilterChainConverter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Converts the chain hash as a base3 number each digit representing a filter stage from lower (LSD) to upper level (MSD)
|
||||||
|
// The corresponding log2 of decimation or interpolation factor is also the number of filter stages
|
||||||
|
// A vector of indexes as base3 digits is filled in (0: low band, 1: center band, : high band)
|
||||||
|
// The shift factor of center frequency is returned. The actual shift is obtained by multiplying this factor by the sample rate.
|
||||||
|
static double convertToIndexes(unsigned int log2, unsigned int chainHash, std::vector<unsigned int>& chainIndexes);
|
||||||
|
// Same but used only for display giving a string representation of the filter chain
|
||||||
|
static double convertToString(unsigned int log2, unsigned int chainHash, QString& chainString);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SDRBASE_DSP_HBFILTERCHAINCONVERTER_H
|
@ -96,6 +96,7 @@ SOURCES += audio/audiodevicemanager.cpp\
|
|||||||
dsp/filerecord.cpp\
|
dsp/filerecord.cpp\
|
||||||
dsp/freqlockcomplex.cpp\
|
dsp/freqlockcomplex.cpp\
|
||||||
dsp/interpolator.cpp\
|
dsp/interpolator.cpp\
|
||||||
|
dsp/hbfilterchainconverter.cpp \
|
||||||
dsp/hbfiltertraits.cpp\
|
dsp/hbfiltertraits.cpp\
|
||||||
dsp/lowpass.cpp\
|
dsp/lowpass.cpp\
|
||||||
dsp/nco.cpp\
|
dsp/nco.cpp\
|
||||||
@ -181,6 +182,7 @@ HEADERS += audio/audiodevicemanager.h\
|
|||||||
dsp/filerecord.h\
|
dsp/filerecord.h\
|
||||||
dsp/freqlockcomplex.h\
|
dsp/freqlockcomplex.h\
|
||||||
dsp/gfft.h\
|
dsp/gfft.h\
|
||||||
|
dsp/hbfilterchainconverter.h \
|
||||||
dsp/hbfiltertraits.h\
|
dsp/hbfiltertraits.h\
|
||||||
dsp/iirfilter.h\
|
dsp/iirfilter.h\
|
||||||
dsp/interpolator.h\
|
dsp/interpolator.h\
|
||||||
|
Loading…
Reference in New Issue
Block a user