mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-07 17:16:02 -05:00
409 lines
10 KiB
C++
409 lines
10 KiB
C++
// polymult.cpp : Defines the entry point for the console application.
|
|
//
|
|
#include "stdio.h"
|
|
#include "stdlib.h"
|
|
#include "memory.h"
|
|
#include "DVBS2.h"
|
|
|
|
|
|
//
|
|
// Display routines.
|
|
//
|
|
void display_poly( int *in, int len )
|
|
{
|
|
loggerf("\n");
|
|
for( int i = 0; i < len; i++ )
|
|
{
|
|
if(in[i] == 1 )
|
|
{
|
|
if( i == 0 )
|
|
loggerf("1");
|
|
else
|
|
if( i == 1 )
|
|
loggerf("+x");
|
|
else
|
|
loggerf("+x^%d",i);
|
|
}
|
|
}
|
|
loggerf("\n");
|
|
}
|
|
//
|
|
// length is in bits
|
|
//
|
|
void display_poly_pack( unsigned int *in, int len )
|
|
{
|
|
(void) in;
|
|
// loggerf("\n");
|
|
for( int i = 0; i < len/32; i++ )
|
|
{
|
|
// loggerf("%.8X",in[i]);
|
|
}
|
|
switch((len%32)/8)
|
|
{
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
// loggerf("%.2X",in[(len/32)]>>24);
|
|
break;
|
|
case 2:
|
|
// loggerf("%.2X",in[(len/32)]>>24);
|
|
// loggerf("%.2X",in[(len/32)]>>16);
|
|
break;
|
|
case 3:
|
|
// loggerf("%.2X",in[(len/32)]>>24);
|
|
// loggerf("%.2X",in[(len/32)]>>16);
|
|
// loggerf("%.2X",in[(len/32)]>>8);
|
|
break;
|
|
}
|
|
// loggerf("\n");
|
|
}
|
|
|
|
//
|
|
// Polynomial calculation routines
|
|
//
|
|
// multiply polynomials
|
|
//
|
|
int DVB2::poly_mult( const int *ina, int lena, const int *inb, int lenb, int *out )
|
|
{
|
|
memset( out, 0, sizeof(int)*(lena+lenb));
|
|
|
|
for( int i = 0; i < lena; i++ )
|
|
{
|
|
for( int j = 0; j < lenb; j++ )
|
|
{
|
|
if( ina[i]*inb[j] > 0 ) out[i+j]++;// count number of terms for this pwr of x
|
|
}
|
|
}
|
|
int max=0;
|
|
for( int i = 0; i < lena+lenb; i++ )
|
|
{
|
|
out[i] = out[i]&1;// If even ignore the term
|
|
if(out[i]) max = i;
|
|
}
|
|
// return the size of array to house the result.
|
|
return max+1;
|
|
|
|
}
|
|
//
|
|
// Pack the polynomial into a 32 bit array
|
|
//
|
|
|
|
void DVB2::poly_pack( const int *pin, u32* pout, int len )
|
|
{
|
|
int lw = len/32;
|
|
int ptr = 0;
|
|
u32 temp;
|
|
if( len % 32 ) lw++;
|
|
|
|
for( int i = 0; i < lw; i++ )
|
|
{
|
|
temp = 0x80000000;
|
|
pout[i] = 0;
|
|
for( int j = 0; j < 32; j++ )
|
|
{
|
|
if( pin[ptr++] ) pout[i] |= temp;
|
|
temp >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
void DVB2::poly_reverse( int *pin, int *pout, int len )
|
|
{
|
|
int c;
|
|
c = len-1;
|
|
|
|
for( int i = 0; i < len; i++ )
|
|
{
|
|
pout[c--] = pin[i];
|
|
}
|
|
}
|
|
//
|
|
// Shift a 128 bit register
|
|
//
|
|
void inline DVB2::reg_4_shift( u32 *sr )
|
|
{
|
|
sr[3] = (sr[3]>>1) | (sr[2]<<31);
|
|
sr[2] = (sr[2]>>1) | (sr[1]<<31);
|
|
sr[1] = (sr[1]>>1) | (sr[0]<<31);
|
|
sr[0] = (sr[0]>>1);
|
|
}
|
|
//
|
|
// Shift 160 bits
|
|
//
|
|
void inline DVB2::reg_5_shift( u32 *sr )
|
|
{
|
|
sr[4] = (sr[4]>>1) | (sr[3]<<31);
|
|
sr[3] = (sr[3]>>1) | (sr[2]<<31);
|
|
sr[2] = (sr[2]>>1) | (sr[1]<<31);
|
|
sr[1] = (sr[1]>>1) | (sr[0]<<31);
|
|
sr[0] = (sr[0]>>1);
|
|
}
|
|
//
|
|
// Shift 192 bits
|
|
//
|
|
void inline DVB2::reg_6_shift( u32 *sr )
|
|
{
|
|
sr[5] = (sr[5]>>1) | (sr[4]<<31);
|
|
sr[4] = (sr[4]>>1) | (sr[3]<<31);
|
|
sr[3] = (sr[3]>>1) | (sr[2]<<31);
|
|
sr[2] = (sr[2]>>1) | (sr[1]<<31);
|
|
sr[1] = (sr[1]>>1) | (sr[0]<<31);
|
|
sr[0] = (sr[0]>>1);
|
|
}
|
|
|
|
//
|
|
// Take an bit array, bch encode it and place the result in a bit array
|
|
// The input length is in bits.
|
|
//
|
|
Bit DVB2::bch_n_8_encode( Bit *in, int len )
|
|
{
|
|
Bit b;
|
|
int i;
|
|
u32 shift[4];
|
|
|
|
//Zero the shift register
|
|
memset( shift,0,sizeof(u32)*4);
|
|
|
|
for( i = 0; i < len; i++ )
|
|
{
|
|
b = in[i]^(shift[3]&1);
|
|
reg_4_shift( shift );
|
|
if( b )
|
|
{
|
|
shift[0] ^= m_poly_n_8[0];
|
|
shift[1] ^= m_poly_n_8[1];
|
|
shift[2] ^= m_poly_n_8[2];
|
|
shift[3] ^= m_poly_n_8[3];
|
|
}
|
|
}
|
|
// Now add the parity bits to the output
|
|
for( int n = 0; n < 128; n++ )
|
|
{
|
|
in[i++] = shift[3]&1;
|
|
reg_4_shift( shift );
|
|
}
|
|
return i;
|
|
}
|
|
Bit DVB2::bch_n_10_encode( Bit *in,int len )
|
|
{
|
|
Bit b;
|
|
int i;
|
|
u32 shift[5];
|
|
|
|
//Zero the shift register
|
|
memset( shift,0,sizeof(u32)*5);
|
|
|
|
for( i = 0; i < len; i++ )
|
|
{
|
|
b = in[i]^(shift[4]&1);
|
|
reg_5_shift( shift );
|
|
if(b)
|
|
{
|
|
shift[0] ^= m_poly_n_10[0];
|
|
shift[1] ^= m_poly_n_10[1];
|
|
shift[2] ^= m_poly_n_10[2];
|
|
shift[3] ^= m_poly_n_10[3];
|
|
shift[4] ^= m_poly_n_10[4];
|
|
}
|
|
}
|
|
// Now add the parity bits to the output
|
|
for( int n = 0; n < 160; n++ )
|
|
{
|
|
in[i++] = shift[4]&1;
|
|
reg_5_shift( shift );
|
|
}
|
|
return i;
|
|
}
|
|
|
|
Bit DVB2::bch_n_12_encode( Bit *in, int len )
|
|
{
|
|
Bit b;
|
|
int i;
|
|
u32 shift[6];
|
|
//Zero the shift register
|
|
memset( shift,0,sizeof(u32)*6);
|
|
// MSB of the codeword first
|
|
for( i = 0; i < len; i++ )
|
|
{
|
|
b = in[i] ^ (shift[5]&1);
|
|
reg_6_shift( shift );
|
|
if(b)
|
|
{
|
|
shift[0] ^= m_poly_n_12[0];
|
|
shift[1] ^= m_poly_n_12[1];
|
|
shift[2] ^= m_poly_n_12[2];
|
|
shift[3] ^= m_poly_n_12[3];
|
|
shift[4] ^= m_poly_n_12[4];
|
|
shift[5] ^= m_poly_n_12[5];
|
|
}
|
|
}
|
|
// Now add the parity bits to the output
|
|
for( int n = 0; n < 192; n++ )
|
|
{
|
|
in[i++] = shift[5]&1;
|
|
reg_6_shift( shift );
|
|
}
|
|
return i;
|
|
}
|
|
|
|
Bit DVB2::bch_s_12_encode( Bit *in, int len )
|
|
{
|
|
Bit b;
|
|
int i;
|
|
u32 shift[6];
|
|
|
|
//Zero the shift register
|
|
memset( shift,0,sizeof(u32)*6);
|
|
|
|
for( i = 0; i < len; i++ )
|
|
{
|
|
b = (in[i] ^ ((shift[5]&0x01000000)?1:0));
|
|
reg_6_shift( shift );
|
|
if(b)
|
|
{
|
|
shift[0] ^= m_poly_s_12[0];
|
|
shift[1] ^= m_poly_s_12[1];
|
|
shift[2] ^= m_poly_s_12[2];
|
|
shift[3] ^= m_poly_s_12[3];
|
|
shift[4] ^= m_poly_s_12[4];
|
|
shift[5] ^= m_poly_s_12[5];
|
|
}
|
|
}
|
|
// Now add the parity bits to the output
|
|
for( int n = 0; n < 168; n++ )
|
|
{
|
|
in[i++] = (shift[5]&0x01000000) ? 1:0;
|
|
reg_6_shift( shift );
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
int DVB2::bch_encode( void )
|
|
{
|
|
int res;
|
|
int len = m_format[0].kbch;
|
|
|
|
switch(m_format[0].bch_code)
|
|
{
|
|
case BCH_CODE_N8:
|
|
res = bch_n_8_encode( m_frame, len );
|
|
break;
|
|
case BCH_CODE_N10:
|
|
res = bch_n_10_encode( m_frame, len );
|
|
break;
|
|
case BCH_CODE_N12:
|
|
res = bch_n_12_encode( m_frame, len );
|
|
break;
|
|
case BCH_CODE_S12:
|
|
res = bch_s_12_encode( m_frame, len );
|
|
break;
|
|
default:
|
|
printf("BCH error situation\n");
|
|
res = 0;
|
|
break;
|
|
}
|
|
return res;
|
|
}
|
|
|
|
//
|
|
//
|
|
//
|
|
void DVB2::bch_poly_build_tables( void )
|
|
{
|
|
// Normal polynomials
|
|
const int polyn01[]={1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,1};
|
|
const int polyn02[]={1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,0,1};
|
|
const int polyn03[]={1,0,1,1,1,1,0,1,1,1,1,1,0,0,0,0,1};
|
|
const int polyn04[]={1,0,1,0,1,0,1,0,0,1,0,1,1,0,1,0,1};
|
|
const int polyn05[]={1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1};
|
|
const int polyn06[]={1,0,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1};
|
|
const int polyn07[]={1,0,1,0,0,1,1,0,1,1,1,1,0,1,0,1,1};
|
|
const int polyn08[]={1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,1};
|
|
const int polyn09[]={1,0,0,0,0,1,0,1,0,1,1,1,0,0,0,0,1};
|
|
const int polyn10[]={1,1,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1};
|
|
const int polyn11[]={1,0,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1};
|
|
const int polyn12[]={1,1,0,0,0,1,1,1,0,1,0,1,1,0,0,0,1};
|
|
|
|
// Short polynomials
|
|
const int polys01[]={1,1,0,1,0,1,0,0,0,0,0,0,0,0,1};
|
|
const int polys02[]={1,0,0,0,0,0,1,0,1,0,0,1,0,0,1};
|
|
const int polys03[]={1,1,1,0,0,0,1,0,0,1,1,0,0,0,1};
|
|
const int polys04[]={1,0,0,0,1,0,0,1,1,0,1,0,1,0,1};
|
|
const int polys05[]={1,0,1,0,1,0,1,0,1,1,0,1,0,1,1};
|
|
const int polys06[]={1,0,0,1,0,0,0,1,1,1,0,0,0,1,1};
|
|
const int polys07[]={1,0,1,0,0,1,1,1,0,0,1,1,0,1,1};
|
|
const int polys08[]={1,0,0,0,0,1,0,0,1,1,1,1,0,0,1};
|
|
const int polys09[]={1,1,1,1,0,0,0,0,0,1,1,0,0,0,1};
|
|
const int polys10[]={1,0,0,1,0,0,1,0,0,1,0,1,1,0,1};
|
|
const int polys11[]={1,0,0,0,1,0,0,0,0,0,0,1,1,0,1};
|
|
const int polys12[]={1,1,1,1,0,1,1,1,1,0,1,0,0,1,1};
|
|
|
|
int len;
|
|
int polyout[3][2000];
|
|
|
|
len = poly_mult( polyn01, 17, polyn02, 17, polyout[0] );
|
|
len = poly_mult( polyn03, 17, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polyn04, 17, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polyn05, 17, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polyn06, 17, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polyn07, 17, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polyn08, 17, polyout[1], len, polyout[0] );
|
|
poly_pack( polyout[0], m_poly_n_8, 128 );
|
|
// display_poly_pack( m_poly_n_8, 128);
|
|
|
|
len = poly_mult( polyn09, 17, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polyn10, 17, polyout[1], len, polyout[0] );
|
|
poly_pack( polyout[0], m_poly_n_10, 160 );
|
|
// display_poly_pack( m_poly_n_10, 160);
|
|
|
|
len = poly_mult( polyn11, 17, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polyn12, 17, polyout[1], len, polyout[0] );
|
|
poly_pack( polyout[0], m_poly_n_12, 192 );
|
|
// display_poly_pack( m_poly_n_12, 192);
|
|
// display_poly( polyout[0], len );//12
|
|
|
|
|
|
len = poly_mult( polys01, 15, polys02, 15, polyout[0] );
|
|
len = poly_mult( polys03, 15, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polys04, 15, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polys05, 15, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polys06, 15, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polys07, 15, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polys08, 15, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polys09, 15, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polys10, 15, polyout[1], len, polyout[0] );
|
|
len = poly_mult( polys11, 15, polyout[0], len, polyout[1] );
|
|
len = poly_mult( polys12, 15, polyout[1], len, polyout[0] );
|
|
poly_pack( polyout[0], m_poly_s_12, 168 );
|
|
// display_poly_pack( m_poly_s_12, 168);
|
|
|
|
/*
|
|
// test
|
|
int pt1[] = {1,1};
|
|
int pt2[] = {1,1,1};
|
|
int pt3[] = {1,0,1,1,1,1};
|
|
len = poly_mult( pt1, 2, pt2, 3, polyout[0] );
|
|
len = poly_mult( pt3, 6, polyout[0], len, polyout[1] );
|
|
display_poly( polyout[1], len );
|
|
poly_pack( polyout[1], m_poly_s_12, len );
|
|
display_poly_pack( m_poly_s_12, 8 );
|
|
u32 shift[6];
|
|
shift[0] = 0x80000000;
|
|
shift[1] = 0x00000000;
|
|
shift[2] = 0x00000000;
|
|
shift[3] = 0x00000000;
|
|
shift[4] = 0x00000000;
|
|
shift[5] = 0x00000000;
|
|
|
|
for( int i = 0; i < 192; i++ )
|
|
{
|
|
display_poly_pack( shift, 192 );
|
|
reg_6_shift( shift );
|
|
}
|
|
|
|
// display_poly( polyout[0], len );//12
|
|
// display_poly_pack( m_poly_s_12, 168 );// Wont work because of shift register length
|
|
*/
|
|
}
|