From 7334b2fd20d14ad163273a0bd65504361c59de33 Mon Sep 17 00:00:00 2001 From: f4exb Date: Sun, 7 Mar 2021 00:29:01 +0100 Subject: [PATCH] DATV: external LDPC tool implementation final: dialog to select ldpctool and maximum retries --- plugins/channelrx/demoddatv/CMakeLists.txt | 3 + plugins/channelrx/demoddatv/datvdemodgui.cpp | 21 ++- plugins/channelrx/demoddatv/datvdemodgui.h | 1 + .../channelrx/demoddatv/datvdemodsettings.cpp | 11 ++ .../channelrx/demoddatv/datvdemodsettings.h | 2 + plugins/channelrx/demoddatv/datvdemodsink.cpp | 23 ++- .../demoddatv/datvdvbs2ldpcdialog.cpp | 78 ++++++++ .../channelrx/demoddatv/datvdvbs2ldpcdialog.h | 51 +++++ .../demoddatv/datvdvbs2ldpcdialog.ui | 175 ++++++++++++++++++ plugins/channelrx/demoddatv/leansdr/dvbs2.h | 28 ++- plugins/channelrx/demoddatv/readme.md | 9 +- 11 files changed, 390 insertions(+), 12 deletions(-) create mode 100644 plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp create mode 100644 plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h create mode 100644 plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui diff --git a/plugins/channelrx/demoddatv/CMakeLists.txt b/plugins/channelrx/demoddatv/CMakeLists.txt index 143d3c1aa..318877e14 100644 --- a/plugins/channelrx/demoddatv/CMakeLists.txt +++ b/plugins/channelrx/demoddatv/CMakeLists.txt @@ -13,6 +13,7 @@ set(datv_SOURCES datvdemodreport.cpp datvdemodsink.cpp datvdemodbaseband.cpp + datvdvbs2ldpcdialog.cpp leansdr/dvb.cpp leansdr/filtergen.cpp leansdr/framework.cpp @@ -20,6 +21,7 @@ set(datv_SOURCES leansdr/sdr.cpp ldpctool/tables_handler.cpp datvdemodgui.ui + datvdvbs2ldpcdialog.ui ) set(datv_HEADERS @@ -36,6 +38,7 @@ set(datv_HEADERS datvdemodreport.h datvdemodsink.h datvdemodbaseband.h + datvdvbs2ldpcdialog.h leansdr/dvb.h leansdr/dvbs2.h leansdr/filtergen.h diff --git a/plugins/channelrx/demoddatv/datvdemodgui.cpp b/plugins/channelrx/demoddatv/datvdemodgui.cpp index b33f3b1c2..045ba4ff6 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.cpp +++ b/plugins/channelrx/demoddatv/datvdemodgui.cpp @@ -34,6 +34,7 @@ #include "mainwindow.h" #include "datvdemodreport.h" +#include "datvdvbs2ldpcdialog.h" #include "datvdemodgui.h" const char* const DATVDemodGUI::m_strChannelID = "sdrangel.channel.demoddatv"; @@ -250,6 +251,9 @@ DATVDemodGUI::DATVDemodGUI(PluginAPI* objPluginAPI, DeviceUISet *deviceUISet, Ba CRightClickEnabler *audioMuteRightClickEnabler = new CRightClickEnabler(ui->audioMute); connect(audioMuteRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(audioSelect())); + CRightClickEnabler *ldpcToolRightClickEnabler = new CRightClickEnabler(ui->softLDPC); + connect(ldpcToolRightClickEnabler, SIGNAL(rightClick(const QPoint &)), this, SLOT(ldpcToolSelect())); + resetToDefaults(); // does applySettings() } @@ -428,7 +432,7 @@ void DATVDemodGUI::enterEvent(QEvent*) void DATVDemodGUI::audioSelect() { - qDebug("AMDemodGUI::audioSelect"); + qDebug("DATVDemodGUI::audioSelect"); AudioSelectDialog audioSelect(DSPEngine::instance()->getAudioDeviceManager(), m_settings.m_audioDeviceName); audioSelect.exec(); @@ -439,6 +443,21 @@ void DATVDemodGUI::audioSelect() } } +void DATVDemodGUI::ldpcToolSelect() +{ + qDebug("DATVDemodGUI::ldpcToolSelect"); + DatvDvbS2LdpcDialog ldpcDialog; + ldpcDialog.setFileName(m_settings.m_softLDPCToolPath); + ldpcDialog.setMaxTrials(m_settings.m_softLDPCMaxTrials); + + if (ldpcDialog.exec() == QDialog::Accepted) + { + m_settings.m_softLDPCMaxTrials = ldpcDialog.getMaxTrials(); + m_settings.m_softLDPCToolPath = ldpcDialog.getFileName(); + applySettings(); + } +} + void DATVDemodGUI::tick() { if (m_objDATVDemod) diff --git a/plugins/channelrx/demoddatv/datvdemodgui.h b/plugins/channelrx/demoddatv/datvdemodgui.h index 6b36646cf..10e7c079d 100644 --- a/plugins/channelrx/demoddatv/datvdemodgui.h +++ b/plugins/channelrx/demoddatv/datvdemodgui.h @@ -62,6 +62,7 @@ private slots: void onMenuDialogCalled(const QPoint& p); void handleInputMessages(); void audioSelect(); + void ldpcToolSelect(); void tick(); void on_cmbStandard_currentIndexChanged(int index); diff --git a/plugins/channelrx/demoddatv/datvdemodsettings.cpp b/plugins/channelrx/demoddatv/datvdemodsettings.cpp index 1d0552d63..d4e44b5ef 100644 --- a/plugins/channelrx/demoddatv/datvdemodsettings.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsettings.cpp @@ -43,6 +43,8 @@ void DATVDemodSettings::resetToDefaults() m_modulation = BPSK; m_fec = FEC12; m_softLDPC = false; + m_softLDPCToolPath = "/opt/install/sdrangel/bin/ldpctool"; + m_softLDPCMaxTrials = 8; m_maxBitflips = 0; m_symbolRate = 250000; m_notchFilters = 0; @@ -107,6 +109,8 @@ QByteArray DATVDemodSettings::serialize() const s.writeU32(31, m_reverseAPIChannelIndex); s.writeBool(32, m_softLDPC); s.writeS32(33, m_maxBitflips); + s.writeString(34, m_softLDPCToolPath); + s.writeS32(35, m_softLDPCMaxTrials); return s.final(); } @@ -191,6 +195,9 @@ bool DATVDemodSettings::deserialize(const QByteArray& data) d.readBool(32, &m_softLDPC, false); d.readS32(33, &m_maxBitflips, 0); + d.readString(34, &m_softLDPCToolPath, "/opt/install/sdrangel/bin/ldpctool"); + d.readS32(35, &tmp, 8); + m_softLDPCMaxTrials = tmp < 1 ? 1 : tmp > 8 ? 8 : tmp; validateSystemConfiguration(); @@ -217,6 +224,8 @@ void DATVDemodSettings::debug(const QString& msg) const << " m_viterbi: " << m_viterbi << " m_fec: " << m_fec << " m_softLDPC: " << m_softLDPC + << " m_softLDPCMaxTrials: " << m_softLDPCMaxTrials + << " m_softLDPCToolPath: " << m_softLDPCToolPath << " m_maxBitflips: " << m_maxBitflips << " m_modulation: " << m_modulation << " m_standard: " << m_standard @@ -239,6 +248,8 @@ bool DATVDemodSettings::isDifferent(const DATVDemodSettings& other) || (m_viterbi != other.m_viterbi) || (m_fec != other.m_fec) || (m_softLDPC != other.m_softLDPC) + || (m_softLDPCMaxTrials != other.m_softLDPCMaxTrials) + || (m_softLDPCToolPath != other.m_softLDPCToolPath) || (m_maxBitflips != other.m_maxBitflips) || (m_modulation != other.m_modulation) || (m_standard != other.m_standard) diff --git a/plugins/channelrx/demoddatv/datvdemodsettings.h b/plugins/channelrx/demoddatv/datvdemodsettings.h index fce8692d6..fe03272b8 100644 --- a/plugins/channelrx/demoddatv/datvdemodsettings.h +++ b/plugins/channelrx/demoddatv/datvdemodsettings.h @@ -81,6 +81,8 @@ struct DATVDemodSettings DATVModulation m_modulation; DATVCodeRate m_fec; bool m_softLDPC; + QString m_softLDPCToolPath; + int m_softLDPCMaxTrials; int m_maxBitflips; bool m_audioMute; QString m_audioDeviceName; diff --git a/plugins/channelrx/demoddatv/datvdemodsink.cpp b/plugins/channelrx/demoddatv/datvdemodsink.cpp index e4e8aa988..2bfc8c26d 100644 --- a/plugins/channelrx/demoddatv/datvdemodsink.cpp +++ b/plugins/channelrx/demoddatv/datvdemodsink.cpp @@ -21,6 +21,7 @@ #include #include +#include #include "audio/audiooutputdevice.h" #include "dsp/dspengine.h" @@ -903,9 +904,9 @@ void DATVDemodSink::InitDATVS2Framework() << " RollOff: " << m_settings.m_rollOff << " Viterbi: " << m_settings.m_viterbi << " Excursion: " << m_settings.m_excursion - << " Sample rate: " << m_channelSampleRate ; - - + << " Sample rate: " << m_channelSampleRate + << " m_softLDPCMaxTrials: " << m_settings.m_softLDPCMaxTrials + << " m_softLDPCToolPath: " << m_settings.m_softLDPCToolPath; m_objCfg.standard = m_settings.m_standard; @@ -1139,9 +1140,18 @@ void DATVDemodSink::InitDATVS2Framework() p_vbitcount= new leansdr::pipebuf(m_objScheduler, "Bits processed", BUF_S2PACKETS); p_verrcount = new leansdr::pipebuf(m_objScheduler, "Bits corrected", BUF_S2PACKETS); - if (m_settings.m_softLDPC) + bool commandFileValid = false; + + if (QFileInfo::exists(m_settings.m_softLDPCToolPath)) + { + QFileInfo fileInfo = QFileInfo(m_settings.m_softLDPCToolPath); + commandFileValid = fileInfo.isExecutable(); + } + + if (m_settings.m_softLDPC && commandFileValid) { #if 0 + // Doesn't work... // Soft LDPC decoder mode. // Deinterleave into soft bits. p_fecframes = new leansdr::pipebuf >(m_objScheduler, "FEC frames", BUF_FRAMES); @@ -1162,6 +1172,8 @@ void DATVDemodSink::InitDATVS2Framework() // External LDPC decoder mode. // Deinterleave into soft bits. // TBD Latency + QByteArray ba = m_settings.m_softLDPCToolPath.toLocal8Bit(); + const char *c_str2 = ba.data(); p_fecframes = new leansdr::pipebuf >(m_objScheduler, "FEC frames", BUF_FRAMES); p_s2_deinterleaver = new leansdr::s2_deinterleaver( m_objScheduler, @@ -1173,7 +1185,7 @@ void DATVDemodSink::InitDATVS2Framework() m_objScheduler, *(leansdr::pipebuf< leansdr::fecframe > *) p_fecframes, *(leansdr::pipebuf *) p_bbframes, - "/opt/install/sdrangel/bin/ldpctool", + c_str2, p_vbitcount, p_verrcount) ; @@ -1181,6 +1193,7 @@ void DATVDemodSink::InitDATVS2Framework() const int nhelpers = 2; fecdec->nhelpers = nhelpers; fecdec->must_buffer = false; + fecdec->max_trials = m_settings.m_softLDPCMaxTrials; #endif } else diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp new file mode 100644 index 000000000..a098acd8f --- /dev/null +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.cpp @@ -0,0 +1,78 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#include + +#include "datvdvbs2ldpcdialog.h" +#include "ui_datvdvbs2ldpcdialog.h" + +DatvDvbS2LdpcDialog::DatvDvbS2LdpcDialog(QWidget* parent) : + QDialog(parent), + ui(new Ui::DatvDvbS2LdpcDialog) +{ + ui->setupUi(this); +} + +DatvDvbS2LdpcDialog::~DatvDvbS2LdpcDialog() +{ + delete ui; +} + +void DatvDvbS2LdpcDialog::accept() +{ + QDialog::accept(); +} + +void DatvDvbS2LdpcDialog::setFileName(const QString& fileName) +{ + m_fileName = fileName; + ui->ldpcToolText->setText(m_fileName); +} + +void DatvDvbS2LdpcDialog::setMaxTrials(int maxTrials) +{ + m_maxTrials = maxTrials < 1 ? 1 : maxTrials > 8 ? 8 : maxTrials; + ui->maxTrials->setValue(m_maxTrials); +} + +void DatvDvbS2LdpcDialog::on_showFileDialog_clicked(bool checked) +{ + (void) checked; + + QFileDialog fileDialog(this, "Select LDPC tool"); + fileDialog.setOption(QFileDialog::DontUseNativeDialog, true); + fileDialog.setFilter(QDir::Executable | QDir::Files); + fileDialog.selectFile(m_fileName); + + if (fileDialog.exec() == QDialog::Accepted) + { + QStringList fileNames = fileDialog.selectedFiles(); + + if (fileNames.size() > 0) + { + m_fileName = fileNames[0]; + ui->ldpcToolText->setText(m_fileName); + } + } +} + +void DatvDvbS2LdpcDialog::on_maxTrials_valueChanged(int value) +{ + m_maxTrials = value; +} + diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h new file mode 100644 index 000000000..d36447cb7 --- /dev/null +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.h @@ -0,0 +1,51 @@ +/////////////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2021 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 . // +/////////////////////////////////////////////////////////////////////////////////// + +#ifndef SDRGUI_GUI_DATVDVBS2LDPCDIALOG_H_ +#define SDRGUI_GUI_DATVDVBS2LDPCDIALOG_H_ + +#include +#include "export.h" + +namespace Ui { + class DatvDvbS2LdpcDialog; +} + +class SDRGUI_API DatvDvbS2LdpcDialog : public QDialog { + Q_OBJECT +public: + explicit DatvDvbS2LdpcDialog(QWidget* parent = nullptr); + ~DatvDvbS2LdpcDialog(); + + void setFileName(const QString& fileName); + void setMaxTrials(int maxTrials); + QString& getFileName() { return m_fileName; } + int getMaxTrials() { return m_maxTrials; } + +private: + Ui::DatvDvbS2LdpcDialog* ui; + QString m_fileName; + int m_maxTrials; + +private slots: + void accept(); + void on_showFileDialog_clicked(bool checked); + void on_maxTrials_valueChanged(int value); +}; + +#endif /* SDRGUI_GUI_DATVDVBS2LDPCDIALOG_H_ */ diff --git a/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui new file mode 100644 index 000000000..62cac97f7 --- /dev/null +++ b/plugins/channelrx/demoddatv/datvdvbs2ldpcdialog.ui @@ -0,0 +1,175 @@ + + + DatvDvbS2LdpcDialog + + + + 0 + 0 + 461 + 121 + + + + + Liberation Sans + 9 + + + + DATV DVBS2 LDPC settings + + + + + + + + Max trials + + + + + + + 1 + + + 8 + + + 10 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + LDPC tool + + + + + + + + 24 + 16777215 + + + + Choose a log file + + + + + + + :/preset-load.png:/preset-load.png + + + + + + + + 300 + 0 + + + + Log file + + + ... + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + true + + + + + + + buttonBox + + + + + + + buttonBox + accepted() + DatvDvbS2LdpcDialog + accept() + + + 257 + 194 + + + 157 + 203 + + + + + buttonBox + rejected() + DatvDvbS2LdpcDialog + reject() + + + 314 + 194 + + + 286 + 203 + + + + + diff --git a/plugins/channelrx/demoddatv/leansdr/dvbs2.h b/plugins/channelrx/demoddatv/leansdr/dvbs2.h index 99aa0ec71..ee3539fbb 100644 --- a/plugins/channelrx/demoddatv/leansdr/dvbs2.h +++ b/plugins/channelrx/demoddatv/leansdr/dvbs2.h @@ -2350,6 +2350,8 @@ struct s2_fecdec_helper : runnable int batch_size; int nhelpers; bool must_buffer; + int max_trials; + s2_fecdec_helper(scheduler *sch, pipebuf> &_in, pipebuf &_out, @@ -2360,15 +2362,22 @@ struct s2_fecdec_helper : runnable batch_size(16), nhelpers(1), must_buffer(false), + max_trials(8), in(_in), out(_out), - command(_command), bitcount(opt_writer(_bitcount, 1)), errcount(opt_writer(_errcount, 1)) { + command = strdup(_command); for (int mc = 0; mc < 32; ++mc) for (int sf = 0; sf < 2; ++sf) pools[mc][sf].procs = nullptr; } + + ~s2_fecdec_helper() + { + free(command); + } + void run() { // Send work until all helpers block. @@ -2520,12 +2529,21 @@ struct s2_fecdec_helper : runnable dup2(tx[0], 0); close(rx[0]); dup2(rx[1], 1); - char mc_arg[16]; - sprintf(mc_arg, "%d", pls->modcod); + char max_trials_arg[16]; + sprintf(max_trials_arg, "%d", max_trials); char batch_size_arg[16]; sprintf(batch_size_arg, "%d", batch_size); + char mc_arg[16]; + sprintf(mc_arg, "%d", pls->modcod); const char *sf_arg = pls->sf ? "--shortframes" : nullptr; - const char *argv[] = {command, "--trials", "8", "--batch-size", batch_size_arg, "--modcod", mc_arg, sf_arg, nullptr}; + const char *argv[] = { + command, + "--trials", max_trials_arg, + "--batch-size", batch_size_arg, + "--modcod", mc_arg, + sf_arg, + nullptr + }; execve(command, (char *const *)argv, nullptr); fatal(command); } @@ -2592,7 +2610,7 @@ struct s2_fecdec_helper : runnable pipereader> in; pipewriter out; - const char *command; + char *command; SOFTBYTE ldpc_buf[64800 / 8]; uint8_t bch_buf[64800 / 8]; // Temp storage for hardening before BCH s2_bch_engines s2bch; diff --git a/plugins/channelrx/demoddatv/readme.md b/plugins/channelrx/demoddatv/readme.md index 08acd6665..b1448c39a 100644 --- a/plugins/channelrx/demoddatv/readme.md +++ b/plugins/channelrx/demoddatv/readme.md @@ -165,7 +165,14 @@ The controls specific to DVB-S are disabled and greyed out. These are: Fast Lock
B.2b.6: DVB-S2 specific - Soft LDPC decoder
-Not implemented yet +This is for experimenters only. It can be used to decode signals lower that ~10 db MER which is the limit of LDPC hard decoding as explained next (B.2b.7). Video degrades progressively down to about 7.5 dB MER and drops below this limit. + +Runs the `ldpctool` program for soft LDPC decoding. Frames are sent on its standard input and decoded frames retrieved from its standard output. Two processes executing `ldpctool` are spawned but so far it seems that only one is effectively used. + +Right clicking on this control opens a dialog where you can choose: + + - The `ldpctool` executable. You have to use the `ldpctool` binary produced by the build of SDRangel. + - The maximum of retries in LDPC decoding from 1 to 8.
B.2b.7: DVB-S2 specific - LDPC maximum number of bit flips allowed