mirror of
https://github.com/SatDump/SatDump
synced 2026-08-13 17:47:30 -04:00
Get around the viterbi kernel issue in Volk
This commit is contained in:
parent
c9b3774ee0
commit
86caa06ce8
3 changed files with 207 additions and 12 deletions
11
README.md
11
README.md
|
|
@ -4,17 +4,6 @@ A generic satellite data processing software.
|
|||
|
||||
**Still WIP**
|
||||
|
||||
# Important - Possible issues with VOLK Viterbi decoding (Windows users can probably ignore this)
|
||||
|
||||
/!\ Some decoders utilize VOLK's Viterbi decoder. But as of writing this, only the "spiral" (SSE) implementation performs as intended. Please ensure you have it set as such in your volk_config or things may not work as expected! /!\
|
||||
|
||||
On Windows, this should not be necessary as it this will (should!) be the default already.
|
||||
|
||||
On Linux, Mac OS and similar platforms, please edit your ~/.volk/volk_config file.
|
||||
Find the line referring to `volk_8u_x4_conv_k7_r2_8u`, and make sure it contains the following : `volk_8u_x4_conv_k7_r2_8u spiral spiral`.
|
||||
|
||||
If you are using an ARM-based machine (Raspbery Pi, most Android devices), there is unfortunately no way around poorer decoding performances of the "generic" kernel... Until this gets fixed in VOLK itself.
|
||||
|
||||
# Usage
|
||||
|
||||
First of all, as with any program using volk, running volk_profile once is highly recommended for better performances.
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@
|
|||
#include <cstdio>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include "logger.h"
|
||||
#include "volk_k7_r2_generic_fixed.h"
|
||||
|
||||
namespace fec
|
||||
{
|
||||
|
|
@ -122,7 +124,35 @@ namespace fec
|
|||
d_SUBSHIFT = 0;
|
||||
}
|
||||
|
||||
std::map<std::string, conv_kernel> yp_kernel = {{"k=7r=2", volk_8u_x4_conv_k7_r2_8u}};
|
||||
conv_kernel k7_r2_kernel = volk_fixed::volk_8u_x4_conv_k7_r2_8u_generic; // Default to our fixed generic kernel
|
||||
|
||||
// We need to get around Volk's broken generic and AVX kernel....
|
||||
{
|
||||
volk_func_desc k7_r2_desc = volk_8u_x4_conv_k7_r2_8u_get_func_desc(); // Check what kernels are available
|
||||
|
||||
bool has_spiral = false;
|
||||
|
||||
for (int i = 0; i < (int)k7_r2_desc.n_impls; i++)
|
||||
{
|
||||
if (std::string(k7_r2_desc.impl_names[i]) == "spiral") // Try to find spiral
|
||||
{
|
||||
has_spiral = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_spiral)
|
||||
{ // If spiral is available, use it
|
||||
logger->trace("Volk has the spiral kernel using it!");
|
||||
k7_r2_kernel = volk_fixed::volk_8u_x4_conv_k7_r2_8u_spiral;
|
||||
}
|
||||
else
|
||||
{ // Stick to our fixed kernel
|
||||
logger->trace("Volk does not have the spiral kernel, will default to bundled generic.");
|
||||
}
|
||||
}
|
||||
|
||||
std::map<std::string, conv_kernel> yp_kernel = {{"k=7r=2", k7_r2_kernel}};
|
||||
|
||||
std::string k_ = "k=";
|
||||
std::string r_ = "r=";
|
||||
|
|
|
|||
176
src-core/common/codings/viterbi/volk_k7_r2_generic_fixed.h
Normal file
176
src-core/common/codings/viterbi/volk_k7_r2_generic_fixed.h
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/* -*- c++ -*- */
|
||||
/*
|
||||
* Copyright 2014 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GNU Radio
|
||||
*
|
||||
* GNU Radio 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; either version 3, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* GNU Radio 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 for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with GNU Radio; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
/*!
|
||||
* \page volk_8u_x4_conv_k7_r2_8u
|
||||
*
|
||||
* \b Overview
|
||||
*
|
||||
* Performs convolutional decoding for a K=7, rate 1/2 convolutional
|
||||
* code. The polynomials user defined.
|
||||
*
|
||||
* <b>Dispatcher Prototype</b>
|
||||
* \code
|
||||
* void volk_8u_x4_conv_k7_r2_8u(unsigned char* Y, unsigned char* X, unsigned char* syms,
|
||||
* unsigned char* dec, unsigned int framebits, unsigned int excess, unsigned char*
|
||||
* Branchtab) \endcode
|
||||
*
|
||||
* \b Inputs
|
||||
* \li X: <FIXME>
|
||||
* \li syms: <FIXME>
|
||||
* \li dec: <FIXME>
|
||||
* \li framebits: size of the frame to decode in bits.
|
||||
* \li excess: <FIXME>
|
||||
* \li Branchtab: <FIXME>
|
||||
*
|
||||
* \b Outputs
|
||||
* \li Y: The decoded output bits.
|
||||
*
|
||||
* \b Example
|
||||
* \code
|
||||
* int N = 10000;
|
||||
*
|
||||
* volk_8u_x4_conv_k7_r2_8u();
|
||||
*
|
||||
* volk_free(x);
|
||||
* \endcode
|
||||
*/
|
||||
|
||||
// The default version in Volk is broken right now, so I am including this fix
|
||||
// SatDump will default to unless volk_config returned a working implemenation
|
||||
|
||||
#ifndef INCLUDED_volk_8u_x4_conv_k7_r2_8u_H
|
||||
#define INCLUDED_volk_8u_x4_conv_k7_r2_8u_H
|
||||
|
||||
#include <volk/volk.h>
|
||||
|
||||
namespace volk_fixed
|
||||
{
|
||||
typedef union
|
||||
{
|
||||
unsigned char /*DECISIONTYPE*/ t[64 /*NUMSTATES*/ / 8 /*DECISIONTYPE_BITSIZE*/];
|
||||
unsigned int w[64 /*NUMSTATES*/ / 32];
|
||||
unsigned short s[64 /*NUMSTATES*/ / 16];
|
||||
unsigned char c[64 /*NUMSTATES*/ / 8];
|
||||
#ifdef _MSC_VER
|
||||
} decision_t;
|
||||
#else
|
||||
} decision_t __attribute__((aligned(16)));
|
||||
#endif
|
||||
|
||||
static inline void renormalize(unsigned char *X, unsigned char /*threshold*/)
|
||||
{
|
||||
int NUMSTATES = 64;
|
||||
int i;
|
||||
|
||||
unsigned char min = X[0];
|
||||
// if(min > threshold) {
|
||||
for (i = 0; i < NUMSTATES; i++)
|
||||
if (min > X[i])
|
||||
min = X[i];
|
||||
for (i = 0; i < NUMSTATES; i++)
|
||||
X[i] -= min;
|
||||
//}
|
||||
}
|
||||
|
||||
// helper BFLY for GENERIC version
|
||||
static inline void BFLY(int i,
|
||||
int s,
|
||||
unsigned char *syms,
|
||||
unsigned char *Y,
|
||||
unsigned char *X,
|
||||
decision_t *d,
|
||||
unsigned char *Branchtab)
|
||||
{
|
||||
int j, decision0, decision1;
|
||||
unsigned char metric, m0, m1, m2, m3;
|
||||
|
||||
int NUMSTATES = 64;
|
||||
int RATE = 2;
|
||||
int METRICSHIFT = 2;
|
||||
int PRECISIONSHIFT = 2;
|
||||
|
||||
metric = 0;
|
||||
for (j = 0; j < RATE; j++)
|
||||
metric += (Branchtab[i + j * NUMSTATES / 2] ^ syms[s * RATE + j]) >> METRICSHIFT;
|
||||
metric = metric >> PRECISIONSHIFT;
|
||||
|
||||
unsigned char max = ((RATE * ((256 - 1) >> METRICSHIFT)) >> PRECISIONSHIFT);
|
||||
|
||||
m0 = X[i] + metric;
|
||||
m1 = X[i + NUMSTATES / 2] + (max - metric);
|
||||
m2 = X[i] + (max - metric);
|
||||
m3 = X[i + NUMSTATES / 2] + metric;
|
||||
|
||||
decision0 = (signed int)(m0 - m1) > 0;
|
||||
decision1 = (signed int)(m2 - m3) > 0;
|
||||
|
||||
Y[2 * i] = decision0 ? m1 : m0;
|
||||
Y[2 * i + 1] = decision1 ? m3 : m2;
|
||||
|
||||
d->w[i / (sizeof(unsigned int) * 8 / 2) +
|
||||
s * (sizeof(decision_t) / sizeof(unsigned int))] |=
|
||||
(decision0 | decision1 << 1) << ((2 * i) & (sizeof(unsigned int) * 8 - 1));
|
||||
}
|
||||
|
||||
static inline void volk_8u_x4_conv_k7_r2_8u_generic(unsigned char *Y,
|
||||
unsigned char *X,
|
||||
unsigned char *syms,
|
||||
unsigned char *dec,
|
||||
unsigned int framebits,
|
||||
unsigned int excess,
|
||||
unsigned char *Branchtab)
|
||||
{
|
||||
int nbits = framebits + excess;
|
||||
int NUMSTATES = 64;
|
||||
int RENORMALIZE_THRESHOLD = 210;
|
||||
|
||||
int s, i;
|
||||
for (s = 0; s < nbits; s++)
|
||||
{
|
||||
void *tmp;
|
||||
for (i = 0; i < NUMSTATES / 2; i++)
|
||||
{
|
||||
BFLY(i, s, syms, Y, X, (decision_t *)dec, Branchtab);
|
||||
}
|
||||
|
||||
renormalize(Y, RENORMALIZE_THRESHOLD);
|
||||
|
||||
/// Swap pointers to old and new metrics
|
||||
tmp = (void *)X;
|
||||
X = Y;
|
||||
Y = (unsigned char *)tmp;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void volk_8u_x4_conv_k7_r2_8u_spiral(unsigned char *Y,
|
||||
unsigned char *X,
|
||||
unsigned char *syms,
|
||||
unsigned char *dec,
|
||||
unsigned int framebits,
|
||||
unsigned int excess,
|
||||
unsigned char *Branchtab)
|
||||
{
|
||||
volk_8u_x4_conv_k7_r2_8u_manual(Y, X, syms, dec, framebits, excess, Branchtab, "spiral");
|
||||
}
|
||||
};
|
||||
#endif /*INCLUDED_volk_8u_x4_conv_k7_r2_8u_H*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue