1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-15 12:51:49 -05:00

M17 demod: implemented BER display

This commit is contained in:
f4exb 2022-07-07 03:19:01 +02:00
parent c3f55af6a6
commit fe6830e552
8 changed files with 323 additions and 2 deletions

View File

@ -44,7 +44,7 @@ if(NOT SERVER_MODE)
m17statustextdialog.h
)
set(TARGET_NAME demodm17)
set(TARGET_LIB "Qt5::Widgets")
set(TARGET_LIB "Qt5::Widgets" Qt5::Charts)
set(TARGET_LIB_GUI "sdrgui")
set(INSTALL_FOLDER ${INSTALL_PLUGINS_DIR})
else()

View File

@ -242,6 +242,10 @@ public:
);
}
void getBERT(uint32_t& bertErrors, uint32_t& bertBits) {
m_basebandSink->getBERT(bertErrors, bertBits);
}
uint32_t getLSFCount() const { return m_basebandSink->getLSFCount(); }
const QString& getSrcCall() const { return m_basebandSink->getSrcCall(); }
const QString& getDestcCall() const { return m_basebandSink->getDestcCall(); }

View File

@ -103,6 +103,10 @@ public:
);
}
void getBERT(uint32_t& bertErrors, uint32_t& bertBits) {
m_sink.getBERT(bertErrors, bertBits);
}
uint32_t getLSFCount() const { return m_sink.getLSFCount(); }
const QString& getSrcCall() const { return m_sink.getSrcCall(); }
const QString& getDestcCall() const { return m_sink.getDestcCall(); }

View File

@ -284,6 +284,22 @@ void M17DemodGUI::on_aprsClearTable_clicked()
ui->aprsPackets->setRowCount(0);
}
void M17DemodGUI::on_totButton_toggled(bool checked)
{
m_showBERTotalOrCurrent = checked;
ui->curButton->blockSignals(true);
ui->curButton->setChecked(!checked);
ui->curButton->blockSignals(false);
}
void M17DemodGUI::on_curButton_toggled(bool checked)
{
m_showBERTotalOrCurrent = !checked;
ui->totButton->blockSignals(true);
ui->totButton->setChecked(!checked);
ui->totButton->blockSignals(false);
}
void M17DemodGUI::onWidgetRolled(QWidget* widget, bool rollDown)
{
(void) widget;
@ -360,7 +376,10 @@ M17DemodGUI::M17DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
m_squelchOpen(false),
m_audioSampleRate(-1),
m_lsfCount(0),
m_tickCount(0)
m_tickCount(0),
m_lastBERErrors(0),
m_lastBERBits(0),
m_showBERTotalOrCurrent(true)
{
setAttribute(Qt::WA_DeleteOnClose, true);
m_helpURL = "plugins/channelrx/demodm17/readme.md";
@ -427,6 +446,15 @@ M17DemodGUI::M17DemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
ui->dcdLabel->setPixmap(QIcon(":/carrier.png").pixmap(QSize(20, 20)));
ui->lockLabel->setPixmap(QIcon(":/locked.png").pixmap(QSize(20, 20)));
m_berChart.setTheme(QChart::ChartThemeDark);
m_berChart.legend()->hide();
ui->berChart->setChart(&m_berChart);
ui->berChart->setRenderHint(QPainter::Antialiasing);
m_berChart.addAxis(&m_berChartXAxis, Qt::AlignBottom);
m_berChart.addAxis(&m_berChartYAxis, Qt::AlignLeft);
m_berChart.layout()->setContentsMargins(0, 0, 0, 0);
m_berChart.setMargins(QMargins(1, 1, 1, 1));
updateMyPosition();
displaySettings();
makeUIConnections();
@ -503,6 +531,9 @@ void M17DemodGUI::displaySettings()
ui->traceDecayText->setText(QString("%1").arg(m_settings.m_traceDecay));
m_scopeVisXY->setDecay(m_settings.m_traceDecay);
ui->totButton->setChecked(m_showBERTotalOrCurrent);
ui->curButton->setChecked(!m_showBERTotalOrCurrent);
updateIndexLabel();
getRollupContents()->restoreState(m_rollupState);
@ -665,6 +696,73 @@ void M17DemodGUI::tick()
m_lsfCount = m_m17Demod->getLSFCount();
}
if (((status == 5) || (status == 4)) && (sync_word_type == 3))
{
uint32_t bertErrors, bertBits;
m_m17Demod->getBERT(bertErrors, bertBits);
uint32_t bertErrorsDelta = bertErrors - m_lastBERErrors;
uint32_t bertBitsDelta = bertBits - m_lastBERBits;
m_lastBERErrors = bertErrors;
m_lastBERBits = bertBits;
m_berPoints.append(BERPoint{
QDateTime::currentDateTime(),
bertErrors,
bertBits,
bertErrorsDelta,
bertBitsDelta
});
m_currentErrors.append(bertErrorsDelta);
uint32_t maxY;
QLineSeries *series;
if (m_showBERTotalOrCurrent)
{
ui->berCounts->setText(tr("%1/%2").arg(bertErrors).arg(bertBits));
series = addBERSeries(true, maxY);
if (bertBits > 0) {
ui->berRatio->setText(tr("%1").arg((double) bertErrors / (double) bertBits, 0, 'e', 2));
}
}
else
{
ui->berCounts->setText(tr("%1/%2").arg(bertErrorsDelta).arg(bertBitsDelta));
series = addBERSeries(false, maxY);
if (bertBitsDelta > 0) {
ui->berRatio->setText(tr("%1").arg((double) bertErrorsDelta / (double) bertBitsDelta, 0, 'e', 2));
}
}
if (series)
{
m_berChart.removeAllSeries();
m_berChart.removeAxis(&m_berChartXAxis);
m_berChart.removeAxis(&m_berChartYAxis);
m_berChart.addSeries(series);
m_berChartXAxis.setRange(m_berPoints.front().m_dateTime, m_berPoints.back().m_dateTime);
m_berChartXAxis.setFormat("hh:mm:ss");
m_berChart.addAxis(&m_berChartXAxis, Qt::AlignBottom);
series->attachAxis(&m_berChartXAxis);
m_berChartYAxis.setRange(0, maxY == 0 ? 1 : maxY);
m_berChart.addAxis(&m_berChartYAxis, Qt::AlignLeft);
series->attachAxis(&m_berChartYAxis);
}
}
else
{
// qDebug("M17DemodGUI::tick: BER reset: status: %d sync_word_type: %d", status, sync_word_type);
m_lastBERErrors = 0;
m_lastBERBits = 0;
m_berPoints.clear();
m_currentErrors.clear();
}
}
m_tickCount++;
@ -697,6 +795,37 @@ QString M17DemodGUI::getStatus(int status, int sync_word_type, bool streamElsePa
}
}
QLineSeries *M17DemodGUI::addBERSeries(bool total, uint32_t& maxVal)
{
if (m_berPoints.size() < 2) {
return nullptr;
}
QLineSeries *series = new QLineSeries();
if (!total) {
maxVal = *std::max_element(m_currentErrors.begin(), m_currentErrors.end());
} else {
maxVal = m_berPoints.back().m_totalErrors;
}
for (auto berPoint : m_berPoints)
{
double x = berPoint.m_dateTime.toMSecsSinceEpoch();
double y;
if (total) {
y = berPoint.m_totalErrors;
} else {
y = berPoint.m_currentErrors;
}
series->append(x, y);
}
return series;
}
void M17DemodGUI::makeUIConnections()
{
QObject::connect(ui->deltaFrequency, &ValueDialZ::changed, this, &M17DemodGUI::on_deltaFrequency_changed);
@ -714,6 +843,8 @@ void M17DemodGUI::makeUIConnections()
QObject::connect(ui->audioMute, &QToolButton::toggled, this, &M17DemodGUI::on_audioMute_toggled);
QObject::connect(ui->viewStatusLog, &QPushButton::clicked, this, &M17DemodGUI::on_viewStatusLog_clicked);
QObject::connect(ui->aprsClearTable, &QPushButton::clicked, this, &M17DemodGUI::on_aprsClearTable_clicked);
QObject::connect(ui->totButton, &ButtonSwitch::toggled, this, &M17DemodGUI::on_totButton_toggled);
QObject::connect(ui->curButton, &ButtonSwitch::toggled, this, &M17DemodGUI::on_curButton_toggled);
}
void M17DemodGUI::updateAbsoluteCenterFrequency()

View File

@ -20,6 +20,8 @@
#define INCLUDE_M17DEMODGUI_H
#include <QMenu>
#include <QtCharts>
#include <QDateTime>
#include "channel/channelgui.h"
#include "dsp/dsptypes.h"
@ -72,6 +74,15 @@ protected:
void resizeEvent(QResizeEvent* size);
private:
struct BERPoint
{
QDateTime m_dateTime;
uint32_t m_totalErrors;
uint32_t m_totalBits;
uint32_t m_currentErrors;
uint32_t m_currentBits;
};
Ui::M17DemodGUI* ui;
PluginAPI* m_pluginAPI;
DeviceUISet* m_deviceUISet;
@ -92,6 +103,15 @@ private:
int m_audioSampleRate;
uint32_t m_lsfCount;
uint32_t m_tickCount;
uint32_t m_lastBERErrors;
uint32_t m_lastBERBits;
bool m_showBERTotalOrCurrent;
QChart m_berChart;
QDateTimeAxis m_berChartXAxis;
QValueAxis m_berChartYAxis;
QList<BERPoint> m_berPoints;
QList<uint32_t> m_currentErrors;
float m_myLatitude;
float m_myLongitude;
@ -112,6 +132,7 @@ private:
void updateAbsoluteCenterFrequency();
QString getStatus(int status, int sync_word_type, bool streamElsePacket, int packetProtocol);
void packetReceived(QByteArray packet);
QLineSeries *addBERSeries(bool total, uint32_t& maxVal);
void leaveEvent(QEvent*);
void enterEvent(QEvent*);
@ -131,6 +152,8 @@ private slots:
void on_highPassFilter_toggled(bool checked);
void on_audioMute_toggled(bool checked);
void on_aprsClearTable_clicked();
void on_totButton_toggled(bool checked);
void on_curButton_toggled(bool checked);
void onWidgetRolled(QWidget* widget, bool rollDown);
void onMenuDialogCalled(const QPoint& p);
void on_viewStatusLog_clicked();

View File

@ -1634,6 +1634,150 @@
</property>
</widget>
</widget>
<widget class="QWidget" name="berTab">
<property name="toolTip">
<string>BER test data</string>
</property>
<attribute name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/ruler.png</normaloff>:/ruler.png</iconset>
</attribute>
<attribute name="title">
<string/>
</attribute>
<attribute name="toolTip">
<string>BER test</string>
</attribute>
<widget class="QLabel" name="berCounts">
<property name="geometry">
<rect>
<x>80</x>
<y>10</y>
<width>140</width>
<height>28</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Errors/Bits counts</string>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string>0/1000000</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="berLabel">
<property name="geometry">
<rect>
<x>230</x>
<y>10</y>
<width>30</width>
<height>28</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Total BER</string>
</property>
<property name="text">
<string>BER</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="QLabel" name="berRatio">
<property name="geometry">
<rect>
<x>265</x>
<y>10</y>
<width>85</width>
<height>28</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>30</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Bit Error Rate</string>
</property>
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string>0.00e+00</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
<widget class="ButtonSwitch" name="totButton">
<property name="geometry">
<rect>
<x>0</x>
<y>5</y>
<width>36</width>
<height>35</height>
</rect>
</property>
<property name="toolTip">
<string>Select total BER counts</string>
</property>
<property name="text">
<string>TOT</string>
</property>
</widget>
<widget class="ButtonSwitch" name="curButton">
<property name="geometry">
<rect>
<x>40</x>
<y>5</y>
<width>36</width>
<height>35</height>
</rect>
</property>
<property name="toolTip">
<string>Select current BER counts</string>
</property>
<property name="text">
<string>CUR</string>
</property>
</widget>
<widget class="QChartView" name="berChart">
<property name="geometry">
<rect>
<x>0</x>
<y>43</y>
<width>480</width>
<height>165</height>
</rect>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
@ -1669,6 +1813,11 @@
<header>gui/tvscreen.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QChartView</class>
<extends>QGraphicsView</extends>
<header>QtCharts</header>
</customwidget>
</customwidgets>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>

View File

@ -92,6 +92,12 @@ public:
viterbiCost = m_viterbiCost;
}
void getBERT(uint32_t& bertErrors, uint32_t& bertBits)
{
bertErrors = m_prbs.errors();
bertBits = m_prbs.bits();
}
private:
std::vector<uint8_t> m_currentPacket;
size_t m_packetFrameCounter;

View File

@ -105,6 +105,10 @@ public:
);
}
void getBERT(uint32_t& bertErrors, uint32_t& bertBits) {
m_m17DemodProcessor.getBERT(bertErrors, bertBits);
}
uint32_t getLSFCount() const { return m_m17DemodProcessor.getLSFCount(); }
const QString& getSrcCall() const { return m_m17DemodProcessor.getSrcCall(); }
const QString& getDestcCall() const { return m_m17DemodProcessor.getDestcCall(); }