mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-22 08:04:49 -05:00
DATV: enhancement and fixes to DVBS2 external LDPC tool process. Implements #804
This commit is contained in:
parent
c575c02791
commit
233f512f9c
@ -197,7 +197,7 @@ bool DATVDemodSettings::deserialize(const QByteArray& data)
|
||||
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;
|
||||
m_softLDPCMaxTrials = tmp < 1 ? 1 : tmp > m_softLDPCMaxMaxTrials ? m_softLDPCMaxMaxTrials : tmp;
|
||||
|
||||
validateSystemConfiguration();
|
||||
|
||||
|
@ -106,6 +106,7 @@ struct DATVDemodSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIDeviceIndex;
|
||||
uint16_t m_reverseAPIChannelIndex;
|
||||
static const int m_softLDPCMaxMaxTrials = 25;
|
||||
|
||||
DATVDemodSettings();
|
||||
void resetToDefaults();
|
||||
|
@ -431,6 +431,10 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
|
||||
{
|
||||
delete (leansdr::s2_fecdec_soft<leansdr::llr_t,leansdr::llr_sb>*) r_fecdecsoft;
|
||||
}
|
||||
if(r_fecdechelper != nullptr)
|
||||
{
|
||||
delete (leansdr::s2_fecdec_helper<leansdr::llr_t,leansdr::llr_sb>*) r_fecdechelper;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(p_deframer != nullptr)
|
||||
@ -442,7 +446,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
|
||||
{
|
||||
delete r_scope_symbols_dvbs2;
|
||||
}
|
||||
}
|
||||
} // blnRelease
|
||||
|
||||
m_objScheduler=nullptr;
|
||||
|
||||
@ -547,6 +551,7 @@ void DATVDemodSink::CleanUpDATVFramework(bool blnRelease)
|
||||
p_s2_deinterleaver = nullptr;
|
||||
r_fecdec = nullptr;
|
||||
r_fecdecsoft = nullptr;
|
||||
r_fecdechelper = nullptr;
|
||||
p_deframer = nullptr;
|
||||
r_scope_symbols_dvbs2 = nullptr;
|
||||
}
|
||||
@ -893,7 +898,7 @@ void DATVDemodSink::InitDATVS2Framework()
|
||||
|
||||
m_blnDVBInitialized = false;
|
||||
m_lngReadIQ = 0;
|
||||
CleanUpDATVFramework(false);
|
||||
CleanUpDATVFramework(true);
|
||||
|
||||
qDebug() << "DATVDemodSink::InitDATVS2Framework:"
|
||||
<< " Standard: " << m_settings.m_standard
|
||||
@ -1185,7 +1190,7 @@ void DATVDemodSink::InitDATVS2Framework()
|
||||
*(leansdr::pipebuf< leansdr::fecframe<leansdr::llr_sb> > *) p_fecframes
|
||||
);
|
||||
// Decode FEC-protected frames into plain BB frames.
|
||||
r_fecdec = new leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb>(
|
||||
r_fecdechelper = new leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb>(
|
||||
m_objScheduler,
|
||||
*(leansdr::pipebuf< leansdr::fecframe<leansdr::llr_sb> > *) p_fecframes,
|
||||
*(leansdr::pipebuf<leansdr::bbframe> *) p_bbframes,
|
||||
@ -1193,8 +1198,8 @@ void DATVDemodSink::InitDATVS2Framework()
|
||||
p_vbitcount,
|
||||
p_verrcount)
|
||||
;
|
||||
leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *fecdec = (leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *) r_fecdec;
|
||||
const int nhelpers = 2;
|
||||
leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *fecdec = (leansdr::s2_fecdec_helper<leansdr::llr_t, leansdr::llr_sb> *) r_fecdechelper;
|
||||
const int nhelpers = 4;
|
||||
fecdec->nhelpers = nhelpers;
|
||||
fecdec->must_buffer = false;
|
||||
fecdec->max_trials = m_settings.m_softLDPCMaxTrials;
|
||||
|
@ -225,6 +225,7 @@ private:
|
||||
void *p_s2_deinterleaver;
|
||||
void *r_fecdec;
|
||||
void *r_fecdecsoft;
|
||||
void *r_fecdechelper;
|
||||
void *p_deframer;
|
||||
|
||||
//DECIMATION
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <QFileDialog>
|
||||
|
||||
#include "datvdvbs2ldpcdialog.h"
|
||||
#include "datvdemodsettings.h"
|
||||
#include "ui_datvdvbs2ldpcdialog.h"
|
||||
|
||||
DatvDvbS2LdpcDialog::DatvDvbS2LdpcDialog(QWidget* parent) :
|
||||
@ -46,7 +47,8 @@ void DatvDvbS2LdpcDialog::setFileName(const QString& fileName)
|
||||
|
||||
void DatvDvbS2LdpcDialog::setMaxTrials(int maxTrials)
|
||||
{
|
||||
m_maxTrials = maxTrials < 1 ? 1 : maxTrials > 8 ? 8 : maxTrials;
|
||||
m_maxTrials = maxTrials < 1 ? 1 :
|
||||
maxTrials > DATVDemodSettings::m_softLDPCMaxMaxTrials ? DATVDemodSettings::m_softLDPCMaxMaxTrials : maxTrials;
|
||||
ui->maxTrials->setValue(m_maxTrials);
|
||||
}
|
||||
|
||||
|
@ -31,11 +31,17 @@
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="maxTrials">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>55</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>8</number>
|
||||
<number>25</number>
|
||||
</property>
|
||||
<property name="displayIntegerBase">
|
||||
<number>10</number>
|
||||
|
@ -136,6 +136,10 @@ int main(int argc, char **argv)
|
||||
if (sizeof(ldpctool::code_type) != 1)
|
||||
fail("Bug: Unsupported code_type");
|
||||
|
||||
int trials_count = 0;
|
||||
int max_count = 0;
|
||||
int num_decodes = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
ssize_t iosize = BLOCKS * CODE_LEN * sizeof(*code);
|
||||
@ -153,8 +157,6 @@ int main(int argc, char **argv)
|
||||
pos += nr;
|
||||
}
|
||||
|
||||
int iterations = 0;
|
||||
int num_decodes = 0;
|
||||
|
||||
for (int j = 0; j < BLOCKS; j += ldpctool::SIMD_WIDTH)
|
||||
{
|
||||
@ -164,24 +166,31 @@ int main(int argc, char **argv)
|
||||
for (int i = 0; i < CODE_LEN; ++i)
|
||||
reinterpret_cast<ldpctool::code_type *>(simd + i)[n] = code[(j + n) * CODE_LEN + i];
|
||||
|
||||
int trials = max_trials;
|
||||
int count = decode(simd, simd + DATA_LEN, trials, blocks);
|
||||
++num_decodes;
|
||||
int count = decode(simd, simd + DATA_LEN, max_trials, blocks);
|
||||
num_decodes++;
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
trials_count += max_trials;
|
||||
max_count++;
|
||||
}
|
||||
else
|
||||
{
|
||||
trials_count += max_trials - count;
|
||||
}
|
||||
|
||||
if (num_decodes == 20)
|
||||
{
|
||||
fprintf(stderr, "ldpc_tool: trials: %d%% max: %d%% at converging to a code word\n",
|
||||
(trials_count*100)/(num_decodes*max_trials), (max_count*100)/num_decodes);
|
||||
trials_count = 0;
|
||||
max_count = 0;
|
||||
num_decodes = 0;
|
||||
}
|
||||
|
||||
for (int n = 0; n < blocks; ++n)
|
||||
for (int i = 0; i < CODE_LEN; ++i)
|
||||
code[(j + n) * CODE_LEN + i] = reinterpret_cast<ldpctool::code_type *>(simd + i)[n];
|
||||
|
||||
if (count < 0)
|
||||
{
|
||||
iterations += blocks * trials;
|
||||
std::cerr << "ldpc_tool: decoder failed at converging to a code word in " << trials << " trials" << std::endl;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
iterations += blocks * (trials - count);
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < BLOCKS * CODE_LEN; ++i)
|
||||
|
@ -37,6 +37,8 @@
|
||||
#include "sdr.h"
|
||||
|
||||
#ifdef LINUX
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
#include "ldpctool/layered_decoder.h"
|
||||
#include "ldpctool/testbench.h"
|
||||
#include "ldpctool/algorithms.h"
|
||||
@ -2379,6 +2381,7 @@ struct s2_fecdec_helper : runnable
|
||||
~s2_fecdec_helper()
|
||||
{
|
||||
free(command);
|
||||
killall();
|
||||
}
|
||||
|
||||
void run()
|
||||
@ -2424,6 +2427,7 @@ struct s2_fecdec_helper : runnable
|
||||
int batch_size; // Latency
|
||||
int b_in; // Jobs in input queue
|
||||
int b_out; // Jobs in output queue
|
||||
int pid; // PID of the child
|
||||
};
|
||||
struct pool
|
||||
{
|
||||
@ -2451,10 +2455,13 @@ struct s2_fecdec_helper : runnable
|
||||
int nw = write(h->fd_tx, pin->bytes, iosize);
|
||||
|
||||
if (nw < 0 && errno == EWOULDBLOCK)
|
||||
{
|
||||
lseek(h->fd_tx, 0, SEEK_SET); // allow new writes on this worker
|
||||
continue; // next worker
|
||||
}
|
||||
if (nw < 0)
|
||||
fatal("write(LDPC helper");
|
||||
if (nw != iosize)
|
||||
else if (nw != iosize)
|
||||
fatal("partial write(LDPC helper)");
|
||||
|
||||
helper_job *job = jobs.put();
|
||||
@ -2471,9 +2478,9 @@ struct s2_fecdec_helper : runnable
|
||||
return true; // done sent to worker
|
||||
}
|
||||
|
||||
fprintf(stderr, "s2_fecdec_helper::send_frame: WARNING: all %d workers are busy: modcod=%d sf=%d)\n",
|
||||
fprintf(stderr, "s2_fecdec_helper::send_frame: WARNING: all %d workers were busy: modcod=%d sf=%d)\n",
|
||||
p->nprocs, pin->pls.modcod, pin->pls.sf);
|
||||
return false; // all workers are busy
|
||||
return false; // all workers were busy
|
||||
}
|
||||
|
||||
// Return a pool of running helpers for a given modcod.
|
||||
@ -2494,6 +2501,42 @@ struct s2_fecdec_helper : runnable
|
||||
return p;
|
||||
}
|
||||
|
||||
void killall()
|
||||
{
|
||||
fprintf(stderr, "s2_fecdec_helper::killall\n");
|
||||
|
||||
for (int i = 0; i < 32; i++) // all MODCODs
|
||||
{
|
||||
for (int j = 0; j < 2; j++) // long and short frames
|
||||
{
|
||||
pool *p = &pools[i][j];
|
||||
|
||||
if (p->procs)
|
||||
{
|
||||
for (int i = 0; i < p->nprocs; ++i)
|
||||
{
|
||||
helper_instance *h = &p->procs[i];
|
||||
fprintf(stderr, "s2_fecdec_helper::killall: killing %d\n", h->pid);
|
||||
int rc = kill(h->pid, SIGKILL);
|
||||
if (rc < 0) {
|
||||
fatal("s2_fecdec_helper::killall");
|
||||
} else {
|
||||
int cs;
|
||||
waitpid(h->pid, &cs, 0);
|
||||
}
|
||||
// reset pipes
|
||||
lseek(h->fd_tx, 0, SEEK_SET);
|
||||
lseek(h->fd_rx, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
delete p->procs;
|
||||
p->procs = nullptr;
|
||||
p->nprocs = 0;
|
||||
}
|
||||
} // long and short frames
|
||||
} // all MODCODs
|
||||
}
|
||||
|
||||
// Spawn a helper process.
|
||||
void spawn_helper(helper_instance *h, const s2_pls *pls)
|
||||
{
|
||||
@ -2507,19 +2550,31 @@ struct s2_fecdec_helper : runnable
|
||||
// macOS does not have F_SETPIPE_SZ and there
|
||||
// is no way to change the buffer size
|
||||
#ifndef __APPLE__
|
||||
if (fcntl(tx[0], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(rx[0], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(tx[1], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(rx[1], F_SETPIPE_SZ, pipesize) < 0)
|
||||
long min_pipe_size = (long) fcntl(tx[0], F_GETPIPE_SZ);
|
||||
long pipe_size = (long) fcntl(rx[0], F_GETPIPE_SZ);
|
||||
min_pipe_size = std::min(min_pipe_size, pipe_size);
|
||||
pipe_size = (long) fcntl(tx[1], F_GETPIPE_SZ);
|
||||
min_pipe_size = std::min(min_pipe_size, pipe_size);
|
||||
pipe_size = (long) fcntl(rx[1], F_GETPIPE_SZ);
|
||||
min_pipe_size = std::min(min_pipe_size, pipe_size);
|
||||
|
||||
if (min_pipe_size < pipesize)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*** Failed to increase pipe size.\n"
|
||||
"*** Try echo %d > /proc/sys/fs/pipe-max-size\n",
|
||||
pipesize);
|
||||
if (must_buffer)
|
||||
fatal("F_SETPIPE_SZ");
|
||||
else
|
||||
fprintf(stderr, "*** Throughput will be suboptimal.\n");
|
||||
if (fcntl(tx[0], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(rx[0], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(tx[1], F_SETPIPE_SZ, pipesize) < 0 ||
|
||||
fcntl(rx[1], F_SETPIPE_SZ, pipesize) < 0)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"*** Failed to increase pipe size from %ld.\n"
|
||||
"*** Try echo %d > /proc/sys/fs/pipe-max-size\n",
|
||||
min_pipe_size,
|
||||
pipesize);
|
||||
if (must_buffer)
|
||||
fatal("F_SETPIPE_SZ");
|
||||
else
|
||||
fprintf(stderr, "*** Throughput will be suboptimal.\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// vfork() differs from fork(2) in that the calling thread is
|
||||
@ -2552,15 +2607,19 @@ struct s2_fecdec_helper : runnable
|
||||
fatal(command);
|
||||
}
|
||||
|
||||
h->pid = child;
|
||||
h->fd_tx = tx[1];
|
||||
close(tx[0]);
|
||||
h->fd_rx = rx[0];
|
||||
close(rx[1]);
|
||||
h->batch_size = batch_size; // TBD
|
||||
h->b_in = h->b_out = 0;
|
||||
int flags = fcntl(h->fd_tx, F_GETFL);
|
||||
if (fcntl(h->fd_tx, F_SETFL, flags | O_NONBLOCK))
|
||||
fatal("fcntl(helper)");
|
||||
int flags_tx = fcntl(h->fd_tx, F_GETFL);
|
||||
if (fcntl(h->fd_tx, F_SETFL, flags_tx | O_NONBLOCK))
|
||||
fatal("fcntl_tx(helper)");
|
||||
int flags_rx = fcntl(h->fd_rx, F_GETFL);
|
||||
if (fcntl(h->fd_rx, F_SETFL, flags_rx | O_NONBLOCK))
|
||||
fatal("fcntl_rx(helper)");
|
||||
}
|
||||
|
||||
// Receive a finished job.
|
||||
@ -2570,10 +2629,18 @@ struct s2_fecdec_helper : runnable
|
||||
const s2_pls *pls = &job->pls;
|
||||
int iosize = (pls->framebits() / 8) * sizeof(ldpc_buf[0]);
|
||||
int nr = read(job->h->fd_rx, ldpc_buf, iosize);
|
||||
|
||||
if (nr < 0)
|
||||
fatal("read(LDPC helper)");
|
||||
if (nr != iosize)
|
||||
fatal("partial read(LDPC helper)");
|
||||
{
|
||||
if (errno != EAGAIN) { // if no data then try again next time
|
||||
fatal("s2_fecdec_helper::receive_frame read error");
|
||||
}
|
||||
}
|
||||
else if (nr != iosize)
|
||||
{
|
||||
fprintf(stderr, "s2_fecdec_helper::receive_frame: %d bytes read vs %d", nr, iosize);
|
||||
}
|
||||
|
||||
--job->h->b_out;
|
||||
// Decode BCH.
|
||||
const modcod_info *mcinfo = check_modcod(job->pls.modcod);
|
||||
|
Loading…
Reference in New Issue
Block a user