diff --git a/devices/perseus/deviceperseusscan.cpp b/devices/perseus/deviceperseusscan.cpp
index 39233f17e..a416d75f4 100644
--- a/devices/perseus/deviceperseusscan.cpp
+++ b/devices/perseus/deviceperseusscan.cpp
@@ -33,7 +33,7 @@ void DevicePerseusScan::scan(int nbDevices)
for (int deviceIndex = 0; deviceIndex < nbDevices; deviceIndex++)
{
if ((descr = perseus_open(deviceIndex)) == 0) {
- qCritical("DevicePerseusScan::scan: open error: %s\n", perseus_errorstr());
+ qCritical("DevicePerseusScan::scan: open error: %s", perseus_errorstr());
continue;
}
diff --git a/plugins/samplesource/testsource/testsourcegui.cpp b/plugins/samplesource/testsource/testsourcegui.cpp
index f3454f2e5..e9a0e912d 100644
--- a/plugins/samplesource/testsource/testsourcegui.cpp
+++ b/plugins/samplesource/testsource/testsourcegui.cpp
@@ -57,6 +57,7 @@ TestSourceGui::TestSourceGui(DeviceUISet *deviceUISet, QWidget* parent) :
ui->sampleRate->setValueRange(7, 48000, 9999999);
ui->frequencyShift->setColorMapper(ColorMapper(ColorMapper::GrayGold));
ui->frequencyShift->setValueRange(false, 7, -9999999, 9999999);
+ ui->frequencyShiftLabel->setText(QString("%1").arg(QChar(0x94, 0x03)));
displaySettings();
@@ -212,6 +213,37 @@ void TestSourceGui::on_amplitudeFine_valueChanged(int value __attribute__((unuse
sendSettings();
}
+void TestSourceGui::on_modulation_currentIndexChanged(int index)
+{
+ if ((index < 0) || (index > TestSourceSettings::ModulationLast)) {
+ return;
+ }
+
+ m_settings.m_modulation = (TestSourceSettings::Modulation) index;
+ sendSettings();
+}
+
+void TestSourceGui::on_modulationFrequency_valueChanged(int value)
+{
+ m_settings.m_modulationTone = value;
+ ui->modulationFrequencyText->setText(QString("%1").arg(m_settings.m_modulationTone / 100.0, 0, 'f', 2));
+ sendSettings();
+}
+
+void TestSourceGui::on_amModulation_valueChanged(int value)
+{
+ m_settings.m_amModulation = value;
+ ui->amModulationText->setText(QString("%1").arg(m_settings.m_amModulation));
+ sendSettings();
+}
+
+void TestSourceGui::on_fmDeviation_valueChanged(int value)
+{
+ m_settings.m_fmDeviation = value;
+ ui->fmDeviationText->setText(QString("%1").arg(m_settings.m_fmDeviation / 10.0, 0, 'f', 1));
+ sendSettings();
+}
+
void TestSourceGui::on_dcBias_valueChanged(int value)
{
ui->dcBiasText->setText(QString(tr("%1 %").arg(value)));
@@ -354,6 +386,13 @@ void TestSourceGui::displaySettings()
ui->qBiasText->setText(QString(tr("%1 %").arg(qBiasPercent)));
ui->autoCorr->setCurrentIndex(m_settings.m_autoCorrOptions);
ui->sampleSize->blockSignals(false);
+ ui->modulation->setCurrentIndex((int) m_settings.m_modulation);
+ ui->modulationFrequency->setValue(m_settings.m_modulationTone);
+ ui->modulationFrequencyText->setText(QString("%1").arg(m_settings.m_modulationTone / 100.0, 0, 'f', 2));
+ ui->amModulation->setValue(m_settings.m_amModulation);
+ ui->amModulationText->setText(QString("%1").arg(m_settings.m_amModulation));
+ ui->fmDeviation->setValue(m_settings.m_fmDeviation);
+ ui->fmDeviationText->setText(QString("%1").arg(m_settings.m_fmDeviation / 10.0, 0, 'f', 1));
blockApplySettings(false);
}
diff --git a/plugins/samplesource/testsource/testsourcegui.h b/plugins/samplesource/testsource/testsourcegui.h
index eaac26484..3c0432d69 100644
--- a/plugins/samplesource/testsource/testsourcegui.h
+++ b/plugins/samplesource/testsource/testsourcegui.h
@@ -88,6 +88,10 @@ private slots:
void on_sampleSize_currentIndexChanged(int index);
void on_amplitudeCoarse_valueChanged(int value);
void on_amplitudeFine_valueChanged(int value);
+ void on_modulation_currentIndexChanged(int index);
+ void on_modulationFrequency_valueChanged(int value);
+ void on_amModulation_valueChanged(int value);
+ void on_fmDeviation_valueChanged(int value);
void on_dcBias_valueChanged(int value);
void on_iBias_valueChanged(int value);
void on_qBias_valueChanged(int value);
diff --git a/plugins/samplesource/testsource/testsourcegui.ui b/plugins/samplesource/testsource/testsourcegui.ui
index 89a4d59d4..13e13e02d 100644
--- a/plugins/samplesource/testsource/testsourcegui.ui
+++ b/plugins/samplesource/testsource/testsourcegui.ui
@@ -216,79 +216,6 @@
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
-
- -
-
-
-
-
-
- Shift
-
-
-
- -
-
-
-
- 0
- 0
-
-
-
-
- 32
- 16
-
-
-
-
- DejaVu Sans Mono
- 12
- false
-
-
-
- PointingHandCursor
-
-
- Shift from center frequency
-
-
-
- -
-
-
- Hz
-
-
-
- -
-
-
- Qt::Horizontal
-
-
-
- 40
- 20
-
-
-
-
-
@@ -382,15 +309,66 @@
+ -
+
+
+ Sz
+
+
+
+ -
+
+
+
+ 45
+ 16777215
+
+
+
+ Sample size
+
+
+ 0
+
+
-
+
+ 8
+
+
+ -
+
+ 12
+
+
+ -
+
+ 16
+
+
+
+
+ -
+
+
+ bits
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
- -
-
-
- Qt::Horizontal
-
-
-
-
@@ -409,7 +387,7 @@
- 28
+ 16
0
@@ -454,59 +432,7 @@
-
-
-
- Qt::Vertical
-
-
-
- -
-
-
- size
-
-
-
- -
-
-
-
- 45
- 16777215
-
-
-
- Sample size
-
-
- 0
-
-
-
-
- 8
-
-
- -
-
- 12
-
-
- -
-
- 16
-
-
-
-
- -
-
-
- bits
-
-
-
- -
-
+
Qt::Horizontal
@@ -518,8 +444,245 @@
+ -
+
+
+ Mod
+
+
+
+ -
+
+
+
+ 50
+ 16777215
+
+
+
+ Modulation
+
+
-
+
+ No
+
+
+ -
+
+ AM
+
+
+ -
+
+ FM
+
+
+
+
+ -
+
+
+
+ 22
+ 22
+
+
+
+ Modulation tone (kHz)
+
+
+ 1
+
+
+ 999
+
+
+ 1
+
+
+
+ -
+
+
+
+ 35
+ 0
+
+
+
+ Modulation tone value (kHz)
+
+
+ 0.00
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+ -
+
+
-
+
+
+
+ 16
+ 0
+
+
+
+ D
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 32
+ 16
+
+
+
+
+ DejaVu Sans Mono
+ 12
+ false
+
+
+
+ PointingHandCursor
+
+
+ Shift from center frequency
+
+
+
+ -
+
+
+ Hz
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ AM
+
+
+
+ -
+
+
+
+ 22
+ 22
+
+
+
+ AM modulation (%)
+
+
+ 1
+
+
+
+ -
+
+
+ AM modulation value (%)
+
+
+ 00
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ -
+
+
+ FM
+
+
+
+ -
+
+
+
+ 22
+ 22
+
+
+
+ FM deviation (kHz)
+
+
+ 1
+
+
+ 999
+
+
+ 1
+
+
+
+ -
+
+
+
+ 35
+ 0
+
+
+
+ FM deviation value (kHz)
+
+
+ 00.0
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
-
diff --git a/plugins/samplesource/testsource/testsourceinput.cpp b/plugins/samplesource/testsource/testsourceinput.cpp
index 605bebe23..5fb5cadcc 100644
--- a/plugins/samplesource/testsource/testsourceinput.cpp
+++ b/plugins/samplesource/testsource/testsourceinput.cpp
@@ -350,6 +350,34 @@ bool TestSourceInput::applySettings(const TestSourceSettings& settings, bool for
m_deviceAPI->getDeviceEngineInputMessageQueue()->push(notif);
}
+ if ((m_settings.m_modulationTone != settings.m_modulationTone) || force)
+ {
+ if (m_testSourceThread != 0) {
+ m_testSourceThread->setToneFrequency(settings.m_modulationTone * 10);
+ }
+ }
+
+ if ((m_settings.m_modulation != settings.m_modulation) || force)
+ {
+ if (m_testSourceThread != 0) {
+ m_testSourceThread->setModulation(settings.m_modulation);
+ }
+ }
+
+ if ((m_settings.m_amModulation != settings.m_amModulation) || force)
+ {
+ if (m_testSourceThread != 0) {
+ m_testSourceThread->setAMModulation(settings.m_amModulation / 100.0f);
+ }
+ }
+
+ if ((m_settings.m_fmDeviation != settings.m_fmDeviation) || force)
+ {
+ if (m_testSourceThread != 0) {
+ m_testSourceThread->setFMDeviation(settings.m_fmDeviation * 100.0f);
+ }
+ }
+
m_settings = settings;
return true;
}
diff --git a/plugins/samplesource/testsource/testsourcesettings.cpp b/plugins/samplesource/testsource/testsourcesettings.cpp
index 451b76be2..a78d81f92 100644
--- a/plugins/samplesource/testsource/testsourcesettings.cpp
+++ b/plugins/samplesource/testsource/testsourcesettings.cpp
@@ -33,6 +33,10 @@ void TestSourceSettings::resetToDefaults()
m_sampleSizeIndex = 0;
m_amplitudeBits = 127;
m_autoCorrOptions = AutoCorrNone;
+ m_modulation = ModulationNone;
+ m_modulationTone = 44; // 440 Hz
+ m_amModulation = 50; // 50%
+ m_fmDeviation = 50; // 5 kHz
m_dcFactor = 0.0f;
m_iFactor = 0.0f;
m_qFactor = 0.0f;
@@ -54,6 +58,10 @@ QByteArray TestSourceSettings::serialize() const
s.writeFloat(11, m_iFactor);
s.writeFloat(12, m_qFactor);
s.writeFloat(13, m_phaseImbalance);
+ s.writeS32(14, (int) m_modulation);
+ s.writeS32(15, m_modulationTone);
+ s.writeS32(16, m_amModulation);
+ s.writeS32(17, m_fmDeviation);
return s.final();
}
@@ -91,6 +99,17 @@ bool TestSourceSettings::deserialize(const QByteArray& data)
d.readFloat(11, &m_iFactor, 0.0f);
d.readFloat(12, &m_qFactor, 0.0f);
d.readFloat(13, &m_phaseImbalance, 0.0f);
+ d.readS32(14, &intval, 0);
+
+ if (intval < 0 || intval > (int) ModulationLast) {
+ m_modulation = ModulationNone;
+ } else {
+ m_modulation = (Modulation) intval;
+ }
+
+ d.readS32(15, &m_modulationTone, 44);
+ d.readS32(16, &m_amModulation, 50);
+ d.readS32(17, &m_fmDeviation, 50);
return true;
}
diff --git a/plugins/samplesource/testsource/testsourcesettings.h b/plugins/samplesource/testsource/testsourcesettings.h
index f18947ba4..d4c476703 100644
--- a/plugins/samplesource/testsource/testsourcesettings.h
+++ b/plugins/samplesource/testsource/testsourcesettings.h
@@ -31,6 +31,13 @@ struct TestSourceSettings {
AutoCorrLast,
} AutoCorrOptions;
+ typedef enum {
+ ModulationNone,
+ ModulationAM,
+ ModulationFM,
+ ModulationLast
+ } Modulation;
+
quint64 m_centerFrequency;
qint32 m_frequencyShift;
quint32 m_sampleRate;
@@ -39,6 +46,10 @@ struct TestSourceSettings {
quint32 m_sampleSizeIndex;
qint32 m_amplitudeBits;
AutoCorrOptions m_autoCorrOptions;
+ Modulation m_modulation;
+ int m_modulationTone; //!< 10'Hz
+ int m_amModulation; //!< percent
+ int m_fmDeviation; //!< 100'Hz
float m_dcFactor; //!< -1.0 < x < 1.0
float m_iFactor; //!< -1.0 < x < 1.0
float m_qFactor; //!< -1.0 < x < 1.0
diff --git a/plugins/samplesource/testsource/testsourcethread.cpp b/plugins/samplesource/testsource/testsourcethread.cpp
index 5267fe58c..5b71b596a 100644
--- a/plugins/samplesource/testsource/testsourcethread.cpp
+++ b/plugins/samplesource/testsource/testsourcethread.cpp
@@ -31,6 +31,11 @@ TestSourceThread::TestSourceThread(SampleSinkFifo* sampleFifo, QObject* parent)
m_convertBuffer(TESTSOURCE_BLOCKSIZE),
m_sampleFifo(sampleFifo),
m_frequencyShift(0),
+ m_toneFrequency(440),
+ m_modulation(TestSourceSettings::ModulationNone),
+ m_amModulation(0.5f),
+ m_fmDeviationUnit(0.0f),
+ m_fmPhasor(0.0f),
m_samplerate(48000),
m_log2Decim(4),
m_fcPos(0),
@@ -81,6 +86,7 @@ void TestSourceThread::setSamplerate(int samplerate)
m_chunksize = 4 * ((m_samplerate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000);
m_throttleToggle = !m_throttleToggle;
m_nco.setFreq(m_frequencyShift, m_samplerate);
+ m_toneNco.setFreq(m_toneFrequency, m_samplerate);
}
void TestSourceThread::setLog2Decimation(unsigned int log2_decim)
@@ -149,6 +155,28 @@ void TestSourceThread::setFrequencyShift(int shift)
m_nco.setFreq(shift, m_samplerate);
}
+void TestSourceThread::setToneFrequency(int toneFrequency)
+{
+ m_toneNco.setFreq(toneFrequency, m_samplerate);
+}
+
+void TestSourceThread::setModulation(TestSourceSettings::Modulation modulation)
+{
+ m_modulation = modulation;
+}
+
+void TestSourceThread::setAMModulation(float amModulation)
+{
+ m_amModulation = amModulation < 0.0f ? 0.0f : amModulation > 1.0f ? 1.0f : amModulation;
+}
+
+void TestSourceThread::setFMDeviation(float deviation)
+{
+ float fmDeviationUnit = deviation / (float) m_samplerate;
+ m_fmDeviationUnit = fmDeviationUnit < 0.0f ? 0.0f : fmDeviationUnit > 1.0f ? 1.0f : fmDeviationUnit;
+ qDebug("TestSourceThread::setFMDeviation: m_fmDeviationUnit: %f", m_fmDeviationUnit);
+}
+
void TestSourceThread::run()
{
m_running = true;
@@ -195,14 +223,52 @@ void TestSourceThread::generate(quint32 chunksize)
for (int i = 0; i < n-1;)
{
- Complex c = m_nco.nextIQ(m_phaseImbalance);
- m_buf[i++] = (int16_t) (c.real() * (float) m_amplitudeBitsI) + m_amplitudeBitsDC;
- m_buf[i++] = (int16_t) (c.imag() * (float) m_amplitudeBitsQ);
+ switch (m_modulation)
+ {
+ case TestSourceSettings::ModulationAM:
+ {
+ Complex c = m_nco.nextIQ();
+ Real t, re, im;
+ pullAF(t);
+ t = (t*m_amModulation + 1.0f)*0.5f;
+ re = c.real()*t;
+ im = c.imag()*t + m_phaseImbalance*re;
+ m_buf[i++] = (int16_t) (re * (float) m_amplitudeBitsI) + m_amplitudeBitsDC;
+ m_buf[i++] = (int16_t) (im * (float) m_amplitudeBitsQ);
+ }
+ break;
+ case TestSourceSettings::ModulationFM:
+ {
+ Complex c = m_nco.nextIQ();
+ Real t, re, im;
+ pullAF(t);
+ m_fmPhasor += m_fmDeviationUnit * t;
+ m_fmPhasor = m_fmPhasor < -1.0f ? -m_fmPhasor - 1.0f : m_fmPhasor > 1.0f ? m_fmPhasor - 1.0f : m_fmPhasor;
+ re = c.real()*cos(m_fmPhasor*M_PI) - c.imag()*sin(m_fmPhasor*M_PI);
+ im = (c.real()*sin(m_fmPhasor*M_PI) + c.imag()*cos(m_fmPhasor*M_PI)) + m_phaseImbalance*re;
+ m_buf[i++] = (int16_t) (re * (float) m_amplitudeBitsI) + m_amplitudeBitsDC;
+ m_buf[i++] = (int16_t) (im * (float) m_amplitudeBitsQ);
+ }
+ break;
+ case TestSourceSettings::ModulationNone:
+ default:
+ {
+ Complex c = m_nco.nextIQ(m_phaseImbalance);
+ m_buf[i++] = (int16_t) (c.real() * (float) m_amplitudeBitsI) + m_amplitudeBitsDC;
+ m_buf[i++] = (int16_t) (c.imag() * (float) m_amplitudeBitsQ);
+ }
+ break;
+ }
}
callback(m_buf, n);
}
+void TestSourceThread::pullAF(Real& afSample)
+{
+ afSample = m_toneNco.next();
+}
+
// call appropriate conversion (decimation) routine depending on the number of sample bits
void TestSourceThread::callback(const qint16* buf, qint32 len)
{
diff --git a/plugins/samplesource/testsource/testsourcethread.h b/plugins/samplesource/testsource/testsourcethread.h
index 43d64c78f..a91b6c010 100644
--- a/plugins/samplesource/testsource/testsourcethread.h
+++ b/plugins/samplesource/testsource/testsourcethread.h
@@ -28,6 +28,8 @@
#include "dsp/decimators.h"
#include "dsp/ncof.h"
+#include "testsourcesettings.h"
+
#define TESTSOURCE_THROTTLE_MS 50
class TestSourceThread : public QThread {
@@ -49,6 +51,10 @@ public:
void setQFactor(float qFactor);
void setPhaseImbalance(float phaseImbalance);
void setFrequencyShift(int shift);
+ void setToneFrequency(int toneFrequency);
+ void setModulation(TestSourceSettings::Modulation modulation);
+ void setAMModulation(float amModulation);
+ void setFMDeviation(float deviation);
void connectTimer(const QTimer& timer);
@@ -63,7 +69,13 @@ private:
SampleVector m_convertBuffer;
SampleSinkFifo* m_sampleFifo;
NCOF m_nco;
+ NCOF m_toneNco;
int m_frequencyShift;
+ int m_toneFrequency;
+ TestSourceSettings::Modulation m_modulation;
+ float m_amModulation;
+ float m_fmDeviationUnit;
+ float m_fmPhasor;
int m_samplerate;
unsigned int m_log2Decim;
@@ -101,6 +113,7 @@ private:
void callback(const qint16* buf, qint32 len);
void setBuffers(quint32 chunksize);
void generate(quint32 chunksize);
+ void pullAF(Real& afSample);
// Decimate according to specified log2 (ex: log2=4 => decim=16)
inline void convert_8(SampleVector::iterator* it, const qint16* buf, qint32 len)