1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-12-23 01:55:48 -05:00

DATV: external LDPC tool implementation final: dialog to select ldpctool and maximum retries

This commit is contained in:
f4exb 2021-03-07 00:29:01 +01:00
parent 3e02af8d93
commit 7334b2fd20
11 changed files with 390 additions and 12 deletions

View File

@ -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

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -21,6 +21,7 @@
#include <QDebug>
#include <QObject>
#include <QFileInfo>
#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<int>(m_objScheduler, "Bits processed", BUF_S2PACKETS);
p_verrcount = new leansdr::pipebuf<int>(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<leansdr::fecframe<leansdr::llr_sb> >(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<leansdr::fecframe<leansdr::llr_sb> >(m_objScheduler, "FEC frames", BUF_FRAMES);
p_s2_deinterleaver = new leansdr::s2_deinterleaver<leansdr::llr_ss, leansdr::llr_sb>(
m_objScheduler,
@ -1173,7 +1185,7 @@ void DATVDemodSink::InitDATVS2Framework()
m_objScheduler,
*(leansdr::pipebuf< leansdr::fecframe<leansdr::llr_sb> > *) p_fecframes,
*(leansdr::pipebuf<leansdr::bbframe> *) 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

View File

@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <QFileDialog>
#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;
}

View File

@ -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 <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef SDRGUI_GUI_DATVDVBS2LDPCDIALOG_H_
#define SDRGUI_GUI_DATVDVBS2LDPCDIALOG_H_
#include <QDialog>
#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_ */

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>DatvDvbS2LdpcDialog</class>
<widget class="QDialog" name="DatvDvbS2LdpcDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>461</width>
<height>121</height>
</rect>
</property>
<property name="font">
<font>
<family>Liberation Sans</family>
<pointsize>9</pointsize>
</font>
</property>
<property name="windowTitle">
<string>DATV DVBS2 LDPC settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="levelLayout">
<item>
<widget class="QLabel" name="maxTrialsLabel">
<property name="text">
<string>Max trials</string>
</property>
</widget>
</item>
<item>
<widget class="QSpinBox" name="maxTrials">
<property name="minimum">
<number>1</number>
</property>
<property name="maximum">
<number>8</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="logFileLayout">
<item>
<widget class="QLabel" name="ldpcToolLabel">
<property name="text">
<string>LDPC tool</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="showFileDialog">
<property name="maximumSize">
<size>
<width>24</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip">
<string>Choose a log file</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../../../sdrgui/resources/res.qrc">
<normaloff>:/preset-load.png</normaloff>:/preset-load.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ldpcToolText">
<property name="minimumSize">
<size>
<width>300</width>
<height>0</height>
</size>
</property>
<property name="toolTip">
<string>Log file</string>
</property>
<property name="text">
<string>...</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>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
<property name="centerButtons">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="../../../sdrgui/resources/res.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>DatvDvbS2LdpcDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>257</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>203</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>DatvDvbS2LdpcDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>314</x>
<y>194</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>203</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -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<fecframe<SOFTBYTE>> &_in,
pipebuf<bbframe> &_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<fecframe<SOFTBYTE>> in;
pipewriter<bbframe> 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;

View File

@ -165,7 +165,14 @@ The controls specific to DVB-S are disabled and greyed out. These are: Fast Lock
<h5>B.2b.6: DVB-S2 specific - Soft LDPC decoder</h5>
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.
<h5>B.2b.7: DVB-S2 specific - LDPC maximum number of bit flips allowed</h5>