mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-23 01:55:48 -05:00
Merge pull request #939 from srcejon/radio_clock_waveform
Radio Clock: Send multiple streams to scope
This commit is contained in:
commit
5eff1c7bb4
@ -176,18 +176,6 @@ void RadioClockGUI::on_timezone_currentIndexChanged(int index)
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void RadioClockGUI::on_channel1_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_scopeCh1 = index;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void RadioClockGUI::on_channel2_currentIndexChanged(int index)
|
||||
{
|
||||
m_settings.m_scopeCh2 = index;
|
||||
applySettings();
|
||||
}
|
||||
|
||||
void RadioClockGUI::onWidgetRolled(QWidget* widget, bool rollDown)
|
||||
{
|
||||
(void) widget;
|
||||
@ -259,10 +247,11 @@ RadioClockGUI::RadioClockGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Bas
|
||||
|
||||
m_scopeVis = m_radioClock->getScopeSink();
|
||||
m_scopeVis->setGLScope(ui->glScope);
|
||||
m_scopeVis->setNbStreams(1);
|
||||
m_scopeVis->setNbStreams(7);
|
||||
m_scopeVis->setLiveRate(1000);
|
||||
ui->glScope->connectTimer(MainCore::instance()->getMasterTimer());
|
||||
ui->scopeGUI->setBuddies(m_scopeVis->getInputMessageQueue(), m_scopeVis, ui->glScope);
|
||||
ui->scopeGUI->setStreams(QStringList({"IQ", "MagSq", "TH", "FM", "Data", "Samp", "GotMM"}));
|
||||
|
||||
ui->status->setText("Looking for minute marker");
|
||||
|
||||
@ -342,9 +331,6 @@ void RadioClockGUI::displaySettings()
|
||||
|
||||
displayStreamIndex();
|
||||
|
||||
ui->channel1->setCurrentIndex(m_settings.m_scopeCh1);
|
||||
ui->channel2->setCurrentIndex(m_settings.m_scopeCh2);
|
||||
|
||||
blockApplySettings(false);
|
||||
}
|
||||
|
||||
|
@ -89,8 +89,6 @@ private slots:
|
||||
void on_threshold_valueChanged(int value);
|
||||
void on_modulation_currentIndexChanged(int index);
|
||||
void on_timezone_currentIndexChanged(int index);
|
||||
void on_channel1_currentIndexChanged(int index);
|
||||
void on_channel2_currentIndexChanged(int index);
|
||||
void onWidgetRolled(QWidget* widget, bool rollDown);
|
||||
void onMenuDialogCalled(const QPoint& p);
|
||||
void handleInputMessages();
|
||||
|
@ -586,136 +586,6 @@
|
||||
<property name="bottomMargin">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="scopelLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="channel1Label">
|
||||
<property name="text">
|
||||
<string>Real</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="channel1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Signal to feed to scope as stream 0 real data</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>I</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mag Sq</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mag Sq LPF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Threshold</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FM demod LPF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Data</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sample</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Got minute marker</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="channel2Label">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Imag</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QComboBox" name="channel2">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Signal to feed to scope as stream 0 imag data</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Q</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mag Sq</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Mag Sq LPF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Threshold</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>FM Demod LPF</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Data</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sample</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Got minute marker</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="GLScope" name="glScope" native="true">
|
||||
<property name="minimumSize">
|
||||
@ -778,8 +648,6 @@
|
||||
<tabstop>timezone</tabstop>
|
||||
<tabstop>date</tabstop>
|
||||
<tabstop>time</tabstop>
|
||||
<tabstop>channel1</tabstop>
|
||||
<tabstop>channel2</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
<include location="../../../sdrgui/resources/res.qrc"/>
|
||||
|
@ -37,8 +37,6 @@ void RadioClockSettings::resetToDefaults()
|
||||
m_threshold = 5;
|
||||
m_modulation = MSF;
|
||||
m_timezone = BROADCAST;
|
||||
m_scopeCh1 = 2;
|
||||
m_scopeCh2 = 3;
|
||||
m_rgbColor = QColor(102, 0, 0).rgb();
|
||||
m_title = "Radio Clock";
|
||||
m_streamIndex = 0;
|
||||
@ -58,8 +56,6 @@ QByteArray RadioClockSettings::serialize() const
|
||||
s.writeFloat(4, m_threshold);
|
||||
s.writeS32(5, (int)m_modulation);
|
||||
s.writeS32(6, (int)m_timezone);
|
||||
s.writeS32(10, m_scopeCh1);
|
||||
s.writeS32(11, m_scopeCh2);
|
||||
s.writeU32(12, m_rgbColor);
|
||||
s.writeString(13, m_title);
|
||||
if (m_channelMarker) {
|
||||
@ -97,8 +93,6 @@ bool RadioClockSettings::deserialize(const QByteArray& data)
|
||||
d.readFloat(4, &m_threshold, 30);
|
||||
d.readS32(5, (int *)&m_modulation, DCF77);
|
||||
d.readS32(6, (int *)&m_timezone, BROADCAST);
|
||||
d.readS32(10, &m_scopeCh1, 2);
|
||||
d.readS32(11, &m_scopeCh2, 3);
|
||||
d.readU32(12, &m_rgbColor, QColor(102, 0, 0).rgb());
|
||||
d.readString(13, &m_title, "Radio Clock");
|
||||
d.readBlob(14, &bytetmp);
|
||||
|
@ -41,8 +41,6 @@ struct RadioClockSettings
|
||||
LOCAL,
|
||||
UTC
|
||||
} m_timezone;
|
||||
int m_scopeCh1;
|
||||
int m_scopeCh2;
|
||||
|
||||
quint32 m_rgbColor;
|
||||
QString m_title;
|
||||
|
@ -66,14 +66,22 @@ void RadioClockSink::sampleToScope(Complex sample)
|
||||
{
|
||||
if (m_scopeSink)
|
||||
{
|
||||
Real r = std::real(sample) * SDR_RX_SCALEF;
|
||||
Real i = std::imag(sample) * SDR_RX_SCALEF;
|
||||
SampleVector m_sampleBuffer1;
|
||||
m_sampleBuffer1.push_back(Sample(r, i));
|
||||
std::vector<SampleVector::const_iterator> vbegin;
|
||||
vbegin.push_back(m_sampleBuffer1.begin());
|
||||
m_scopeSink->feed(vbegin, m_sampleBuffer1.end() - m_sampleBuffer1.begin());
|
||||
m_sampleBuffer1.clear();
|
||||
ComplexVector m_sampleBuffer[7];
|
||||
m_sampleBuffer[0].push_back(sample);
|
||||
m_sampleBuffer[1].push_back(Complex(m_magsq, 0.0f));
|
||||
m_sampleBuffer[2].push_back(Complex(m_threshold, 0.0f));
|
||||
m_sampleBuffer[3].push_back(Complex(m_fmDemodMovingAverage.asDouble(), 0.0f));
|
||||
m_sampleBuffer[4].push_back(Complex(m_data, 0.0f));
|
||||
m_sampleBuffer[5].push_back(Complex(m_sample, 0.0f));
|
||||
m_sampleBuffer[6].push_back(Complex(m_gotMinuteMarker, 0.0f));
|
||||
std::vector<ComplexVector::const_iterator> vbegin;
|
||||
for (int i = 0; i < 7; i++) {
|
||||
vbegin.push_back(m_sampleBuffer[i].begin());
|
||||
}
|
||||
m_scopeSink->feed(vbegin, m_sampleBuffer[0].end() - m_sampleBuffer[0].begin());
|
||||
for (int i = 0; i < 7; i++) {
|
||||
m_sampleBuffer[i].clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -596,63 +604,8 @@ void RadioClockSink::processOneSample(Complex &ci)
|
||||
msf60();
|
||||
}
|
||||
|
||||
// Select signals to feed to scope
|
||||
Complex scopeSample;
|
||||
switch (m_settings.m_scopeCh1)
|
||||
{
|
||||
case 0:
|
||||
scopeSample.real(ci.real() / SDR_RX_SCALEF);
|
||||
break;
|
||||
case 1:
|
||||
scopeSample.real(magsq * 1e6);
|
||||
break;
|
||||
case 2:
|
||||
scopeSample.real(m_magsq * 1e6);
|
||||
break;
|
||||
case 3:
|
||||
scopeSample.real(m_threshold * 1e6);
|
||||
break;
|
||||
case 4:
|
||||
scopeSample.real(m_fmDemodMovingAverage.asDouble());
|
||||
break;
|
||||
case 5:
|
||||
scopeSample.real(m_data);
|
||||
break;
|
||||
case 6:
|
||||
scopeSample.real(m_sample);
|
||||
break;
|
||||
case 7:
|
||||
scopeSample.real(m_gotMinuteMarker);
|
||||
break;
|
||||
}
|
||||
switch (m_settings.m_scopeCh2)
|
||||
{
|
||||
case 0:
|
||||
scopeSample.imag(ci.imag() / SDR_RX_SCALEF);
|
||||
break;
|
||||
case 1:
|
||||
scopeSample.imag(magsq * 1e6);
|
||||
break;
|
||||
case 2:
|
||||
scopeSample.imag(m_magsq * 1e6);
|
||||
break;
|
||||
case 3:
|
||||
scopeSample.imag(m_threshold * 1e6);
|
||||
break;
|
||||
case 4:
|
||||
scopeSample.imag(m_fmDemodMovingAverage.asDouble());
|
||||
break;
|
||||
case 5:
|
||||
scopeSample.imag(m_data);
|
||||
break;
|
||||
case 6:
|
||||
scopeSample.imag(m_sample);
|
||||
break;
|
||||
case 7:
|
||||
scopeSample.imag(m_gotMinuteMarker);
|
||||
break;
|
||||
}
|
||||
sampleToScope(scopeSample);
|
||||
// Feed signals to scope
|
||||
sampleToScope(Complex(re, im));
|
||||
}
|
||||
|
||||
void RadioClockSink::applyChannelSettings(int channelSampleRate, int channelFrequencyOffset, bool force)
|
||||
|
@ -12,7 +12,7 @@ If you'd like other transmitters to be supported (such as WWVB), please upload a
|
||||
|
||||
Typically, it will take two minutes before the time is able to be displayed (up to one minute to find the minute marker, then another minute to receive the timecode).
|
||||
|
||||
Although the atomic clocks used to transmit the timecode are extremely accurate, propagation, SDR data transfer and demodulation delays limit accuracy of the displayed time to around 1 second.
|
||||
Although the atomic clocks used to transmit the timecode are extremely accurate, propagation, SDR data transfer and demodulation delays limit accuracy of the displayed time to around 1 second.
|
||||
|
||||
<h2>Interface</h2>
|
||||
|
||||
@ -76,3 +76,22 @@ Displays the demodulator status. This can be:
|
||||
The date and time fields are only valid when the status indicates OK.
|
||||
|
||||
If while in the OK state several second markers are not detected, the status will return to Looking for minute marker.
|
||||
|
||||
<h3>Waveforms</h3>
|
||||
|
||||
The scope shows how various variables within the demodulator vary with time. These can be used to help debug operation of the demodulator.
|
||||
|
||||
The signals available include:
|
||||
|
||||
- IQ - IQ data at channel sample rate (1kHz).
|
||||
- MagSq - Magnitude squared (power) of received signal after being filtered with a moving average filter.
|
||||
- TH - Current threshold, which is moving average of MagSq - TH setting.
|
||||
- FM - Output of FM demodulator for TDF demodulator only.
|
||||
- Data - Demodulated data. For MSF/DCF77, this data=MagSq>TH.
|
||||
- Samp - Indicates when data is sampled (either for the second marker or for a timecode data bit).
|
||||
- GotMM - Indicates whether the minute marker has been received. Cleared when synchronization to second marker is lost.
|
||||
|
||||
As an example of how this can be used, we can plot the MagSq as X and the calculated TH as Y, which can help to set the value of the
|
||||
TH setting to an approproate level.
|
||||
|
||||
![Radio clock plugin GUI](../../../doc/img/RadioClock_waveforms.png)
|
||||
|
Loading…
Reference in New Issue
Block a user