1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-03-25 05:38:39 -04:00

Add worker source

This commit is contained in:
Jon Beniston 2022-07-18 16:40:49 +01:00
parent ff26ece347
commit 3287346a7e
2 changed files with 253 additions and 0 deletions

View File

@ -0,0 +1,159 @@
/*
LDPC testbench
Copyright 2018 Ahmet Inan <xdsopl@gmail.com>
Transformed into external decoder for third-party applications
Copyright 2019 <pabr@pabr.org>
Transformed again in to a Qt worker.
*/
#include <QDebug>
#include <stdlib.h>
#ifdef _MSC_VER
#include <malloc.h>
#endif
#include <iostream>
#include <iomanip>
#include <random>
#include <cmath>
#include <cassert>
#include <chrono>
#include <cstring>
#include <algorithm>
#include <functional>
#include "ldpcworker.h"
LDPCWorker::LDPCWorker(int modcod, int maxTrials, int batchSize, bool shortFrames) :
m_maxTrials(maxTrials),
m_aligned_buffer(nullptr),
m_ldpc(nullptr),
m_code(nullptr),
m_simd(nullptr)
{
// DVB-S2 MODCOD definitions
static const char *mc_tabnames[2][32] = { // [shortframes][modcod]
{// Normal frames
0, "B1", "B2", "B3", "B4", "B5", "B6", "B7",
"B8", "B9", "B10", "B11", "B5", "B6", "B7", "B9",
"B10", "B11", "B6", "B7", "B8", "B9", "B10", "B11",
"B7", "B8", "B8", "B10", "B11", 0, 0, 0},
{// Short frames
0, "C1", "C2", "C3", "C4", "C5", "C6", "C7",
"C8", "C9", "C10", 0, "C5", "C6", "C7", "C9",
"C10", 0, "C6", "C7", "C8", "C9", "C10", 0,
"C7", "C8", "C8", "C10", 0, 0, 0, 0}};
const char *tabname = mc_tabnames[shortFrames][modcod];
if (!tabname)
{
qCritical() << "LDPCWorker::LDPCWorker: unsupported modcod";
return;
}
m_ldpc = ldpctool::create_ldpc((char *)"S2", tabname[0], atoi(tabname + 1));
if (!m_ldpc)
{
qCritical() << "LDPCWorker::LDPCWorker: no such table!";
return;
}
m_codeLen = m_ldpc->code_len();
m_dataLen = m_ldpc->data_len();
m_decode.init(m_ldpc);
BLOCKS = batchSize;
m_code = new ldpctool::code_type[BLOCKS * m_codeLen];
m_aligned_buffer = ldpctool::LDPCUtil::aligned_malloc(sizeof(ldpctool::simd_type), sizeof(ldpctool::simd_type) * m_codeLen);
m_simd = reinterpret_cast<ldpctool::simd_type *>(m_aligned_buffer);
// Expect LLR values in int8_t format.
if (sizeof(ldpctool::code_type) != 1) {
qCritical() << "LDPCWorker::LDPCWorker: Unsupported code_type";
}
}
LDPCWorker::~LDPCWorker()
{
m_condOut.wakeAll();
delete m_ldpc;
ldpctool::LDPCUtil::aligned_free(m_aligned_buffer);
delete[] m_code;
}
void LDPCWorker::process(QByteArray data)
{
int trials_count = 0;
int max_count = 0;
int num_decodes = 0;
int iosize = m_codeLen * sizeof(*m_code);
m_mutexIn.lock();
m_dataIn.append(data);
if (m_dataIn.size() >= BLOCKS)
{
for (int j = 0; j < BLOCKS; j++)
{
QByteArray inputData = m_dataIn.takeAt(0);
memcpy(m_code + j * m_codeLen, inputData.data(), inputData.size());
}
m_mutexIn.unlock();
for (int j = 0; j < BLOCKS; j += ldpctool::SIMD_WIDTH)
{
int blocks = j + ldpctool::SIMD_WIDTH > BLOCKS ? BLOCKS - j : ldpctool::SIMD_WIDTH;
for (int n = 0; n < blocks; ++n)
for (int i = 0; i < m_codeLen; ++i)
reinterpret_cast<ldpctool::code_type *>(m_simd + i)[n] = m_code[(j + n) * m_codeLen + i];
int count = m_decode(m_simd, m_simd + m_dataLen, m_maxTrials, blocks);
num_decodes++;
if (count < 0)
{
trials_count += m_maxTrials;
max_count++;
}
else
{
trials_count += m_maxTrials - count;
}
if (num_decodes == 20)
{
qDebug() << "ldpc_tool: trials: " << ((trials_count*100)/(num_decodes*m_maxTrials)) << "% max: "
<< ((max_count*100)/num_decodes) << "% at converging to a code word (max trials: " << m_maxTrials << ")";
trials_count = 0;
max_count = 0;
num_decodes = 0;
}
for (int n = 0; n < blocks; ++n)
for (int i = 0; i < m_codeLen; ++i)
m_code[(j + n) * m_codeLen + i] = reinterpret_cast<ldpctool::code_type *>(m_simd + i)[n];
}
for (int i = 0; i < BLOCKS * m_codeLen; ++i)
assert(!std::isnan(m_code[i]));
m_mutexOut.lock();
for (int j = 0; j < BLOCKS; j++)
{
QByteArray outputData((const char *)m_code + j * m_codeLen, iosize);
m_dataOut.append(outputData);
}
m_condOut.wakeAll();
m_mutexOut.unlock();
}
else
{
m_mutexIn.unlock();
}
}

View File

@ -0,0 +1,94 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2022 Jon Beniston, M7RCE //
// //
// 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 <QObject>
#include <QByteArray>
#include <QMutex>
#include <QWaitCondition>
#include "testbench.h"
#include "algorithms.h"
#include "ldpc.h"
#include "layered_decoder.h"
class LDPCWorker : public QObject {
Q_OBJECT
public:
LDPCWorker(int modcod, int maxTrials, int batchSize, bool shortFrames);
~LDPCWorker();
// Are we busy
bool busy()
{
QMutexLocker locker(&m_mutexIn);
return m_dataIn.size() >= BLOCKS;
}
// Is processed data available?
bool dataAvailable()
{
QMutexLocker locker(&m_mutexOut);
return !m_dataOut.isEmpty();
}
// Get processed data
QByteArray data()
{
m_mutexOut.lock();
if (m_dataOut.isEmpty()) {
m_condOut.wait(&m_mutexOut);
}
QByteArray data = m_dataOut.takeAt(0);
m_mutexOut.unlock();
return data;
}
public slots:
void process(QByteArray data);
signals:
void finished();
private:
QMutex m_mutexIn;
QMutex m_mutexOut;
QWaitCondition m_condOut;
QList<QByteArray> m_dataIn;
QList<QByteArray> m_dataOut;
int m_maxTrials;
int BLOCKS;
int m_codeLen;
int m_dataLen;
void *m_aligned_buffer;
ldpctool::LDPCInterface *m_ldpc;
ldpctool::code_type *m_code;
ldpctool::simd_type *m_simd;
typedef ldpctool::NormalUpdate<ldpctool::simd_type> update_type;
//typedef SelfCorrectedUpdate<simd_type> update_type;
//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> m_decode;
};