| 
									
										
										
										
											2023-11-18 06:36:53 +01:00
										 |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							|  |  |  | // 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/>.              //
 | 
					
						
							|  |  |  | ///////////////////////////////////////////////////////////////////////////////////////
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  | #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; | 
					
						
							|  |  |  | } |