1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-05-24 11:12:27 -04:00

DATV: external LDPC tool implementation (6): cleanup of soft LDPC but keep external

This commit is contained in:
f4exb 2021-03-06 12:47:42 +01:00
parent 6e8b573b5f
commit 3e02af8d93
2 changed files with 91 additions and 98 deletions

View File

@ -1142,7 +1142,7 @@ void DATVDemodSink::InitDATVS2Framework()
if (m_settings.m_softLDPC) if (m_settings.m_softLDPC)
{ {
#if 0 #if 0
// External LDPC decoder mode. // Soft LDPC decoder mode.
// Deinterleave into soft bits. // Deinterleave into soft bits.
p_fecframes = new leansdr::pipebuf<leansdr::fecframe<leansdr::llr_sb> >(m_objScheduler, "FEC frames", BUF_FRAMES); 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>( p_s2_deinterleaver = new leansdr::s2_deinterleaver<leansdr::llr_ss, leansdr::llr_sb>(

View File

@ -2196,92 +2196,91 @@ struct s2_fecdec_soft : runnable
bitcount(opt_writer(_bitcount, 1)), bitcount(opt_writer(_bitcount, 1)),
errcount(opt_writer(_errcount, 1)) errcount(opt_writer(_errcount, 1))
{ {
tabname = ldpctool::LDPCInterface::mc_tabnames[shortframes][modcod]; const char *tabname = ldpctool::LDPCInterface::mc_tabnames[shortframes][modcod];
ldpc = ldpctool::create_ldpc((char *)"S2", tabname[0], atoi(tabname + 1)); fprintf(stderr, "s2_fecdec_soft::s2_fecdec_soft: tabname: %s\n", tabname);
CODE_LEN = ldpc->code_len();
DATA_LEN = ldpc->data_len(); if (tabname)
decode.init(ldpc); {
code = new ldpctool::code_type[BLOCKS * CODE_LEN]; ldpc = ldpctool::create_ldpc((char *)"S2", tabname[0], atoi(tabname + 1));
aligned_buffer = aligned_alloc(sizeof(ldpctool::simd_type), sizeof(ldpctool::simd_type) * CODE_LEN); code = new ldpctool::code_type[ldpc->code_len()];
simd = reinterpret_cast<ldpctool::simd_type *>(aligned_buffer); aligned_buffer = aligned_alloc(sizeof(ldpctool::simd_type), sizeof(ldpctool::simd_type) * ldpc->code_len());
simd = reinterpret_cast<ldpctool::simd_type *>(aligned_buffer);
}
else
{
ldpc = nullptr;
aligned_buffer = nullptr;
code = nullptr;
}
} }
~s2_fecdec_soft() ~s2_fecdec_soft()
{ {
delete[] code; if (aligned_buffer) {
free(aligned_buffer);
}
if (code) {
delete[] code;
}
} }
void run() void run()
{ {
while (in.readable() >= 1 && out.writable() >= 1 && while (in.readable() >= 1 &&
opt_writable(bitcount, 1) && opt_writable(errcount, 1)) out.writable() >= 1 &&
opt_writable(bitcount, 1) &&
opt_writable(errcount, 1))
{ {
// input
fecframe<SOFTBYTE> *pin = in.rd(); fecframe<SOFTBYTE> *pin = in.rd();
size_t iosize = (pin->pls.framebits() / 8) * sizeof(SOFTBYTE); const modcod_info *mcinfo = check_modcod(pin->pls.modcod);
int8_t *ibytes = reinterpret_cast<int8_t*>(pin->bytes); const fec_info *fi = &fec_infos[pin->pls.sf][mcinfo->rate];
int8_t *icode = reinterpret_cast<int8_t*>(code); bool corrupted = false;
std::copy(ibytes, ibytes + iosize, icode); // write/read bool residual_errors;
// process if (ldpc)
int iterations = 0;
int num_decodes = 0;
for (int j = 0; j < BLOCKS; j += ldpctool::SIMD_WIDTH)
{ {
int blocks = j + ldpctool::SIMD_WIDTH > BLOCKS ? BLOCKS - j : ldpctool::SIMD_WIDTH; decode.init(ldpc);
int count = decode(simd, simd + ldpc->data_len(), max_trials, 1);
for (int n = 0; n < blocks; ++n)
{
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;
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) { if (count < 0) {
iterations += blocks * trials; fprintf(stderr, "s2_fecdec_soft::run: decoder failed at converging to a code word in %d trials\n", max_trials);
} else {
iterations += blocks * (trials - count);
} }
}
// output for (int i = 0; i < ldpc->code_len(); ++i) {
int8_t *ildpc = reinterpret_cast<int8_t*>(ldpc_buf); code[i] = reinterpret_cast<ldpctool::code_type *>(simd + i)[0];
std::copy(icode, icode + iosize, ildpc); // write/read }
// Decode BCH. SOFTBYTE *ldpc_buf = reinterpret_cast<SOFTBYTE*>(code);
const modcod_info *mcinfo = check_modcod(modcod); uint8_t *hardbytes = softbytes_harden(ldpc_buf, fi->kldpc / 8, bch_buf);
const fec_info *fi = &fec_infos[pin->pls.sf ? 1 : 0][mcinfo->rate];
uint8_t *hardbytes = softbytes_harden(ldpc_buf, fi->kldpc / 8, bch_buf); // BCH decode
size_t cwbytes = fi->kldpc / 8; size_t cwbytes = fi->kldpc / 8;
bch_interface *bch = s2bch.bchs[pin->pls.sf ? 1 : 0][mcinfo->rate]; // Decode with suitable BCH decoder for this MODCOD
int ncorr = bch->decode(hardbytes, cwbytes); bch_interface *bch = s2bch.bchs[pin->pls.sf][mcinfo->rate];
bool corrupted = (ncorr < 0); int ncorr = bch->decode(hardbytes, cwbytes);
// Report VBER if (sch->debug2)
opt_write(bitcount, fi->Kbch); fprintf(stderr, "BCHCORR = %d\n", ncorr);
opt_write(errcount, (ncorr >= 0) ? ncorr : fi->Kbch); corrupted = (ncorr < 0);
residual_errors = (ncorr != 0);
// Report VER
opt_write(bitcount, fi->Kbch);
opt_write(errcount, (ncorr >= 0) ? ncorr : fi->Kbch);
int bbsize = fi->Kbch / 8;
if (!corrupted)
{
// Descramble and output
bbframe *pout = out.wr();
pout->pls = pin->pls;
bbscrambling.transform(hardbytes, bbsize, pout->bytes);
out.written(1);
}
if (sch->debug) {
fprintf(stderr, "%c", corrupted ? ':' : residual_errors ? '.' : '_');
}
} // ldpc engine allocated
if (!corrupted)
{
// Descramble and output
bbframe *pout = out.wr();
pout->pls = pin->pls;
bbscrambling.transform(hardbytes, fi->Kbch / 8, pout->bytes);
out.written(1);
}
if (sch->debug)
fprintf(stderr, "%c", corrupted ? '!' : ncorr ? '.' : '_');
in.read(1); in.read(1);
} }
} }
@ -2294,18 +2293,22 @@ private:
int max_trials; int max_trials;
pipewriter<int> *bitcount, *errcount; pipewriter<int> *bitcount, *errcount;
static const int BLOCKS = 32; typedef ldpctool::NormalUpdate<ldpctool::simd_type> update_type;
int CODE_LEN; //typedef SelfCorrectedUpdate<simd_type> update_type;
int DATA_LEN;
const char *tabname; //typedef MinSumAlgorithm<simd_type, update_type> algorithm_type;
//typedef OffsetMinSumAlgorithm<simd_type, update_type, FACTOR> algorithm_type;
typedef ldpctool::MinSumCAlgorithm<ldpctool::simd_type, update_type, ldpctool::FACTOR> algorithm_type;
//typedef LogDomainSPA<simd_type, update_type> algorithm_type;
//typedef LambdaMinAlgorithm<simd_type, update_type, 3> algorithm_type;
//typedef SumProductAlgorithm<simd_type, update_type> algorithm_type;
ldpctool::LDPCDecoder<ldpctool::simd_type, algorithm_type> decode;
ldpctool::LDPCInterface *ldpc; ldpctool::LDPCInterface *ldpc;
ldpctool::code_type *code; ldpctool::code_type *code;
void *aligned_buffer; void *aligned_buffer;
ldpctool::simd_type *simd; ldpctool::simd_type *simd;
typedef ldpctool::NormalUpdate<ldpctool::simd_type> update_type;
typedef ldpctool::MinSumCAlgorithm<ldpctool::simd_type, update_type, ldpctool::FACTOR> algorithm_type;
ldpctool::LDPCDecoder<ldpctool::simd_type, algorithm_type> decode;
SOFTBYTE ldpc_buf[64800 / 8];
uint8_t bch_buf[64800 / 8]; // Temp storage for hardening before BCH uint8_t bch_buf[64800 / 8]; // Temp storage for hardening before BCH
s2_bch_engines s2bch; s2_bch_engines s2bch;
s2_bbscrambling bbscrambling; s2_bbscrambling bbscrambling;
@ -2371,20 +2374,13 @@ struct s2_fecdec_helper : runnable
// Send work until all helpers block. // Send work until all helpers block.
while (in.readable() >= 1 && !jobs.full()) while (in.readable() >= 1 && !jobs.full())
{ {
if (out.writable() >= 1) if ((bbframe_q.size() != 0) && (out.writable() >= 1))
{ {
if (bbframe_q.size() != 0) bbframe *pout = out.wr();
{ pout->pls = bbframe_q.front().pls;
bbframe *pout = out.wr(); std::copy(bbframe_q.front().bytes, bbframe_q.front().bytes + (58192 / 8), pout->bytes);
pout->pls = bbframe_q.front().pls; bbframe_q.pop_front();
std::copy(bbframe_q.front().bytes, bbframe_q.front().bytes + (58192 / 8), pout->bytes); out.written(1);
bbframe_q.pop_front();
out.written(1);
}
else
{
fprintf(stderr, "s2_fecdec_helper::run: WARNING: bbframe queue is empty\n");
}
} }
if ((bitcount_q.size() != 0) && opt_writable(bitcount, 1)) if ((bitcount_q.size() != 0) && opt_writable(bitcount, 1))
@ -2399,19 +2395,16 @@ struct s2_fecdec_helper : runnable
errcount_q.pop_front(); errcount_q.pop_front();
} }
if (!jobs.empty() && jobs.peek()->h->b_out) {
receive_frame(jobs.get());
}
if (!send_frame(in.rd())) { if (!send_frame(in.rd())) {
break; break;
} }
in.read(1); in.read(1);
} }
while (
!jobs.empty() &&
jobs.peek()->h->b_out)
{
receive_frame(jobs.get());
}
} }
private: private:
@ -2532,7 +2525,7 @@ struct s2_fecdec_helper : runnable
char batch_size_arg[16]; char batch_size_arg[16];
sprintf(batch_size_arg, "%d", batch_size); sprintf(batch_size_arg, "%d", batch_size);
const char *sf_arg = pls->sf ? "--shortframes" : nullptr; const char *sf_arg = pls->sf ? "--shortframes" : nullptr;
const char *argv[] = {command, "--trials", "5", "--batch-size", batch_size_arg, "--modcod", mc_arg, sf_arg, nullptr}; const char *argv[] = {command, "--trials", "8", "--batch-size", batch_size_arg, "--modcod", mc_arg, sf_arg, nullptr};
execve(command, (char *const *)argv, nullptr); execve(command, (char *const *)argv, nullptr);
fatal(command); fatal(command);
} }