| 
									
										
										
										
											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 "DVB2.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Update working parameters for the next frame
 | 
					
						
							|  |  |  | // This prevents parameters changing during a frame
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | void DVB2::base_end_of_frame_actions(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if( m_params_changed ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         m_format[0] = m_format[1]; | 
					
						
							|  |  |  |         ldpc_lookup_generate(); | 
					
						
							|  |  |  |         m_params_changed = 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // reset the pointer
 | 
					
						
							|  |  |  |     m_frame_offset_bits = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This configures the system and calculates
 | 
					
						
							|  |  |  | // any required intermediate values
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | int DVB2::set_configure( DVB2FrameFormat *f ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int bch_bits = 0; | 
					
						
							|  |  |  |     int error = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( f->broadcasting ) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-07-10 22:59:13 +02:00
										 |  |  |         // Set standard parameters for broadcasting
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |         f->frame_type        = FRAME_NORMAL; | 
					
						
							|  |  |  |         f->bb_header.ts_gs   = TS_GS_TRANSPORT; | 
					
						
							|  |  |  |         f->bb_header.sis_mis = SIS_MIS_SINGLE; | 
					
						
							|  |  |  |         f->bb_header.ccm_acm = CCM; | 
					
						
							|  |  |  |         f->bb_header.issyi   = 0; | 
					
						
							|  |  |  |         f->bb_header.npd     = 0; | 
					
						
							|  |  |  |         f->bb_header.upl     = 188*8; | 
					
						
							|  |  |  |         f->bb_header.sync    = 0x47; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     f->bb_header.ro = f->roll_off; | 
					
						
							|  |  |  |     // Fill in the mode specific values and bit lengths
 | 
					
						
							|  |  |  |     if( f->frame_type == FRAME_NORMAL ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         f->nldpc = 64800; | 
					
						
							|  |  |  |         bch_bits = 192; | 
					
						
							|  |  |  |         f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |         // Apply code rate
 | 
					
						
							|  |  |  |         switch(f->code_rate ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case CR_1_4: | 
					
						
							|  |  |  |                 f->q_val = 135; | 
					
						
							|  |  |  |                 f->kbch  = 16008; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_1_3: | 
					
						
							|  |  |  |                 f->q_val = 120; | 
					
						
							|  |  |  |                 f->kbch  = 21408; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_2_5: | 
					
						
							|  |  |  |                 f->q_val = 108; | 
					
						
							|  |  |  |                 f->kbch  = 25728; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_1_2: | 
					
						
							|  |  |  |                 f->q_val = 90; | 
					
						
							|  |  |  |                 f->kbch  = 32208; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_3_5: | 
					
						
							|  |  |  |                 f->q_val = 72; | 
					
						
							|  |  |  |                 f->kbch  = 38688; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_2_3: | 
					
						
							|  |  |  |                 bch_bits = 160; | 
					
						
							|  |  |  |                 f->q_val = 60; | 
					
						
							|  |  |  |                 f->kbch  = 43040; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N10; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_3_4: | 
					
						
							|  |  |  |                 f->q_val = 45; | 
					
						
							|  |  |  |                 f->kbch  = 48408; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_4_5: | 
					
						
							|  |  |  |                 f->q_val = 36; | 
					
						
							|  |  |  |                 f->kbch  = 51648; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N12; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_5_6: | 
					
						
							|  |  |  |                 bch_bits = 160; | 
					
						
							|  |  |  |                 f->q_val = 30; | 
					
						
							|  |  |  |                 f->kbch  = 53840; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N10; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_8_9: | 
					
						
							|  |  |  |                 bch_bits = 128; | 
					
						
							|  |  |  |                 f->q_val = 20; | 
					
						
							|  |  |  |                 f->kbch  = 57472; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N8; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_9_10: | 
					
						
							|  |  |  |                 bch_bits = 128; | 
					
						
							|  |  |  |                 f->q_val = 18; | 
					
						
							|  |  |  |                 f->kbch  = 58192; | 
					
						
							|  |  |  |                 f->bch_code = BCH_CODE_N8; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  | //                loggerf("Configuration error DVB2\n");
 | 
					
						
							|  |  |  |                 error = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if( f->frame_type == FRAME_SHORT ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         f->nldpc = 16200; | 
					
						
							|  |  |  |         bch_bits = 168; | 
					
						
							|  |  |  |         f->bch_code = BCH_CODE_S12; | 
					
						
							|  |  |  |         // Apply code rate
 | 
					
						
							|  |  |  |         switch(f->code_rate ) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             case CR_1_4: | 
					
						
							|  |  |  |                 f->q_val = 36; | 
					
						
							|  |  |  |                 f->kbch  = 3072; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_1_3: | 
					
						
							|  |  |  |                 f->q_val = 30; | 
					
						
							|  |  |  |                 f->kbch  = 5232; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_2_5: | 
					
						
							|  |  |  |                 f->q_val = 27; | 
					
						
							|  |  |  |                 f->kbch  = 6312; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_1_2: | 
					
						
							|  |  |  |                 f->q_val = 25; | 
					
						
							|  |  |  |                 f->kbch  = 7032; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_3_5: | 
					
						
							|  |  |  |                 f->q_val = 18; | 
					
						
							|  |  |  |                 f->kbch  = 9552; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_2_3: | 
					
						
							|  |  |  |                 f->q_val = 15; | 
					
						
							|  |  |  |                 f->kbch  = 10632; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_3_4: | 
					
						
							|  |  |  |                 f->q_val = 12; | 
					
						
							|  |  |  |                 f->kbch  = 11712; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_4_5: | 
					
						
							|  |  |  |                 f->q_val = 10; | 
					
						
							|  |  |  |                 f->kbch  = 12432; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_5_6: | 
					
						
							|  |  |  |                 f->q_val = 8; | 
					
						
							|  |  |  |                 f->kbch  = 13152; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_8_9: | 
					
						
							|  |  |  |                 f->q_val = 5; | 
					
						
							|  |  |  |                 f->kbch  = 14232; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             case CR_9_10: | 
					
						
							|  |  |  |                 error = 1; | 
					
						
							|  |  |  |                 f->kbch  = 0; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             default: | 
					
						
							|  |  |  | //                loggerf("Configuration error DVB2\n");
 | 
					
						
							|  |  |  |                 error = -1; | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if( error == 0 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Length of the user packets
 | 
					
						
							|  |  |  |         f->bb_header.upl  = 188*8; | 
					
						
							|  |  |  |         // Payload length
 | 
					
						
							|  |  |  |         f->bb_header.dfl = f->kbch - 80; | 
					
						
							|  |  |  |         // Transport packet sync
 | 
					
						
							|  |  |  |         f->bb_header.sync = 0x47; | 
					
						
							|  |  |  |         // Start of LDPC bits
 | 
					
						
							|  |  |  |         f->kldpc = f->kbch + bch_bits; | 
					
						
							|  |  |  |         // Number of padding bits required (not used)
 | 
					
						
							|  |  |  |         f->padding_bits = 0; | 
					
						
							| 
									
										
										
										
											2024-07-10 22:59:13 +02:00
										 |  |  |         // Number of usable data bits (not used)
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |         f->useable_data_bits = f->kbch - 80; | 
					
						
							|  |  |  |         // Save the configuration, will be updated on next frame
 | 
					
						
							|  |  |  |         m_format[1] = *f; | 
					
						
							|  |  |  |         // reset various pointers
 | 
					
						
							|  |  |  |         m_dnp   = 0;// No deleted null packets
 | 
					
						
							|  |  |  |         // Signal we need to update on the next frame.
 | 
					
						
							|  |  |  |         if( m_params_changed ) | 
					
						
							|  |  |  |             base_end_of_frame_actions(); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             m_params_changed = 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return error; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | void DVB2::get_configure( DVB2FrameFormat *f ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     *f = m_format[1]; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Points to first byte in transport packet
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int DVB2::add_ts_frame_base( u8 *ts ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if( m_frame_offset_bits == 0 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |          // New frame needs to be sent
 | 
					
						
							|  |  |  |         add_bbheader(); // Add the header
 | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     // Add a new transport packet
 | 
					
						
							|  |  |  |     unpack_transport_packet_add_crc( ts ); | 
					
						
							|  |  |  |     // Have we reached the end?
 | 
					
						
							|  |  |  |     if( m_frame_offset_bits == m_format[0].kbch ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // Yes so now Scramble the BB frame
 | 
					
						
							|  |  |  |         bb_randomise(); | 
					
						
							|  |  |  |         // BCH encode the BB Frame
 | 
					
						
							|  |  |  |         bch_encode(); | 
					
						
							|  |  |  |         // LDPC encode the BB frame and BCHFEC bits
 | 
					
						
							|  |  |  |         ldpc_encode(); | 
					
						
							|  |  |  |         // Signal to the modulation specific class we have something to send
 | 
					
						
							|  |  |  |         base_end_of_frame_actions(); | 
					
						
							|  |  |  |         return 1; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // Dump NULL packets appends a counter to the end of each UP
 | 
					
						
							|  |  |  | // it is not implemented at the moment.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | int DVB2::next_ts_frame_base( u8 *ts ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int res = 0; | 
					
						
							|  |  |  |     // See if we need to dump null packets
 | 
					
						
							|  |  |  |     if( m_format[0].null_deletion == 1 ) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if(((ts[0]&0x1F) == 0x1F)&&(ts[1] == 0xFF )) | 
					
						
							|  |  |  |         { | 
					
						
							|  |  |  |             // Null packet detected
 | 
					
						
							|  |  |  |             if( m_dnp < 0xFF ) | 
					
						
							|  |  |  |             { | 
					
						
							|  |  |  |                 m_dnp++;// Increment the number of null packets
 | 
					
						
							|  |  |  |                 return 0; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-11-18 06:36:53 +01:00
										 |  |  |     // Need to send a new transport packet
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |     res = add_ts_frame_base( ts ); | 
					
						
							|  |  |  |     if( res ) m_dnp = 0;// Clear the DNP counter
 | 
					
						
							|  |  |  |     // return whether it is time to transmit a new frame
 | 
					
						
							|  |  |  |     return res; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | DVB2::DVB2(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // Clear the transport queue
 | 
					
						
							|  |  |  |     m_tp_q.empty(); | 
					
						
							|  |  |  |     init_bb_randomiser(); | 
					
						
							|  |  |  |     bch_poly_build_tables(); | 
					
						
							|  |  |  |     build_crc8_table(); | 
					
						
							| 
									
										
										
										
											2024-07-10 22:59:13 +02:00
										 |  |  |     m_dnp   = 0;// No deleted null packets
 | 
					
						
							| 
									
										
										
										
											2021-03-31 16:41:42 +01:00
										 |  |  |     m_frame_offset_bits = 0; | 
					
						
							|  |  |  |     m_params_changed = 1; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | DVB2::~DVB2(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } |