satdump/plugins/dvb_support/codings/dvb-s2/s2_deinterleaver.cpp
2023-02-12 23:29:51 +01:00

202 lines
No EOL
5.5 KiB
C++

#include "s2_deinterleaver.h"
namespace dvbs2
{
S2Deinterleaver::S2Deinterleaver(dvbs2_constellation_t constellation, dvbs2_framesize_t framesize, dvbs2_code_rate_t rate)
{
if (framesize == FECFRAME_NORMAL)
frame_length = 64800;
else if (framesize == FECFRAME_SHORT)
frame_length = 16200;
if (constellation == MOD_QPSK)
{
rows = 0; // No interleaving
mod_bits = 2;
}
else if (constellation == MOD_8PSK)
{
if (framesize == FECFRAME_NORMAL)
rows = 21600;
else if (framesize == FECFRAME_SHORT)
rows = 5400;
mod_bits = 3;
if (rate == dvbs2::C3_5)
{
column0 = rows * 2;
column1 = rows;
column2 = 0;
}
else
{
column0 = 0;
column1 = rows;
column2 = rows * 2;
}
}
else if (constellation == MOD_16APSK)
{
if (framesize == FECFRAME_NORMAL)
rows = 16200;
else if (framesize == FECFRAME_SHORT)
rows = 4050;
mod_bits = 4;
column0 = 0;
column1 = rows;
column2 = rows * 2;
column3 = rows * 3;
}
else if (constellation == MOD_32APSK)
{
if (framesize == FECFRAME_NORMAL)
rows = 12960;
else if (framesize == FECFRAME_SHORT)
rows = 3240;
mod_bits = 5;
column0 = 0;
column1 = rows;
column2 = rows * 2;
column3 = rows * 3;
column4 = rows * 4;
}
}
S2Deinterleaver::~S2Deinterleaver()
{
}
void S2Deinterleaver::deinterleave(int8_t *input, int8_t *output)
{
/*
In testing I found doing it this way with branching was faster than a more universal approach,
hence the way it is done here.
*/
if (mod_bits == 2)
{
for (int i = 0; i < frame_length / 2; i++)
{
output[i * 2 + 1] = input[i * 2 + 0];
output[i * 2 + 0] = input[i * 2 + 1];
}
}
else if (mod_bits == 3)
{
int8_t *c1 = &output[column0];
int8_t *c2 = &output[column1];
int8_t *c3 = &output[column2];
int i = 0;
for (int j = 0; j < rows; j++)
{
c1[j] = input[i++];
c2[j] = input[i++];
c3[j] = input[i++];
}
}
else if (mod_bits == 4)
{
int8_t *c1 = &output[column0];
int8_t *c2 = &output[column1];
int8_t *c3 = &output[column2];
int8_t *c4 = &output[column3];
int i = 0;
for (int j = 0; j < rows; j++)
{
c1[j] = input[i++];
c2[j] = input[i++];
c3[j] = input[i++];
c4[j] = input[i++];
}
}
else if (mod_bits == 5)
{
column4 = rows * 4;
int8_t *c1 = &output[column0];
int8_t *c2 = &output[column1];
int8_t *c3 = &output[column2];
int8_t *c4 = &output[column3];
int8_t *c5 = &output[column4];
int i = 0;
for (int j = 0; j < rows; j++)
{
c1[j] = input[i++];
c2[j] = input[i++];
c3[j] = input[i++];
c4[j] = input[i++];
c5[j] = input[i++];
}
}
}
void S2Deinterleaver::interleave(uint8_t *input, uint8_t *output)
{
/*
In testing I found doing it this way with branching was faster than a more universal approach,
hence the way it is done here.
*/
if (mod_bits == 2)
{
for (int i = 0; i < frame_length / 2; i++)
{
output[i * 2 + 0] = input[i * 2 + 1];
output[i * 2 + 1] = input[i * 2 + 0];
}
}
else if (mod_bits == 3)
{
uint8_t *c1 = &input[column0];
uint8_t *c2 = &input[column1];
uint8_t *c3 = &input[column2];
int i = 0;
for (int j = 0; j < rows; j++)
{
output[i++] = c1[j];
output[i++] = c2[j];
output[i++] = c3[j];
}
}
else if (mod_bits == 4)
{
uint8_t *c1 = &input[column0];
uint8_t *c2 = &input[column1];
uint8_t *c3 = &input[column2];
uint8_t *c4 = &input[column3];
int i = 0;
for (int j = 0; j < rows; j++)
{
output[i++] = c1[j];
output[i++] = c2[j];
output[i++] = c3[j];
output[i++] = c4[j];
}
}
else if (mod_bits == 5)
{
column4 = rows * 4;
uint8_t *c1 = &input[column0];
uint8_t *c2 = &input[column1];
uint8_t *c3 = &input[column2];
uint8_t *c4 = &input[column3];
uint8_t *c5 = &input[column4];
int i = 0;
for (int j = 0; j < rows; j++)
{
output[i++] = c1[j];
output[i++] = c2[j];
output[i++] = c3[j];
output[i++] = c4[j];
output[i++] = c5[j];
}
}
}
}