1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-14 12:22:00 -05:00
sdrangel/plugins/channeltx/moddatv/dvb-s2/dvbs2_physical.cpp

349 lines
9.1 KiB
C++

///////////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2021 Jon Beniston, M7RCE <jon@beniston.com> //
// //
// 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 "DVBS2.h"
void DVBS2::b_64_7_code( unsigned char in, int *out )
{
unsigned long temp,bit;
temp = 0;
if(in&0x40) temp ^= g[0];
if(in&0x20) temp ^= g[1];
if(in&0x10) temp ^= g[2];
if(in&0x08) temp ^= g[3];
if(in&0x04) temp ^= g[4];
if(in&0x02) temp ^= g[5];
bit = 0x80000000;
for( int m = 0; m < 32; m++ )
{
out[(m*2)] = (temp&bit)?1:0;
out[(m*2)+1] = out[m*2]^(in&0x01);
bit >>= 1;
}
// Randomise it
for( int m = 0; m < 64; m++ )
{
out[m] = out[m] ^ ph_scram_tab[m];
}
}
//[MODCOD 6:2 ][TYPE 1:0 ]
void DVBS2::s2_pl_header_encode( u8 modcod, u8 type, int *out)
{
unsigned char code;
code = (modcod<<2) | type;
//printf("MODCOD %d TYPE %d %d\n",modcod,type,code);
// Add the modcod and type information and scramble it
b_64_7_code( code, out );
}
void DVBS2::s2_pl_header_create(void)
{
int type, modcod;
modcod = 0;
if( m_format[0].frame_type == FRAME_NORMAL )
type = 0;
else
type = 2;
if( m_format[0].pilots ) type |= 1;
// Mode and code rate
if( m_format[0].constellation == M_QPSK )
{
switch( m_format[0].code_rate )
{
case CR_1_4:
modcod = 1;
break;
case CR_1_3:
modcod = 2;
break;
case CR_2_5:
modcod = 3;
break;
case CR_1_2:
modcod = 4;
break;
case CR_3_5:
modcod = 5;
break;
case CR_2_3:
modcod = 6;
break;
case CR_3_4:
modcod = 7;
break;
case CR_4_5:
modcod = 8;
break;
case CR_5_6:
modcod = 9;
break;
case CR_8_9:
modcod = 10;
break;
case CR_9_10:
modcod = 11;
break;
default:
modcod = 0;
break;
}
}
if( m_format[0].constellation == M_8PSK )
{
switch( m_format[0].code_rate )
{
case CR_3_5:
modcod = 12;
break;
case CR_2_3:
modcod = 13;
break;
case CR_3_4:
modcod = 14;
break;
case CR_5_6:
modcod = 15;
break;
case CR_8_9:
modcod = 16;
break;
case CR_9_10:
modcod = 17;
break;
default:
modcod = 0;
break;
}
}
if( m_format[0].constellation == M_16APSK )
{
switch( m_format[0].code_rate )
{
case CR_2_3:
modcod = 18;
break;
case CR_3_4:
modcod = 19;
break;
case CR_4_5:
modcod = 20;
break;
case CR_5_6:
modcod = 21;
break;
case CR_8_9:
modcod = 22;
break;
case CR_9_10:
modcod = 23;
break;
default:
modcod = 0;
break;
}
}
if( m_format[0].constellation == M_32APSK )
{
switch( m_format[0].code_rate )
{
case CR_3_4:
modcod = 24;
break;
case CR_4_5:
modcod = 25;
break;
case CR_5_6:
modcod = 26;
break;
case CR_8_9:
modcod = 27;
break;
case CR_9_10:
modcod = 28;
break;
default:
modcod = 0;
break;
}
}
// Now create the PL header.
int b[90];
// Add the sync sequence SOF
for( int i = 0; i < 26; i++ ) b[i] = ph_sync_seq[i];
// Add the mode and code
s2_pl_header_encode( modcod, type, &b[26] );
// BPSK modulate and add the header
for( int i = 0; i < 90; i++ )
{
m_pl[i] = m_bpsk[i&1][b[i]];
}
}
//
// m_symbols is the total number of complex symbols in the frame
// Modulate the data starting at symbol 90
//
int DVBS2::s2_pl_data_pack( void )
{
int m = 0;
int n = 90;// Jump over header
int blocks = m_payload_symbols/90;
int block_count = 0;
// See if PSK
if( m_format[0].constellation == M_QPSK )
{
for( int i = 0; i < blocks; i++ )
{
for( int j = 0; j < 90; j++ )
{
m_pl[n++] = m_qpsk[m_iframe[m++]&0x3];
}
block_count = (block_count+1)%16;
if((block_count == 0)&&(i<blocks-1))
{
if( m_format[0].pilots )
{
// Add pilots if needed
for( int k = 0; k < 36; k++ )
{
m_pl[n++] = m_bpsk[0][0];
}
}
}
}
}
// See if 8 PSK
if( m_format[0].constellation == M_8PSK )
{
for( int i = 0; i < blocks; i++ )
{
for( int j = 0; j < 90; j++ )
{
m_pl[n++] = m_8psk[m_iframe[m++]&0x7];
}
block_count = (block_count+1)%16;
if((block_count == 0)&&(i<blocks-1))
{
if( m_format[0].pilots )
{
// Add pilots if needed
for( int k = 0; k < 36; k++ )
{
m_pl[n++] = m_bpsk[0][0];
}
}
}
}
}
// See if 16 PSK
if( m_format[0].constellation == M_16APSK )
{
for( int i = 0; i < blocks; i++ )
{
for( int j = 0; j < 90; j++ )
{
m_pl[n++] = m_16apsk[m_iframe[m++]&0xF];
}
block_count = (block_count+1)%16;
if((block_count == 0)&&(i<blocks-1))
{
if( m_format[0].pilots )
{
// Add pilots if needed
for( int k = 0; k < 36; k++ )
{
m_pl[n++] = m_bpsk[0][0];
}
}
}
}
}
// See if 32 APSK
if( m_format[0].constellation == M_32APSK )
{
for( int i = 0; i < blocks; i++ )
{
for( int j = 0; j < 90; j++ )
{
m_pl[n++] = m_32apsk[m_iframe[m++]&0x1F];
}
block_count = (block_count+1)%16;
if((block_count == 0)&&(i<blocks-1))
{
if( m_format[0].pilots )
{
// Add pilots if needed
for( int k = 0; k < 36; k++ )
{
m_pl[n++] = m_bpsk[0][0];
}
}
}
}
}
// Now apply the scrambler to the data part not the header
pl_scramble_symbols( &m_pl[90], n - 90 );
// Return the length
return n;
}
//
// This is not used for Broadcast mode
//
void DVBS2::pl_build_dummy( void )
{
int n = 0;
int b[90];
// Add the sync sequence SOF
for( int i = 0; i < 26; i++ ) b[i] = ph_sync_seq[i];
// Add the mode and code and sync sequence
s2_pl_header_encode( 0, 0, &b[26] );
// BPSK Modulate
for( int i = 0; i < 90; i++ )
{
m_pl[i].re = m_bpsk[i&1][b[i]].re;
m_pl[i].im = m_bpsk[i&1][b[i]].im;
}
n += (90*36);
pl_scramble_dummy_symbols( n );
m_dummy_frame_length = n;
}
scmplx * DVBS2::pl_get_frame( void )
{
return m_pl;
}
scmplx * DVBS2::pl_get_dummy( int &len )
{
scmplx * frame;
len = m_dummy_frame_length;
frame = m_pl_dummy;
return frame;
}