├── DvbTsToIQ ├── DvbTsToIQ.cpp ├── DvbTsToIQ.vcxproj └── Makefile ├── README.md ├── libdvbmod.sln └── libdvbmod ├── DVB-S ├── dvb_interleave.cpp ├── dvb_rs_encoder.cpp ├── dvbs.h ├── dvbs_conv.cpp ├── dvbs_encode.cpp ├── dvbs_modulator.old └── dvbs_receive.cpp ├── DVB-S2 ├── DVB2.cpp ├── DVB2.h ├── DVBS2.cpp ├── DVBS2.h ├── dvb2_bbheader.cpp ├── dvb2_bch.cpp ├── dvb2_ldpc_encode.cpp ├── dvb2_ldpc_tables.cpp ├── dvb2_scrambler.cpp ├── dvbs2_interleave.cpp ├── dvbs2_modulator.cpp ├── dvbs2_physical.cpp ├── dvbs2_scrambler.cpp └── dvbs2_tables.cpp ├── DVB-T ├── dvb_t.cpp ├── dvb_t.h ├── dvb_t_bits.cpp ├── dvb_t_enc.cpp ├── dvb_t_i.cpp ├── dvb_t_linux_fft.cpp ├── dvb_t_lpf.cpp ├── dvb_t_mod.cpp ├── dvb_t_qam_tab.cpp ├── dvb_t_stab.cpp ├── dvb_t_sym.cpp ├── dvb_t_sym.h └── dvb_t_tp.cpp ├── Makefile ├── dvb.h ├── dvb_types.h ├── libdvbmod.cpp ├── libdvbmod.h └── libdvbmod.vcxproj /DvbTsToIQ/DvbTsToIQ.cpp: -------------------------------------------------------------------------------- 1 | // DvbTsToIQ.cpp�: d�finit le point d'entr�e pour l'application console. 2 | // 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "../libdvbmod/libdvbmod.h" 9 | #include 10 | #include 11 | #include 12 | #define PROGRAM_VERSION "0.0.1" 13 | 14 | #ifndef WINDOWS 15 | 16 | /* Non-windows includes */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include /* IPPROTO_IP, sockaddr_in, htons(), 23 | htonl() */ 24 | #include /* inet_addr() */ 25 | #include 26 | #else 27 | 28 | /* Windows-specific includes */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | 35 | #endif /* WINDOWS */ 36 | #include 37 | #include 38 | 39 | FILE *input, *output; 40 | enum 41 | { 42 | DVBS, 43 | DVBS2 44 | }; 45 | int Bitrate = 0; 46 | int ModeDvb = 0; 47 | #define BUFFER_SIZE (188) 48 | int Pilot = 0; 49 | unsigned int SymbolRate = 0; 50 | int FEC = CR_1_2; 51 | bool Simu=false; 52 | float GainSimu=1.0; // Gain QSB 53 | float TimingSimu=1.0; //Cycle QSB 54 | 55 | static uint64_t _timestamp_ns(void) 56 | { 57 | struct timespec tp; 58 | 59 | if (clock_gettime(CLOCK_REALTIME, &tp) != 0) 60 | { 61 | return (0); 62 | } 63 | 64 | return ((int64_t)tp.tv_sec * 1e9 + tp.tv_nsec); 65 | } 66 | 67 | unsigned int NullFiller(int NbPacket) 68 | { 69 | unsigned char NullPacket[188] = {0x47, 0x1F, 0xFF}; 70 | unsigned int TotalSampleWritten = 0; 71 | for (int i = 0; i < NbPacket; i++) 72 | { 73 | int len; 74 | if (ModeDvb == DVBS) 75 | len = DvbsAddTsPacket(NullPacket); 76 | if (ModeDvb == DVBS2) 77 | len = Dvbs2AddTsPacket(NullPacket); 78 | if (len != 0) 79 | { 80 | sfcmplx *Frame = NULL; 81 | //fprintf(stderr, "Len %d\n", len); 82 | if (ModeDvb == DVBS) 83 | Frame = Dvbs_get_IQ(); 84 | if (ModeDvb == DVBS2) 85 | Frame = Dvbs2_get_IQ(); 86 | 87 | fwrite(Frame, sizeof(sfcmplx), len, output); 88 | TotalSampleWritten += len; 89 | } 90 | } 91 | return TotalSampleWritten; 92 | } 93 | 94 | unsigned int CalibrateOutput() 95 | { 96 | int n, ret; 97 | static uint64_t TimeBefore = 0; 98 | ret = ioctl(fileno(output), FIONREAD, &n); 99 | int n_start = 0; 100 | usleep(1e6); 101 | NullFiller(10000); 102 | 103 | ret = ioctl(fileno(output), FIONREAD, &n); 104 | n_start = n; 105 | TimeBefore = _timestamp_ns(); 106 | fprintf(stderr, "Fillstart is %i %lu\n", n_start, TimeBefore); 107 | uint WaitSampleWritten = 0; 108 | while (WaitSampleWritten < SymbolRate) 109 | { 110 | WaitSampleWritten += NullFiller(1); 111 | } 112 | 113 | fprintf(stderr, "Fillstop is %i %lu\n", n, _timestamp_ns()); 114 | unsigned int OutSampleRate = (WaitSampleWritten)*1e9 / (_timestamp_ns() - TimeBefore); 115 | return OutSampleRate; 116 | } 117 | 118 | bool Tune(int Frequency) 119 | { 120 | 121 | #define LEN_CARRIER 1000 122 | static sfcmplx Frame[LEN_CARRIER]; 123 | if(Frequency==0) 124 | for(int i=0;i Filling\n"); 173 | 174 | } 175 | else 176 | { 177 | usleep(1); 178 | //fprintf(stderr, "OK in =%d out%d\n", nin, nout); 179 | } 180 | ret = ioctl(fileno(input), FIONREAD, &nin); 181 | 182 | } 183 | } 184 | else 185 | { 186 | //fprintf(stderr,"OK in =%d out%d\n",nin,nout); 187 | } 188 | if ((nin > 64000) && (nout > 64000)) 189 | fprintf(stderr, "DVB2IQ fifoin %d fifoout %d\n", nin, nout); 190 | */ 191 | } 192 | 193 | int NbRead = fread(BufferTS, 1, BUFFER_SIZE, input); 194 | DebugReceivedpacket += NbRead; 195 | if (NbRead != BUFFER_SIZE) 196 | { 197 | if (!live) 198 | { 199 | fseek(input, 0, SEEK_SET); 200 | fprintf(stderr,"TS Loop file\n"); 201 | return true; 202 | //return false; //end of file 203 | } 204 | } 205 | 206 | if (NbRead % 188 != 0) 207 | fprintf(stderr, "TS alignment Error\n"); 208 | if (BufferTS[0] != 0x47) 209 | { 210 | fprintf(stderr, "TS Sync Error Try to Resynch\n"); 211 | for (int i = 0; i < NbRead; i++) 212 | { 213 | if (BufferTS[i] == 0x47) 214 | { 215 | fread(BufferTS, 1, i, input); //Try to read garbage 216 | fprintf(stderr, "TS Sync recovery\n"); 217 | break; 218 | } 219 | } 220 | fread(BufferTS, 1, BUFFER_SIZE, input); //Read the next aligned 221 | } 222 | for (int i = 0; i < NbRead; i += 188) 223 | { 224 | int len = 0; 225 | /*if ((BufferTS[i + 1] == 0x1F) && (BufferTS[i + 2] == 0xFF)) 226 | continue; // Remove Null packets*/ 227 | if (ModeDvb == DVBS) 228 | len = DvbsAddTsPacket(BufferTS + i); 229 | if (ModeDvb == DVBS2) 230 | len = Dvbs2AddTsPacket(BufferTS + i); 231 | 232 | if (len != 0) 233 | { 234 | sfcmplx *Frame = NULL; 235 | //fprintf(stderr, "Len %d\n", len); 236 | if (ModeDvb == DVBS) 237 | Frame = Dvbs_get_IQ(); 238 | if (ModeDvb == DVBS2) 239 | Frame = Dvbs2_get_IQ(); 240 | if(Simu==false) 241 | { 242 | int nout; 243 | ioctl(fileno(output), FIONREAD, &nout); 244 | 245 | /*if(0xFFFF-nout \n",len*sizeof(sfcmplx),nout); 248 | return true; 249 | }*/ 250 | fwrite(Frame, sizeof(sfcmplx), len, output); 251 | } 252 | /*else 253 | { 254 | sfcmplx *FrameSimu=(sfcmplx *)malloc(len*sizeof(sfcmplx)); 255 | for(int j=0;j 4) 416 | upsample = 4; 417 | break; 418 | case 'v': 419 | ShortFrame = true; 420 | break; 421 | case -1: 422 | break; 423 | case '?': 424 | if (isprint(optopt)) 425 | { 426 | fprintf(stderr, "dvb2iq `-%c'.\n", optopt); 427 | } 428 | else 429 | { 430 | fprintf(stderr, "dvb2iq: unknown option character `\\x%x'.\n", optopt); 431 | } 432 | print_usage(); 433 | 434 | exit(1); 435 | break; 436 | default: 437 | print_usage(); 438 | exit(1); 439 | break; 440 | } /* end switch a */ 441 | } /* end while getopt() */ 442 | 443 | if (SymbolRate == 0) 444 | { 445 | fprintf(stderr, "SymbolRate is mandatory !\n"); 446 | exit(0); 447 | } 448 | if ((ModeDvb == DVBS)&&(FEC>=0)) 449 | { 450 | Bitrate = DvbsInit(SymbolRate, FEC, Constellation, upsample); 451 | } 452 | if ((ModeDvb == DVBS2)&&(FEC>=0)) 453 | { 454 | Bitrate = Dvbs2Init(SymbolRate, FEC, Constellation, Pilot, RO_0_35, upsample,ShortFrame); 455 | } 456 | 457 | fprintf(stderr, "Net TS bitrate input should be %d\n", Bitrate); 458 | if(AskNetBitrate) 459 | { 460 | fprintf(stdout, "%d\n", Bitrate); 461 | exit(1); 462 | } 463 | bool isapipe = (fseek(input, 0, SEEK_CUR) < 0); //Dirty trick to see if it is a pipe or not 464 | if (isapipe) 465 | { 466 | 467 | 468 | fprintf(stderr, "Using live mode\n"); 469 | } 470 | else 471 | fprintf(stderr, "Using file mode\n"); 472 | while (!want_quit && RunWithFile(isapipe)) 473 | ; 474 | 475 | return 0; 476 | } 477 | -------------------------------------------------------------------------------- /DvbTsToIQ/DvbTsToIQ.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {07FDFF87-0845-4321-B355-0C2C53CAEB25} 24 | Win32Proj 25 | DvbTsToIQ 26 | 10.0.14393.0 27 | 28 | 29 | 30 | Application 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | Application 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | Application 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | Application 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | true 75 | 76 | 77 | true 78 | 79 | 80 | false 81 | 82 | 83 | false 84 | 85 | 86 | 87 | 88 | 89 | Level3 90 | Disabled 91 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 92 | 93 | 94 | Console 95 | ../Debug/libdvbmod.lib;%(AdditionalDependencies) 96 | 97 | 98 | 99 | 100 | 101 | 102 | Level3 103 | Disabled 104 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 105 | 106 | 107 | Console 108 | 109 | 110 | 111 | 112 | Level3 113 | 114 | 115 | MaxSpeed 116 | true 117 | true 118 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 119 | 120 | 121 | Console 122 | true 123 | true 124 | 125 | 126 | 127 | 128 | Level3 129 | 130 | 131 | MaxSpeed 132 | true 133 | true 134 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 135 | 136 | 137 | Console 138 | true 139 | true 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | -------------------------------------------------------------------------------- /DvbTsToIQ/Makefile: -------------------------------------------------------------------------------- 1 | all: dvb2iq 2 | 3 | CC = g++ 4 | CFLAGS = -Wall -g -O2 5 | LDFLAGS = -lm -lrt -lfftw3 -lpthread 6 | 7 | .cpp.o: 8 | $(CC) $(CFLAGS) -c $< 9 | 10 | dvb2iq : DvbTsToIQ.o ../libdvbmod/lib/libdvbmod.a 11 | $(CC) $(CFLAGS) $(LDFLAGS) -o dvb2iq DvbTsToIQ.o ../libdvbmod/lib/libdvbmod.a 12 | 13 | clean: 14 | rm -f *.o dvb2iq -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libdvbmod 2 | A simple library to get I/Q symbols from a MPEG Transport stream 3 | 4 | This is a rework on developments from G4GUO for DatvExpress 5 | 6 | #Dependencies 7 | FFTW3 : on debian based : sudo apt-get install libfftw3-dev 8 | -------------------------------------------------------------------------------- /libdvbmod.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26228.10 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libdvbmod", "libdvbmod\libdvbmod.vcxproj", "{96163F30-C318-4CF5-97B0-DFB367FDDC68}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Debug|x64.ActiveCfg = Debug|x64 17 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Debug|x64.Build.0 = Debug|x64 18 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Debug|x86.ActiveCfg = Debug|Win32 19 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Debug|x86.Build.0 = Debug|Win32 20 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Release|x64.ActiveCfg = Release|x64 21 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Release|x64.Build.0 = Release|x64 22 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Release|x86.ActiveCfg = Release|Win32 23 | {96163F30-C318-4CF5-97B0-DFB367FDDC68}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvb_interleave.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "../dvb.h" 3 | #include "dvbs.h" 4 | 5 | #define I_MOD 17 6 | #define I_ROWS 12 7 | 8 | uint8_t d_array[2000];//where data is stored 9 | uint8_t *rows[I_ROWS];// data rows 10 | unsigned long i_mc[I_ROWS];// current row 11 | int i_mods[I_ROWS];//length of each row 12 | 13 | void dvb_interleave_init( void ) 14 | { 15 | int i; 16 | int m = 0; 17 | rows[0] = &d_array[m]; 18 | m++; 19 | for( i = 1; i < I_ROWS; i++ ) 20 | { 21 | rows[i] = &d_array[m]; 22 | i_mods[i] = (I_MOD*i); 23 | m += i_mods[i]; 24 | i_mc[i] = 0; 25 | } 26 | //printf("%d \n",m ); 27 | } 28 | inline void dvb_interleave_sub( uint8_t *inout ) 29 | { 30 | int i; 31 | int off; 32 | uint8_t out; 33 | 34 | // rows[0][0] = inout[0]; 35 | // inout[0] = rows[0][0]; 36 | 37 | for( i = 1; i < I_ROWS; i++ ) 38 | { 39 | off = i_mc[i]; 40 | out = rows[i][off]; 41 | rows[i][off] = inout[i]; 42 | inout[i] = out; 43 | // Update modulo counter 44 | i_mc[i] = (i_mc[i]+1)%i_mods[i]; 45 | } 46 | } 47 | // 48 | // Do this inplace, interleave the bytes 49 | // 50 | 51 | void dvb_convolutional_interleave( uint8_t *inout ) 52 | { 53 | int i; 54 | 55 | for( i = 0; i < DVBS_T_CODED_FRAME_LEN; i+= I_ROWS ) 56 | { 57 | dvb_interleave_sub( &inout[i] ); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvb_rs_encoder.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "memory.h" 3 | #include "../dvb.h" 4 | 5 | #ifdef __TEST__ 6 | 7 | // Shorter test RS code 8 | #define G_POLY 0x3 9 | #define G_BITS 4 10 | #define G_MASK 0xF 11 | #define G_OVR 0x10 12 | #define G_MSB 0x8 13 | #define G_SIZE 16 14 | #define RS_LEN 4 15 | #define M_LEN 11 16 | #define P_LEN 4 17 | #define gadd(a,b) (a^b) 18 | #define gsub(a,b) (a^b) 19 | #define gmul(a,b) (gmult_tab[a][b]) 20 | 21 | uint8_t gpoly[RS_LEN]={12,1,3,15}; 22 | #else 23 | 24 | // DVB-S RS code 25 | #define G_POLY 0x1D 26 | #define G_BITS 8 27 | #define G_MASK 0xFF 28 | #define G_OVR 0x100 29 | #define G_MSB 0x80 30 | #define G_SIZE 256 31 | #define RS_LEN 16 32 | #define M_LEN 188 33 | #define P_LEN 16 34 | #define gadd(a,b) (a^b) 35 | #define gsub(a,b) (a^b) 36 | #define gmul(a,b) (gmult_tab[a][b]) 37 | 38 | // Generator Polynomial (reverse order, highest order ignored) 39 | uint8_t gpoly[RS_LEN]={59,36,50,98,229,41,65,163,8,30,209,68,189,104,13,59}; 40 | 41 | #endif 42 | 43 | uint8_t gf[G_SIZE]; 44 | uint8_t gmult_tab[G_SIZE][RS_LEN]; 45 | uint8_t l_shift[RS_LEN]; 46 | 47 | inline uint8_t gmult(uint8_t a, uint8_t b) 48 | { 49 | uint8_t p = 0; 50 | int i; 51 | uint8_t hbs; 52 | for( i = 0; i < G_BITS; i++) 53 | { 54 | if((b & 1) == 1) 55 | p ^= a; 56 | hbs = (a & G_MSB); 57 | a <<= 1; 58 | if(hbs == G_MSB) 59 | { 60 | a ^= G_POLY; 61 | a &= G_MASK; 62 | } 63 | b >>= 1; 64 | } 65 | return p; 66 | } 67 | // 68 | // Fast multiply table 69 | // 70 | void build_gf_mult_tab( void ) 71 | { 72 | int a,b; 73 | 74 | for( a = 0; a < G_SIZE; a++ ) 75 | { 76 | for( b = 0; b < RS_LEN; b++ ) 77 | { 78 | gmult_tab[a][b] = gmult( a, gpoly[b] ); 79 | } 80 | } 81 | } 82 | // 83 | // Construct the Galois field from the generator poly. 84 | // 85 | void build_gf_tab( void ) 86 | { 87 | int i; 88 | int n = 1; 89 | int temp[1000]; 90 | temp[0] = 1; 91 | for( i = 1; i < G_MASK; i++ ) 92 | { 93 | temp[i] = temp[i-1]<<1; 94 | if(temp[i] >= G_OVR ) 95 | { 96 | temp[i] &= G_MASK; 97 | temp[i] ^= G_POLY; 98 | } 99 | } 100 | gf[0] = 0; 101 | for( i = 0; i < G_SIZE-1; i++ ) //GSIZE-1 : Fixme : Nee to check if valid : GSIZE in original code 102 | { 103 | gf[n++] = temp[i]; 104 | } 105 | 106 | #ifdef __TEST__ 107 | 108 | for( i = 0; i < G_SIZE; i++ ) 109 | { 110 | //printf("%d %.2X\n",i,gf[i]); 111 | printf("%d %d\n",i,gf[i]); 112 | } 113 | uint8_t b = gf[2]; 114 | uint8_t v = gmult( 0x53, 0xCA ); 115 | printf("\nRes %.2X\n",v ); 116 | 117 | #endif 118 | } 119 | /* 120 | inline uint8_t old_rs_round( void ) 121 | { 122 | int i; 123 | uint8_t sum = 0; 124 | 125 | for( i = 0; i < RS_LEN; i++ ) 126 | { 127 | sum = gadd(sum,gmul(l_shift[i],gpoly[i])); 128 | } 129 | return sum; 130 | } 131 | */ 132 | inline uint8_t rs_round( uint8_t val ) 133 | { 134 | uint8_t sum = 0; 135 | 136 | sum = gadd(sum,gmul(l_shift[0],0)); 137 | l_shift[0] = l_shift[1]; 138 | sum = gadd(sum,gmul(l_shift[1],1)); 139 | l_shift[1] = l_shift[2]; 140 | sum = gadd(sum,gmul(l_shift[2],2)); 141 | l_shift[2] = l_shift[3]; 142 | sum = gadd(sum,gmul(l_shift[3],3)); 143 | l_shift[3] = l_shift[4]; 144 | sum = gadd(sum,gmul(l_shift[4],4)); 145 | l_shift[4] = l_shift[5]; 146 | sum = gadd(sum,gmul(l_shift[5],5)); 147 | l_shift[5] = l_shift[6]; 148 | sum = gadd(sum,gmul(l_shift[6],6)); 149 | l_shift[6] = l_shift[7]; 150 | sum = gadd(sum,gmul(l_shift[7],7)); 151 | l_shift[7] = l_shift[8]; 152 | sum = gadd(sum,gmul(l_shift[8],8)); 153 | l_shift[8] = l_shift[9]; 154 | sum = gadd(sum,gmul(l_shift[9],9)); 155 | l_shift[9] = l_shift[10]; 156 | sum = gadd(sum,gmul(l_shift[10],10)); 157 | l_shift[10] = l_shift[11]; 158 | sum = gadd(sum,gmul(l_shift[11],11)); 159 | l_shift[11] = l_shift[12]; 160 | sum = gadd(sum,gmul(l_shift[12],12)); 161 | l_shift[12] = l_shift[13]; 162 | sum = gadd(sum,gmul(l_shift[13],13)); 163 | l_shift[13] = l_shift[14]; 164 | sum = gadd(sum,gmul(l_shift[14],14)); 165 | l_shift[14] = l_shift[15]; 166 | sum = gadd(sum,gmul(l_shift[15],15)); 167 | l_shift[15] = sum ^ val; 168 | return sum; 169 | } 170 | inline uint8_t rs_round( void ) 171 | { 172 | uint8_t sum; 173 | 174 | sum = gadd(0,gmul(l_shift[0],0)); 175 | l_shift[0] = l_shift[1]; 176 | sum = gadd(sum,gmul(l_shift[1],1)); 177 | l_shift[1] = l_shift[2]; 178 | sum = gadd(sum,gmul(l_shift[2],2)); 179 | l_shift[2] = l_shift[3]; 180 | sum = gadd(sum,gmul(l_shift[3],3)); 181 | l_shift[3] = l_shift[4]; 182 | sum = gadd(sum,gmul(l_shift[4],4)); 183 | l_shift[4] = l_shift[5]; 184 | sum = gadd(sum,gmul(l_shift[5],5)); 185 | l_shift[5] = l_shift[6]; 186 | sum = gadd(sum,gmul(l_shift[6],6)); 187 | l_shift[6] = l_shift[7]; 188 | sum = gadd(sum,gmul(l_shift[7],7)); 189 | l_shift[7] = l_shift[8]; 190 | sum = gadd(sum,gmul(l_shift[8],8)); 191 | l_shift[8] = l_shift[9]; 192 | sum = gadd(sum,gmul(l_shift[9],9)); 193 | l_shift[9] = l_shift[10]; 194 | sum = gadd(sum,gmul(l_shift[10],10)); 195 | l_shift[10] = l_shift[11]; 196 | sum = gadd(sum,gmul(l_shift[11],11)); 197 | l_shift[11] = l_shift[12]; 198 | sum = gadd(sum,gmul(l_shift[12],12)); 199 | l_shift[12] = l_shift[13]; 200 | sum = gadd(sum,gmul(l_shift[13],13)); 201 | l_shift[13] = l_shift[14]; 202 | sum = gadd(sum,gmul(l_shift[14],14)); 203 | l_shift[14] = l_shift[15]; 204 | sum = gadd(sum,gmul(l_shift[15],15)); 205 | l_shift[15] = 0; 206 | return sum; 207 | } 208 | // 209 | // Build all the required tables 210 | // 211 | void dvb_rs_init( void ) 212 | { 213 | build_gf_tab(); 214 | build_gf_mult_tab(); 215 | 216 | #ifdef __TEST__ 217 | 218 | // Test code 219 | int i; 220 | uint8_t in[15]={1,2,3,4,5,6,7,8,9,10,11,0,0,0,0}; 221 | printf("\n"); 222 | dvb_rs_encode( in ); 223 | for( i = 0; i < 15; i++ ) 224 | { 225 | printf(" %d,",in[i] ); 226 | } 227 | printf("\n"); 228 | 229 | #endif 230 | 231 | } 232 | // 233 | // This is a RS(255,239,8) RS encoder 234 | // The 188 byte blocks are padded out to 239 bytes 235 | // by adding 51 zero bytes at the beginning and then removing 236 | // them before transmission. 237 | // 238 | // Operates in place 239 | // 240 | void dvb_rs_encode( uint8_t *inout ) 241 | { 242 | // The shift register has been zeroed by this point 243 | uint8_t *b = inout; 244 | // Data phase use feedback 245 | int i; 246 | 247 | for( i = 0; i < M_LEN; i++ ) rs_round(b[i]); 248 | 249 | // Parity phase use 16 zeros 250 | b[i++] = rs_round(); 251 | b[i++] = rs_round(); 252 | b[i++] = rs_round(); 253 | b[i++] = rs_round(); 254 | b[i++] = rs_round(); 255 | b[i++] = rs_round(); 256 | b[i++] = rs_round(); 257 | b[i++] = rs_round(); 258 | b[i++] = rs_round(); 259 | b[i++] = rs_round(); 260 | b[i++] = rs_round(); 261 | b[i++] = rs_round(); 262 | b[i++] = rs_round(); 263 | b[i++] = rs_round(); 264 | b[i++] = rs_round(); 265 | b[i++] = rs_round(); 266 | } 267 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvbs.h: -------------------------------------------------------------------------------- 1 | #define MP_T_SYNC 0x47 2 | #define DVBS_T_ISYNC 0xB8 3 | #define DVBS_T_PAYLOAD_LEN 187 4 | #define MP_T_FRAME_LEN 188 5 | #define DVBS_RS_BLOCK_DATA 239 6 | #define DVBS_RS_BLOCK_PARITY 16 7 | #define DVBS_RS_BLOCK (DVBS_RS_BLOCK_DATA+DVBS_RS_BLOCK_PARITY) 8 | #define DVBS_PARITY_LEN 16 9 | #define DVBS_T_CODED_FRAME_LEN (MP_T_FRAME_LEN+DVBS_PARITY_LEN) 10 | #define DVBS_T_FRAMES_IN_BLOCK 8 11 | #define DVBS_T_BIT_WIDTH 8 12 | #define DVBS_T_SCRAM_SEQ_LENGTH 1503 13 | 14 | extern void dvb_encode_init(int FEC); 15 | extern int dvb_encode_frame(uint8_t *tp, uint8_t *dibit); -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvbs_conv.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "../dvb.h" 3 | 4 | #define CONV_STATES 128 5 | 6 | //131 Y 7 | #define C20MASK 0x0001 8 | #define C21MASK 0x0002 9 | #define C23MASK 0x0008 10 | #define C24MASK 0x0010 11 | #define C26MASK 0x0040 12 | 13 | //171 X 14 | #define C10MASK 0x0001 15 | #define C13MASK 0x0008 16 | #define C14MASK 0x0010 17 | #define C15MASK 0x0020 18 | #define C16MASK 0x0040 19 | 20 | static uint8_t conv_tab[CONV_STATES]; 21 | static int encode_state; 22 | static int dvbs_code_rate; 23 | // Storage 24 | static uint8_t mb[10]; 25 | static int mbc; 26 | // 27 | // Calculate the parity 28 | // Bit 0 is G1 (X) 29 | // Bit 1 is G2 (Y) 30 | // 31 | uint8_t dvb_conv_parity( int state ) 32 | { 33 | uint8_t count; 34 | uint8_t parity; 35 | 36 | count = 0; 37 | if(state&C20MASK) count++; 38 | if(state&C21MASK) count++; 39 | if(state&C23MASK) count++; 40 | if(state&C24MASK) count++; 41 | if(state&C26MASK) count++; 42 | 43 | parity = (count&1)<<1; 44 | 45 | count = 0; 46 | if(state&C10MASK) count++; 47 | if(state&C13MASK) count++; 48 | if(state&C14MASK) count++; 49 | if(state&C15MASK) count++; 50 | if(state&C16MASK) count++; 51 | 52 | parity |= (count&1); 53 | 54 | return parity; 55 | } 56 | 57 | void dvb_conv_ctl( void ) 58 | { 59 | mbc = 0; 60 | encode_state = 0; 61 | } 62 | 63 | void dvb_conv_init( int FEC ) 64 | { 65 | int i; 66 | 67 | 68 | // Build the encoding Tables 69 | for( i = 0; i < CONV_STATES; i++) 70 | { 71 | conv_tab[i] = dvb_conv_parity( i ); 72 | } 73 | 74 | dvb_conv_ctl(); 75 | // FixMe should pass FEC 76 | dvbs_code_rate = FEC; 77 | //if( info.dvb_mode == MODE_DVBS ) dvbs_code_rate = info.dvbs_fmt.fec; 78 | //if( info.dvb_mode == MODE_DVBT ) dvbs_code_rate = info.dvbt_fmt.fec; 79 | 80 | } 81 | inline uint8_t dvb_conv_encode_bit( uint8_t in ) 82 | { 83 | encode_state = encode_state>>1; 84 | 85 | if(in) encode_state |= 0x40; 86 | 87 | return conv_tab[encode_state]; 88 | } 89 | // 90 | // This punctures the dibits I channel Bit 0, Q channel Bit 1 91 | // The output length varies depending on the puncture rate. 92 | // The input array is overwritten 93 | // 94 | int dvb_puncture( uint8_t *in, int len ) 95 | { 96 | int i; 97 | uint8_t tmp[2000]; 98 | // Output length 99 | int odx = 0; 100 | 101 | if( dvbs_code_rate == FEC_12 ) 102 | { 103 | // Nothing to do 104 | return len; 105 | } 106 | 107 | if( dvbs_code_rate == FEC_23 ) 108 | { 109 | for( i = 0; i < len; i++ ) 110 | { 111 | mb[mbc++] = in[i]; 112 | if( mbc == 4 ) 113 | { 114 | tmp[odx++] = mb[0]; //(Y1,X1) LSB == X (sent first) 115 | tmp[odx++] = ((mb[2]<<1)&0x02)|(mb[1]>>1);//(X3,Y2) 116 | tmp[odx++] = (mb[3]&0x2)|(mb[2]>>1);//(Y4,Y3) 117 | mbc = 0; 118 | } 119 | } 120 | } 121 | 122 | if( dvbs_code_rate == FEC_34 ) 123 | { 124 | for( i = 0; i < len; i++ ) 125 | { 126 | mb[mbc++] = in[i]; 127 | if( mbc == 3 ) 128 | { 129 | tmp[odx++] = mb[0]; //(Y1,X1) 130 | tmp[odx++] = ((mb[2]<<1)&0x02)|(mb[1]>>1);//(X3,Y2) 131 | mbc = 0; 132 | } 133 | } 134 | } 135 | 136 | if( dvbs_code_rate == FEC_56 ) 137 | { 138 | for( i = 0; i < len; i++ ) 139 | { 140 | mb[mbc++] = in[i]; 141 | if( mbc == 5 ) 142 | { 143 | tmp[odx++] = mb[0]; //(Y1,X1) 144 | tmp[odx++] = ((mb[2]<<1)&0x02)|(mb[1]>>1); //(X3,Y2) 145 | tmp[odx++] = ((mb[4]<<1)&0x02)|(mb[3]>>1); //(X5,Y4) 146 | mbc = 0; 147 | } 148 | } 149 | } 150 | 151 | if( dvbs_code_rate == FEC_78 ) 152 | { 153 | for( i = 0; i < len; i++ ) 154 | { 155 | mb[mbc++] = in[i]; 156 | if( mbc == 7 ) 157 | { 158 | tmp[odx++] = mb[0]; //(Y1,X1) 159 | tmp[odx++] = (mb[2]&0x02)|(mb[1]>>1);//(Y3,Y2) 160 | tmp[odx++] = ((mb[4]<<1)&0x2)|(mb[3]>>1);//(X5,Y4) 161 | tmp[odx++] = ((mb[6]<<1)&0x2)|(mb[5]>>1);//(X7,Y6) 162 | mbc = 0; 163 | } 164 | } 165 | } 166 | memcpy(in,tmp,sizeof(uint8_t)*odx); 167 | return odx; 168 | } 169 | // 170 | // The input is octets and the output is dibits. 171 | // 172 | int dvb_conv_encode_frame( uint8_t *in, uint8_t *out, int len ) 173 | { 174 | int i; 175 | int odx=0; 176 | 177 | for( i = 0; i < len; i++ ) 178 | { 179 | out[odx++] = dvb_conv_encode_bit( in[i]&0x80 ); 180 | out[odx++] = dvb_conv_encode_bit( in[i]&0x40 ); 181 | out[odx++] = dvb_conv_encode_bit( in[i]&0x20 ); 182 | out[odx++] = dvb_conv_encode_bit( in[i]&0x10 ); 183 | out[odx++] = dvb_conv_encode_bit( in[i]&0x08 ); 184 | out[odx++] = dvb_conv_encode_bit( in[i]&0x04 ); 185 | out[odx++] = dvb_conv_encode_bit( in[i]&0x02 ); 186 | out[odx++] = dvb_conv_encode_bit( in[i]&0x01 ); 187 | } 188 | odx = dvb_puncture( out, odx ); 189 | return odx; 190 | } 191 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvbs_encode.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "../dvb.h" 3 | #include "dvbs.h" 4 | #include 5 | extern void dvb_rs_encode(uint8_t *inout); 6 | extern void dvb_convolutional_interleave(uint8_t *inout); 7 | extern int dvb_conv_encode_frame(uint8_t *in, uint8_t *out, int len); 8 | extern void dvb_conv_init(int FEC); 9 | extern void dvb_interleave_init(void); 10 | extern void dvb_rs_init(void); 11 | 12 | 13 | unsigned int s_reg;// Register used for scrambler 14 | unsigned char dvbs_s_table[DVBS_T_SCRAM_SEQ_LENGTH];//Scrambler table 15 | static int m_fc; 16 | static int m_sc; 17 | 18 | // 19 | // Called once 20 | // 21 | 22 | int dvb_scramble_bit( void ) 23 | { 24 | int out = s_reg&0x01; 25 | //Shift 26 | s_reg >>= 1; 27 | 28 | out ^= (s_reg&1); 29 | 30 | if( out ) s_reg |= 0x4000; 31 | 32 | return out; 33 | } 34 | void dvb_scrambler_init( void ) 35 | { 36 | int i,j; 37 | s_reg = 0x4A80;// prime value 38 | uint8_t *p = &dvbs_s_table[0]; 39 | 40 | for( i = 0; i < DVBS_T_SCRAM_SEQ_LENGTH; i++ ) 41 | { 42 | p[i]=0; 43 | for( j = 0; j < 8; j++ ) 44 | { 45 | p[i]<<=1; 46 | p[i] |= dvb_scramble_bit(); 47 | } 48 | } 49 | //print_scramble_table(); 50 | } 51 | // 52 | // Called many times 53 | // In place operation,starts at byte after the sync byte 54 | // 55 | void dvb_scramble_transport_packet( uint8_t *in, uint8_t *out ) 56 | { 57 | int i; 58 | 59 | for( i = 1; i <= DVBS_T_PAYLOAD_LEN; i++ ) 60 | { 61 | out[i] = in[i]^dvbs_s_table[m_sc++]; 62 | } 63 | // The scramber carries on but the SYNC byte is not 64 | // scrambled so we need to increment the pointer by one 65 | m_sc++; 66 | } 67 | void dvb_encode_init( int FEC ) 68 | { 69 | dvb_interleave_init(); 70 | dvb_rs_init(); 71 | 72 | dvb_scrambler_init(); 73 | dvb_conv_init(FEC); 74 | m_fc = 0; 75 | m_sc = 0; 76 | } 77 | void dvb_reset_scrambler(void) 78 | { 79 | m_sc = 0; 80 | } 81 | 82 | // 83 | // Input the transport packets 84 | // Output the baeband modulated samples 85 | // 86 | // tp = transport packet 87 | // 88 | int dvb_encode_frame( uint8_t *tp, uint8_t *dibit ) 89 | { 90 | int len; 91 | uint8_t pkt[DVBS_RS_BLOCK]; 92 | 93 | if( m_fc == 0 ) 94 | { 95 | // Add the inverted sync byte and do the first frame 96 | // Transport multiplex adaption 97 | pkt[0] = DVBS_T_ISYNC; 98 | // Reset the scrambler 99 | dvb_reset_scrambler(); 100 | } 101 | else 102 | { 103 | pkt[0] = MP_T_SYNC; 104 | } 105 | m_fc = (m_fc+1)%DVBS_T_FRAMES_IN_BLOCK; 106 | 107 | // Apply the scrambler 108 | dvb_scramble_transport_packet( tp, pkt ); 109 | 110 | // Reed Solomon Encode the whole frame 111 | dvb_rs_encode( pkt ); 112 | 113 | 114 | // Apply the Interleaver 115 | dvb_convolutional_interleave( pkt ); 116 | 117 | // Apply the convolutional encoder and produce the dibit array 118 | len = dvb_conv_encode_frame( pkt, dibit, DVBS_T_CODED_FRAME_LEN ); 119 | 120 | return len; 121 | } 122 | 123 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvbs_modulator.old: -------------------------------------------------------------------------------- 1 | #include 2 | #include "memory.h" 3 | #include "../dvb.h" 4 | 5 | // DVB-S encoding table 6 | 7 | #define SMAG (0x7FFF) 8 | 9 | scmplx tx_lookup[4] = { 10 | { SMAG, SMAG}, 11 | { -SMAG, SMAG}, 12 | { SMAG, -SMAG}, 13 | { -SMAG, -SMAG} 14 | }; 15 | static scmplx m_sams[20000]; 16 | static int m_tx_hardware; 17 | 18 | // 19 | // It all starts here 20 | // 21 | void dvbs_modulate_init( void ) 22 | { 23 | } 24 | // 25 | // Input transport packet 26 | // 27 | // tp -> dibit -> samples -> queue 28 | // 29 | void dvb_s_encode_and_modulate( uint8_t *tp, uint8_t *dibit ) 30 | { 31 | // Samples passed to Express 32 | 33 | int len = dvb_encode_frame( tp, dibit ); 34 | 35 | for( int i = 0; i < len; i++ ) 36 | { 37 | m_sams[i].re = tx_lookup[dibit[i]].re | 0x0001;// Mark I channel, LSB is always '1'; 38 | m_sams[i].im = tx_lookup[dibit[i]].im & 0xFFFE;// Mark Q channel, LSB is always '0'; 39 | } 40 | write_final_tx_queue( m_sams, len ); 41 | } 42 | // 43 | // Input IQ samples float, 44 | // length is the number of complex samples 45 | // Output complex samples short 46 | // 47 | void dvbt_clip( fft_complex *in, int length ) 48 | { 49 | for( int i = 0; i < length; i++) 50 | { 51 | 52 | if(fabs(in[i].re)>0.707) 53 | { 54 | if(in[i].re > 0 ) 55 | in[i].re = 0.707; 56 | else 57 | in[i].re = -0.707; 58 | } 59 | if(fabs(in[i].im) > 0.707) 60 | { 61 | if(in[i].im > 0 ) 62 | in[i].im = 0.707; 63 | else 64 | in[i].im = -0.707; 65 | } 66 | } 67 | } 68 | 69 | void dvbt_modulate( fft_complex *in, double *taper, int length ) 70 | { 71 | // Convert to 16 bit fixed point and apply clipping where required 72 | 73 | for( int i = 0; i < length; i++) 74 | { 75 | m_sams[i].re = (short)(in[i].re*taper[i]*0x7FFF) | 0x0001;// Mark I channel, LSB is always '1' 76 | m_sams[i].im = (short)(in[i].im*taper[i]*0x7FFF) & 0xFFFE;// Mark Q channel, LSB is always '0' 77 | } 78 | // We should now queue the symbols 79 | write_final_tx_queue( m_sams, length); 80 | } 81 | void dvbt_modulate( fft_complex *in, int length ) 82 | { 83 | // Convert to 16 bit fixed point and apply clipping where required 84 | 85 | for( int i = 0; i < length; i++) 86 | { 87 | m_sams[i].re = (short)(in[i].re*0x7FFF) | 0x0001;// Mark I channel, LSB is always '1' 88 | m_sams[i].im = (short)(in[i].im*0x7FFF) & 0xFFFE;// Mark Q channel, LSB is always '0' 89 | } 90 | // We should now queue the symbols 91 | write_final_tx_queue( m_sams, length); 92 | } 93 | void dvbs2_modulate( scmplx *in, int length ) 94 | { 95 | // We should now queue the symbols 96 | write_final_tx_queue( in, length ); 97 | } 98 | void dvb_modulate_init(void) 99 | { 100 | sys_config info; 101 | dvb_config_get( &info ); 102 | m_tx_hardware = info.tx_hardware; 103 | } 104 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S/dvbs_receive.cpp: -------------------------------------------------------------------------------- 1 | void dvbs_receive( short int *, int ) 2 | { 3 | // To be filled in if I ever decide to do a receive decoder 4 | } 5 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/DVB2.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "DVB2.h" 3 | #include "../dvb.h" 4 | 5 | // 6 | // Update working parameters for the next frame 7 | // This prevents parameters changing during a frame 8 | // 9 | void DVB2::base_end_of_frame_actions(void) 10 | { 11 | if( m_params_changed ) 12 | { 13 | m_format[0] = m_format[1]; 14 | ldpc_lookup_generate(); 15 | m_params_changed = 0; 16 | } 17 | // reset the pointer 18 | m_frame_offset_bits = 0; 19 | } 20 | 21 | // 22 | // This configures the system and calculates 23 | // any required intermediate values 24 | // 25 | int DVB2::set_configure( DVB2FrameFormat *f ) 26 | { 27 | int bch_bits = 0; 28 | int error = 0; 29 | 30 | if( f->broadcasting ) 31 | { 32 | // Set standard parametrs for broadcasting 33 | //f->frame_type = FRAME_NORMAL; 34 | f->bb_header.ts_gs = TS_GS_TRANSPORT; 35 | f->bb_header.sis_mis = SIS_MIS_SINGLE; 36 | f->bb_header.ccm_acm = CCM; 37 | f->bb_header.issyi = 0; 38 | f->bb_header.npd = 0; 39 | f->bb_header.upl = 188*8; 40 | f->bb_header.sync = 0x47; 41 | } 42 | f->bb_header.ro = f->roll_off; 43 | // Fill in the mode specific values and bit lengths 44 | if( f->frame_type == FRAME_NORMAL ) 45 | { 46 | f->nldpc = 64800; 47 | bch_bits = 192; 48 | f->bch_code = BCH_CODE_N12; 49 | // Apply code rate 50 | switch(f->code_rate ) 51 | { 52 | case CR_1_4: 53 | f->q_val = 135; 54 | f->kbch = 16008; 55 | f->bch_code = BCH_CODE_N12; 56 | break; 57 | case CR_1_3: 58 | f->q_val = 120; 59 | f->kbch = 21408; 60 | f->bch_code = BCH_CODE_N12; 61 | break; 62 | case CR_2_5: 63 | f->q_val = 108; 64 | f->kbch = 25728; 65 | f->bch_code = BCH_CODE_N12; 66 | break; 67 | case CR_1_2: 68 | f->q_val = 90; 69 | f->kbch = 32208; 70 | f->bch_code = BCH_CODE_N12; 71 | break; 72 | case CR_3_5: 73 | f->q_val = 72; 74 | f->kbch = 38688; 75 | f->bch_code = BCH_CODE_N12; 76 | break; 77 | case CR_2_3: 78 | bch_bits = 160; 79 | f->q_val = 60; 80 | f->kbch = 43040; 81 | f->bch_code = BCH_CODE_N10; 82 | break; 83 | case CR_3_4: 84 | f->q_val = 45; 85 | f->kbch = 48408; 86 | f->bch_code = BCH_CODE_N12; 87 | break; 88 | case CR_4_5: 89 | f->q_val = 36; 90 | f->kbch = 51648; 91 | f->bch_code = BCH_CODE_N12; 92 | break; 93 | case CR_5_6: 94 | bch_bits = 160; 95 | f->q_val = 30; 96 | f->kbch = 53840; 97 | f->bch_code = BCH_CODE_N10; 98 | break; 99 | case CR_8_9: 100 | bch_bits = 128; 101 | f->q_val = 20; 102 | f->kbch = 57472; 103 | f->bch_code = BCH_CODE_N8; 104 | break; 105 | case CR_9_10: 106 | bch_bits = 128; 107 | f->q_val = 18; 108 | f->kbch = 58192; 109 | f->bch_code = BCH_CODE_N8; 110 | break; 111 | default : 112 | ////loggerf("Configuration error DVB2\n"); 113 | error = -1; 114 | 115 | } 116 | } 117 | 118 | if( f->frame_type == FRAME_SHORT ) 119 | { 120 | f->nldpc = 16200; 121 | bch_bits = 168; 122 | f->bch_code = BCH_CODE_S12; 123 | // Apply code rate 124 | switch(f->code_rate ) 125 | { 126 | case CR_1_4: 127 | f->q_val = 36; 128 | f->kbch = 3072; 129 | break; 130 | case CR_1_3: 131 | f->q_val = 30; 132 | f->kbch = 5232; 133 | break; 134 | case CR_2_5: 135 | f->q_val = 27; 136 | f->kbch = 6312; 137 | break; 138 | case CR_1_2: 139 | f->q_val = 25; 140 | f->kbch = 7032; 141 | break; 142 | case CR_3_5: 143 | f->q_val = 18; 144 | f->kbch = 9552; 145 | break; 146 | case CR_2_3: 147 | f->q_val = 15; 148 | f->kbch = 10632; 149 | break; 150 | case CR_3_4: 151 | f->q_val = 12; 152 | f->kbch = 11712; 153 | break; 154 | case CR_4_5: 155 | f->q_val = 10; 156 | f->kbch = 12432; 157 | break; 158 | case CR_5_6: 159 | f->q_val = 8; 160 | f->kbch = 13152; 161 | break; 162 | case CR_8_9: 163 | f->q_val = 5; 164 | f->kbch = 14232; 165 | break; 166 | case CR_9_10: 167 | error = 1; 168 | f->kbch = 0; 169 | break; 170 | default: 171 | //loggerf("Configuration error DVB2\n"); 172 | error = -1; 173 | break; 174 | } 175 | } 176 | if( error == 0 ) 177 | { 178 | // Length of the user packets 179 | f->bb_header.upl = 188*8; 180 | // Payload length 181 | f->bb_header.dfl = f->kbch - 80; 182 | // Transport packet sync 183 | f->bb_header.sync = 0x47; 184 | // Start of LDPC bits 185 | f->kldpc = f->kbch + bch_bits; 186 | // Number of padding bits required (not used) 187 | f->padding_bits = 0; 188 | // Number of useable data bits (not used) 189 | f->useable_data_bits = f->kbch - 80; 190 | // Save the configuration, will be updated on next frame 191 | m_format[1] = *f; 192 | // reset various pointers 193 | m_dnp = 0;// No deleted null packets 194 | // Signal we need to update on the next frame. 195 | if( m_params_changed ) 196 | base_end_of_frame_actions(); 197 | else 198 | m_params_changed = 1; 199 | } 200 | return error; 201 | } 202 | void DVB2::get_configure( DVB2FrameFormat *f ) 203 | { 204 | *f = m_format[1]; 205 | } 206 | 207 | // Points to first byte in transport packet 208 | 209 | int DVB2::add_ts_frame_base( u8 *ts ) 210 | { 211 | if( m_frame_offset_bits == 0 ) 212 | { 213 | // New frame needs to be sent 214 | add_bbheader(); // Add the header 215 | } 216 | // Add a new transport packet 217 | unpack_transport_packet_add_crc( ts ); 218 | // Have we reached the end? 219 | if( m_frame_offset_bits == m_format[0].kbch ) 220 | { 221 | // Yes so now Scramble the BB frame 222 | bb_randomise(); 223 | // BCH encode the BB Frame 224 | bch_encode(); 225 | // LDPC encode the BB frame and BCHFEC bits 226 | ldpc_encode(); 227 | // Signal to the modulation specific class we have something to send 228 | base_end_of_frame_actions(); 229 | return 1; 230 | } 231 | return 0; 232 | } 233 | // 234 | // Dump NULL packets appends a counter to the end of each UP 235 | // it is not implemented at the moment. 236 | // 237 | int DVB2::next_ts_frame_base( u8 *ts ) 238 | { 239 | int res = 0; 240 | // See if we need to dump null packets 241 | if( m_format[0].null_deletion == 1 ) 242 | { 243 | if(((ts[0]&0x1F) == 0x1F)&&(ts[1] == 0xFF )) 244 | { 245 | // Null packet detected 246 | if( m_dnp < 0xFF ) 247 | { 248 | m_dnp++;// Increment the number of null packets 249 | return 0; 250 | } 251 | } 252 | } 253 | // Need to send a new transport packet 254 | res = add_ts_frame_base( ts ); 255 | if( res ) m_dnp = 0;// Clear the DNP counter 256 | // return whether it is time to transmit a new frame 257 | return res; 258 | } 259 | DVB2::DVB2(void) 260 | { 261 | // Clear the transport queue 262 | m_tp_q.empty(); 263 | init_bb_randomiser(); 264 | bch_poly_build_tables(); 265 | build_crc8_table(); 266 | m_dnp = 0;// No delted null packets 267 | m_frame_offset_bits = 0; 268 | m_params_changed = 1; 269 | } 270 | DVB2::~DVB2(void) 271 | { 272 | } 273 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/DVB2.h: -------------------------------------------------------------------------------- 1 | #ifndef DVB2_H 2 | #define DVB2_H 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "../dvb_types.h" 8 | 9 | using namespace std; 10 | 11 | typedef unsigned int u32; 12 | typedef unsigned char u8; 13 | 14 | // BB HEADER fileds 15 | #define TS_GS_TRANSPORT 3 16 | #define TS_GS_GENERIC_PACKETIZED 0 17 | #define TS_GS_GENERIC_CONTINUOUS 1 18 | #define TS_GS_RESERVED 2 19 | 20 | #define SIS_MIS_SINGLE 1 21 | #define SIS_MIS_MULTIPLE 0 22 | 23 | #define CCM 1 24 | #define ACM 0 25 | 26 | #define ISSYI_ACTIVE 1 27 | #define ISSYI_NOT_ACTIVE 0 28 | 29 | #define NPD_ACTIVE 1 30 | #define NPD_NOT_ACTIVE 0 31 | // Rolloff 32 | #define RO_0_35 0 33 | #define RO_0_25 1 34 | #define RO_0_20 2 35 | #define RO_RESERVED 3 36 | 37 | typedef struct{ 38 | int ts_gs; 39 | int sis_mis; 40 | int ccm_acm; 41 | int issyi; 42 | int npd; 43 | int ro; 44 | int isi; 45 | int upl; 46 | int dfl; 47 | int sync; 48 | int syncd; 49 | }BBHeader; 50 | 51 | typedef int Bit; 52 | 53 | // The number of useable and stuff bits in a frame 54 | typedef struct{ 55 | int data_bits; 56 | int stuff_bits; 57 | }FrameBits; 58 | 59 | //4 for Upsample 60 | #define FRAME_SIZE_NORMAL (64800) 61 | #define FRAME_SIZE_SHORT (16200) 62 | #define LDPC_ENCODE_TABLE_LENGTH (FRAME_SIZE_NORMAL*10) 63 | 64 | typedef struct{ 65 | int table_length; 66 | Bit d[LDPC_ENCODE_TABLE_LENGTH]; 67 | Bit p[LDPC_ENCODE_TABLE_LENGTH]; 68 | }Ldpc_encode_table; 69 | 70 | #define FRAME_NORMAL 0x00 71 | #define FRAME_SHORT 0x10 72 | #define BB_HEADER_LENGTH_BITS 72 73 | #define CRC8_LENGTH_BITS 8 74 | 75 | #define PADDING_LENGTH 200 76 | 77 | // Code rates 78 | #define CR_1_4 0 79 | #define CR_1_3 1 80 | #define CR_2_5 2 81 | #define CR_1_2 3 82 | #define CR_3_5 4 83 | #define CR_2_3 5 84 | #define CR_3_4 6 85 | #define CR_4_5 7 86 | #define CR_5_6 8 87 | #define CR_8_9 9 88 | #define CR_7_8 10 89 | #define CR_9_10 11 90 | // BCH Code 91 | #define BCH_CODE_N8 0 92 | #define BCH_CODE_N10 1 93 | #define BCH_CODE_N12 2 94 | #define BCH_CODE_S12 3 95 | // Constellation 96 | #define M_QPSK 0 97 | #define M_8PSK 1 98 | #define M_16APSK 2 99 | #define M_32APSK 3 100 | //Interface 101 | #define M_ACM 0 102 | #define M_CCM 1 103 | #define M_VCM 2 104 | 105 | 106 | typedef struct{ 107 | int frame_type; 108 | int code_rate; 109 | int roll_off; 110 | int constellation; 111 | int pilots; 112 | int dummy_frame; 113 | int null_deletion; 114 | int interface; 115 | int broadcasting; 116 | // Calculated information, not used by caller 117 | BBHeader bb_header; 118 | int kldpc; 119 | int kbch; 120 | int nldpc; 121 | int q_val; 122 | int bch_code; 123 | int useable_data_bits; 124 | int padding_bits; 125 | int total_bits; 126 | int nr_tps; 127 | int nr_tps_bits; 128 | }DVB2FrameFormat; 129 | 130 | 131 | class DVB2{ 132 | 133 | public: 134 | 135 | protected: 136 | Bit m_frame[FRAME_SIZE_NORMAL]; 137 | DVB2FrameFormat m_format[2]; 138 | Bit m_padding[PADDING_LENGTH]; 139 | int m_frame_offset_bits; 140 | int m_params_changed; 141 | 142 | private: 143 | int m_bbheader[BB_HEADER_LENGTH_BITS+CRC8_LENGTH_BITS]; 144 | int m_bb_randomise[FRAME_SIZE_NORMAL]; 145 | u32 m_poly_n_8[4]; 146 | u32 m_poly_n_10[5]; 147 | u32 m_poly_n_12[6]; 148 | u32 m_poly_s_12[6]; 149 | u8 m_crc_tab[256]; 150 | u8 m_dnp; // Deleted null packet 151 | // Transport packet queue 152 | queue m_tp_q; 153 | 154 | // LDPC tables 155 | const static int ldpc_tab_1_4N[45][13]; 156 | const static int ldpc_tab_1_3N[60][13]; 157 | const static int ldpc_tab_2_5N[72][13]; 158 | const static int ldpc_tab_1_2N[90][9]; 159 | const static int ldpc_tab_3_5N[108][13]; 160 | const static int ldpc_tab_2_3N[120][14]; 161 | const static int ldpc_tab_3_4N[135][13]; 162 | const static int ldpc_tab_4_5N[144][12]; 163 | const static int ldpc_tab_5_6N[150][14]; 164 | const static int ldpc_tab_8_9N[160][5]; 165 | const static int ldpc_tab_9_10N[162][5]; 166 | const static int ldpc_tab_1_4S[9][13]; 167 | const static int ldpc_tab_1_3S[15][13]; 168 | const static int ldpc_tab_2_5S[18][13]; 169 | const static int ldpc_tab_1_2S[20][9]; 170 | const static int ldpc_tab_3_5S[27][13]; 171 | const static int ldpc_tab_2_3S[30][14]; 172 | const static int ldpc_tab_3_4S[33][13]; 173 | const static int ldpc_tab_4_5S[35][4]; 174 | const static int ldpc_tab_5_6S[37][14]; 175 | const static int ldpc_tab_8_9S[40][5]; 176 | 177 | 178 | Ldpc_encode_table m_ldpc_encode; 179 | void bb_randomise(void); 180 | void init_scrambler(void); 181 | void init_bb_randomiser(void); 182 | void ldpc_lookup_generate(void); 183 | void ldpc_encode( void ); 184 | int add_transport_packet( u8 *pkt, Bit *b ); 185 | void build_crc8_table( void ); 186 | u8 calc_crc8( u8 *b, int len ); 187 | int add_crc8_bits( Bit *in, int length ); 188 | void unpack_transport_packet_add_crc( u8 *ts ); 189 | void add_bbheader( void ); 190 | void poly_reverse( int *pin, int *pout, int len ); 191 | void poly_pack( const int *pin, u32* pout, int len ); 192 | int poly_mult( const int *ina, int lena, const int *inb, int lenb, int *out ); 193 | void bch_poly_build_tables( void ); 194 | void reg_4_shift( u32 *sr ); 195 | void reg_5_shift( u32 *sr ); 196 | void reg_6_shift( u32 *sr ); 197 | Bit bch_n_8_encode( Bit *in, int len ); 198 | Bit bch_n_10_encode( Bit *in, int len ); 199 | Bit bch_n_12_encode( Bit *in, int len ); 200 | Bit bch_s_12_encode( Bit *in, int len ); 201 | int bch_encode( void ); 202 | int add_ts_frame_base( u8 *ts ); 203 | void ldpc_encode_test(); 204 | void base_end_of_frame_actions(void); 205 | protected: 206 | int set_configure( DVB2FrameFormat *f ); 207 | void get_configure( DVB2FrameFormat *f ); 208 | int next_ts_frame_base( u8 *ts ); 209 | public: 210 | // encode a new transport packet 211 | // virtual void physical(void); 212 | DVB2(); 213 | ~DVB2(); 214 | }; 215 | 216 | #endif 217 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/DVBS2.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "DVBS2.h" 3 | 4 | // 5 | // called at the end of a frame 6 | // 7 | void DVBS2::end_of_frame_actions(void) 8 | { 9 | if( m_s2_config_updated ) 10 | { 11 | modulator_configuration(); 12 | m_s2_config_updated = 0; 13 | } 14 | } 15 | 16 | int DVBS2::is_valid( int mod, int coderate ) 17 | { 18 | if( mod == M_QPSK ) 19 | { 20 | if(coderate == CR_1_4) return 0; 21 | if(coderate == CR_1_3) return 0; 22 | if(coderate == CR_2_5) return 0; 23 | if(coderate == CR_1_2) return 0; 24 | if(coderate == CR_3_5) return 0; 25 | if(coderate == CR_2_3) return 0; 26 | if(coderate == CR_3_4) return 0; 27 | if(coderate == CR_4_5) return 0; 28 | if(coderate == CR_5_6) return 0; 29 | if(coderate == CR_8_9) return 0; 30 | if(coderate == CR_9_10) return 0; 31 | } 32 | if( mod == M_8PSK ) 33 | { 34 | if(coderate == CR_3_5) return 0; 35 | if(coderate == CR_2_3) return 0; 36 | if(coderate == CR_3_4) return 0; 37 | if(coderate == CR_5_6) return 0; 38 | if(coderate == CR_8_9) return 0; 39 | if(coderate == CR_9_10) return 0; 40 | } 41 | if( mod == M_16APSK ) 42 | { 43 | if(coderate == CR_2_3) return 0; 44 | if(coderate == CR_3_4) return 0; 45 | if(coderate == CR_4_5) return 0; 46 | if(coderate == CR_5_6) return 0; 47 | if(coderate == CR_8_9) return 0; 48 | if(coderate == CR_9_10) return 0; 49 | } 50 | if( mod == M_32APSK ) 51 | { 52 | if(coderate == CR_3_4) return 0; 53 | if(coderate == CR_4_5) return 0; 54 | if(coderate == CR_5_6) return 0; 55 | if(coderate == CR_8_9) return 0; 56 | if(coderate == CR_9_10) return 0; 57 | } 58 | return -1; 59 | } 60 | // 61 | // index 0 and 1 will only be different when being reconfigured. 62 | // Use index 1 as this will be applied in the following transmit 63 | // frames 64 | // 65 | void DVBS2::calc_efficiency( void ) 66 | { 67 | double p,m,a,s,b,po; 68 | // Calculate the number of symbols in the payload 69 | p = 0;a = 0; m = 0; 70 | if( m_format[1].frame_type == FRAME_NORMAL ) p = (double)FRAME_SIZE_NORMAL; 71 | if( m_format[1].frame_type == FRAME_SHORT ) p = (double)FRAME_SIZE_SHORT; 72 | if( m_format[1].constellation == M_QPSK ) m = 2.0; 73 | if( m_format[1].constellation == M_8PSK ) m = 3.0; 74 | if( m_format[1].constellation == M_16APSK ) m = 4.0; 75 | if( m_format[1].constellation == M_32APSK ) m = 5.0; 76 | s = p/m;//Number of symbols per frame 77 | // PL header overhead 78 | if( m_format[1].pilots ) 79 | { 80 | //po = (s/(90*16))-1;// 1 pilot every 16 blocks (of 90 symbols) 81 | po = (int)((s/90.0-1.0)/16.0);// 1 pilot every 16 blocks (of 90 symbols) 82 | po = po*36; // No pilot at the end 83 | a = s/(90+po+s); 84 | 85 | //a=(s)/(90*(s+1)+36*(int)((s-1)/16.0)); 86 | 87 | } 88 | else 89 | { 90 | 91 | a = s/(90+s);// No pilots 92 | } 93 | // Modulation efficiency 94 | a = a*m; 95 | // Take into account pilot symbols 96 | // TBD 97 | // Now calculate the useable data as percentage of the frame 98 | b = ((double)m_format[1].useable_data_bits)/p; 99 | // Now calculate the efficiency by multiplying the 100 | // useable bits efficiency by the modulation efficiency 101 | m_efficiency = b*a; 102 | } 103 | // 104 | // Multiply the efficiency value by the symbol rate 105 | // to get the useable bitrate 106 | // 107 | double DVBS2::s2_get_efficiency( void ) 108 | { 109 | return m_efficiency; 110 | } 111 | 112 | int DVBS2::s2_set_configure( DVB2FrameFormat *f ) 113 | { 114 | if( is_valid( f->constellation, f->code_rate ) == 0 ) 115 | { 116 | if( set_configure( f ) == 0 ) 117 | { 118 | calc_efficiency(); 119 | m_s2_config_updated = 1; 120 | return 0; 121 | } 122 | } 123 | return -1; 124 | } 125 | void DVBS2::s2_get_configure( DVB2FrameFormat *f ) 126 | { 127 | get_configure( f ); 128 | } 129 | int DVBS2::s2_add_ts_frame( u8 *ts ) 130 | { 131 | int res = 0; 132 | // Call base class 133 | if( next_ts_frame_base( ts ) ) 134 | { 135 | // Interleave and pack 136 | s2_interleave(); 137 | // create the header 138 | s2_pl_header_create(); 139 | // Add the data 140 | res = s2_pl_data_pack(); 141 | // Do any updates required for the next frame 142 | end_of_frame_actions(); 143 | } 144 | return res; 145 | } 146 | void DVBS2::physical( void ) 147 | { 148 | 149 | } 150 | 151 | DVBS2::DVBS2() 152 | { 153 | modulator_configuration(); 154 | build_symbol_scrambler_table(); 155 | pl_build_dummy(); 156 | } 157 | 158 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/DVBS2.h: -------------------------------------------------------------------------------- 1 | #include "DVB2.h" 2 | #ifndef DVBS2_H 3 | #define DVBS2_H 4 | 5 | #ifndef M_PI 6 | #define M_PI 3.14159f 7 | #endif 8 | 9 | class DVBS2 : public DVB2{ 10 | public: 11 | scmplx m_bpsk[2][2]; 12 | scmplx m_qpsk[4]; 13 | scmplx m_8psk[8]; 14 | scmplx m_16apsk[16]; 15 | scmplx m_32apsk[32]; 16 | private: 17 | const static unsigned long g[6]; 18 | const static int ph_scram_tab[64]; 19 | const static int ph_sync_seq[26]; 20 | 21 | 22 | scmplx m_pl[FRAME_SIZE_NORMAL]; 23 | scmplx m_pl_dummy[FRAME_SIZE_NORMAL]; 24 | int m_cscram[FRAME_SIZE_NORMAL]; 25 | int m_iframe[FRAME_SIZE_NORMAL]; 26 | int m_payload_symbols; 27 | int m_dummy_frame_length; 28 | double m_efficiency; 29 | int m_s2_config_updated; 30 | void b_64_7_code( unsigned char in, int *out ); 31 | void s2_pl_header_encode( u8 modcod, u8 type, int *out); 32 | void modulator_configuration(void); 33 | void s2_interleave( void ); 34 | void s2_pl_header_create(void); 35 | int s2_pl_data_pack( void ); 36 | void pl_scramble_symbols( scmplx *fs, int len ); 37 | void pl_scramble_dummy_symbols( int len ); 38 | void pl_build_dummy( void ); 39 | int parity_chk( long a, long b); 40 | void build_symbol_scrambler_table( void ); 41 | int is_valid( int mod, int coderate ); 42 | void calc_efficiency( void ); 43 | void end_of_frame_actions(void); 44 | public: 45 | double s2_get_efficiency( void ); 46 | void physical(void); 47 | int s2_set_configure( DVB2FrameFormat *f ); 48 | void s2_get_configure( DVB2FrameFormat *f ); 49 | scmplx *pl_get_frame(void); 50 | scmplx *pl_get_dummy( int &len ); 51 | int s2_add_ts_frame( u8 *ts ); 52 | DVBS2(); 53 | }; 54 | 55 | #endif 56 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvb2_bbheader.cpp: -------------------------------------------------------------------------------- 1 | #include "DVB2.h" 2 | #include "memory.h" 3 | // 4 | // This file adds the BB header and new transport packets 5 | // 6 | #define CRC_POLY 0xAB 7 | // Reversed 8 | #define CRC_POLYR 0xD5 9 | 10 | void DVB2::build_crc8_table( void ) 11 | { 12 | int r,crc; 13 | 14 | for( int i = 0; i < 256; i++ ) 15 | { 16 | r = i; 17 | crc = 0; 18 | for( int j = 7; j >= 0; j-- ) 19 | { 20 | if((r&(1<>= 1; 56 | if( b ) crc ^= CRC_POLY; 57 | } 58 | 59 | for( int n = 0; n < 8; n++ ) 60 | { 61 | in[i++] = (crc&(1<ts_gs>>1; 75 | m_frame[1] = h->ts_gs&1; 76 | m_frame[2] = h->sis_mis; 77 | m_frame[3] = h->ccm_acm; 78 | m_frame[4] = h->issyi&1; 79 | m_frame[5] = h->npd&1; 80 | m_frame[6] = h->ro>>1; 81 | m_frame[7] = h->ro&1; 82 | m_frame_offset_bits = 8; 83 | if( h->sis_mis == SIS_MIS_MULTIPLE ) 84 | { 85 | temp = h->isi; 86 | for( int n = 7; n >= 0; n-- ) 87 | { 88 | m_frame[m_frame_offset_bits++] = temp&(1<= 0 ; n-- ) 94 | { 95 | m_frame[m_frame_offset_bits++] = 0; 96 | } 97 | } 98 | temp = h->upl; 99 | for( int n = 15; n >= 0; n-- ) 100 | { 101 | m_frame[m_frame_offset_bits++] = temp&(1<dfl; 104 | for( int n = 15; n >= 0; n-- ) 105 | { 106 | m_frame[m_frame_offset_bits++] = temp&(1<sync; 109 | for( int n = 7; n >= 0; n-- ) 110 | { 111 | m_frame[m_frame_offset_bits++] = temp&(1<syncd;// Syncd 120 | for( int n = 15; n >= 0; n-- ) 121 | { 122 | m_frame[m_frame_offset_bits++] = temp&(1<= 0; n-- ) 145 | { 146 | m_frame[m_frame_offset_bits++] = b&(1<>24); 48 | break; 49 | case 2: 50 | //loggerf("%.2X",in[(len/32)]>>24); 51 | //loggerf("%.2X",in[(len/32)]>>16); 52 | break; 53 | case 3: 54 | //loggerf("%.2X",in[(len/32)]>>24); 55 | //loggerf("%.2X",in[(len/32)]>>16); 56 | //loggerf("%.2X",in[(len/32)]>>8); 57 | break; 58 | } 59 | //loggerf("\n"); 60 | } 61 | 62 | // 63 | // Polynomial calculation routines 64 | // 65 | // multiply polynomials 66 | // 67 | int DVB2::poly_mult( const int *ina, int lena, const int *inb, int lenb, int *out ) 68 | { 69 | memset( out, 0, sizeof(int)*(lena+lenb)); 70 | 71 | for( int i = 0; i < lena; i++ ) 72 | { 73 | for( int j = 0; j < lenb; j++ ) 74 | { 75 | if( ina[i]*inb[j] > 0 ) out[i+j]++;// count number of terms for this pwr of x 76 | } 77 | } 78 | int max=0; 79 | for( int i = 0; i < lena+lenb; i++ ) 80 | { 81 | out[i] = out[i]&1;// If even ignore the term 82 | if(out[i]) max = i; 83 | } 84 | // return the size of array to house the result. 85 | return max+1; 86 | 87 | } 88 | // 89 | // Pack the polynomial into a 32 bit array 90 | // 91 | 92 | void DVB2::poly_pack( const int *pin, u32* pout, int len ) 93 | { 94 | int lw = len/32; 95 | int ptr = 0; 96 | u32 temp; 97 | if( len % 32 ) lw++; 98 | 99 | for( int i = 0; i < lw; i++ ) 100 | { 101 | temp = 0x80000000; 102 | pout[i] = 0; 103 | for( int j = 0; j < 32; j++ ) 104 | { 105 | if( pin[ptr++] ) pout[i] |= temp; 106 | temp >>= 1; 107 | } 108 | } 109 | } 110 | 111 | void DVB2::poly_reverse( int *pin, int *pout, int len ) 112 | { 113 | int c; 114 | c = len-1; 115 | 116 | for( int i = 0; i < len; i++ ) 117 | { 118 | pout[c--] = pin[i]; 119 | } 120 | } 121 | // 122 | // Shift a 128 bit register 123 | // 124 | void inline DVB2::reg_4_shift( u32 *sr ) 125 | { 126 | sr[3] = (sr[3]>>1) | (sr[2]<<31); 127 | sr[2] = (sr[2]>>1) | (sr[1]<<31); 128 | sr[1] = (sr[1]>>1) | (sr[0]<<31); 129 | sr[0] = (sr[0]>>1); 130 | } 131 | // 132 | // Shift 160 bits 133 | // 134 | void inline DVB2::reg_5_shift( u32 *sr ) 135 | { 136 | sr[4] = (sr[4]>>1) | (sr[3]<<31); 137 | sr[3] = (sr[3]>>1) | (sr[2]<<31); 138 | sr[2] = (sr[2]>>1) | (sr[1]<<31); 139 | sr[1] = (sr[1]>>1) | (sr[0]<<31); 140 | sr[0] = (sr[0]>>1); 141 | } 142 | // 143 | // Shift 192 bits 144 | // 145 | void inline DVB2::reg_6_shift( u32 *sr ) 146 | { 147 | sr[5] = (sr[5]>>1) | (sr[4]<<31); 148 | sr[4] = (sr[4]>>1) | (sr[3]<<31); 149 | sr[3] = (sr[3]>>1) | (sr[2]<<31); 150 | sr[2] = (sr[2]>>1) | (sr[1]<<31); 151 | sr[1] = (sr[1]>>1) | (sr[0]<<31); 152 | sr[0] = (sr[0]>>1); 153 | } 154 | 155 | // 156 | // Take an bit array, bch encode it and place the result in a bit array 157 | // The input length is in bits. 158 | // 159 | Bit DVB2::bch_n_8_encode( Bit *in, int len ) 160 | { 161 | Bit b; 162 | int i; 163 | u32 shift[4]; 164 | 165 | //Zero the shift register 166 | memset( shift,0,sizeof(u32)*4); 167 | 168 | for( i = 0; i < len; i++ ) 169 | { 170 | b = in[i]^(shift[3]&1); 171 | reg_4_shift( shift ); 172 | if( b ) 173 | { 174 | shift[0] ^= m_poly_n_8[0]; 175 | shift[1] ^= m_poly_n_8[1]; 176 | shift[2] ^= m_poly_n_8[2]; 177 | shift[3] ^= m_poly_n_8[3]; 178 | } 179 | } 180 | // Now add the parity bits to the output 181 | for( int n = 0; n < 128; n++ ) 182 | { 183 | in[i++] = shift[3]&1; 184 | reg_4_shift( shift ); 185 | } 186 | return i; 187 | } 188 | Bit DVB2::bch_n_10_encode( Bit *in,int len ) 189 | { 190 | Bit b; 191 | int i; 192 | u32 shift[5]; 193 | 194 | //Zero the shift register 195 | memset( shift,0,sizeof(u32)*5); 196 | 197 | for( i = 0; i < len; i++ ) 198 | { 199 | b = in[i]^(shift[4]&1); 200 | reg_5_shift( shift ); 201 | if(b) 202 | { 203 | shift[0] ^= m_poly_n_10[0]; 204 | shift[1] ^= m_poly_n_10[1]; 205 | shift[2] ^= m_poly_n_10[2]; 206 | shift[3] ^= m_poly_n_10[3]; 207 | shift[4] ^= m_poly_n_10[4]; 208 | } 209 | } 210 | // Now add the parity bits to the output 211 | for( int n = 0; n < 160; n++ ) 212 | { 213 | in[i++] = shift[4]&1; 214 | reg_5_shift( shift ); 215 | } 216 | return i; 217 | } 218 | 219 | Bit DVB2::bch_n_12_encode( Bit *in, int len ) 220 | { 221 | Bit b; 222 | int i; 223 | u32 shift[6]; 224 | //Zero the shift register 225 | memset( shift,0,sizeof(u32)*6); 226 | // MSB of the codeword first 227 | for( i = 0; i < len; i++ ) 228 | { 229 | b = in[i] ^ (shift[5]&1); 230 | reg_6_shift( shift ); 231 | if(b) 232 | { 233 | shift[0] ^= m_poly_n_12[0]; 234 | shift[1] ^= m_poly_n_12[1]; 235 | shift[2] ^= m_poly_n_12[2]; 236 | shift[3] ^= m_poly_n_12[3]; 237 | shift[4] ^= m_poly_n_12[4]; 238 | shift[5] ^= m_poly_n_12[5]; 239 | } 240 | } 241 | // Now add the parity bits to the output 242 | for( int n = 0; n < 192; n++ ) 243 | { 244 | in[i++] = shift[5]&1; 245 | reg_6_shift( shift ); 246 | } 247 | return i; 248 | } 249 | 250 | Bit DVB2::bch_s_12_encode( Bit *in, int len ) 251 | { 252 | Bit b; 253 | int i; 254 | u32 shift[6]; 255 | 256 | //Zero the shift register 257 | memset( shift,0,sizeof(u32)*6); 258 | 259 | for( i = 0; i < len; i++ ) 260 | { 261 | b = (in[i] ^ ((shift[5]&0x01000000)?1:0)); 262 | reg_6_shift( shift ); 263 | if(b) 264 | { 265 | shift[0] ^= m_poly_s_12[0]; 266 | shift[1] ^= m_poly_s_12[1]; 267 | shift[2] ^= m_poly_s_12[2]; 268 | shift[3] ^= m_poly_s_12[3]; 269 | shift[4] ^= m_poly_s_12[4]; 270 | shift[5] ^= m_poly_s_12[5]; 271 | } 272 | } 273 | // Now add the parity bits to the output 274 | for( int n = 0; n < 168; n++ ) 275 | { 276 | in[i++] = (shift[5]&0x01000000) ? 1:0; 277 | reg_6_shift( shift ); 278 | } 279 | return i; 280 | } 281 | 282 | 283 | int DVB2::bch_encode( void ) 284 | { 285 | int res; 286 | int len = m_format[0].kbch; 287 | 288 | switch(m_format[0].bch_code) 289 | { 290 | case BCH_CODE_N8: 291 | res = bch_n_8_encode( m_frame, len ); 292 | break; 293 | case BCH_CODE_N10: 294 | res = bch_n_10_encode( m_frame, len ); 295 | break; 296 | case BCH_CODE_N12: 297 | res = bch_n_12_encode( m_frame, len ); 298 | break; 299 | case BCH_CODE_S12: 300 | res = bch_s_12_encode( m_frame, len ); 301 | break; 302 | default: 303 | printf("BCH error situation\n"); 304 | res = 0; 305 | break; 306 | } 307 | return res; 308 | } 309 | 310 | // 311 | // 312 | // 313 | void DVB2::bch_poly_build_tables( void ) 314 | { 315 | // Normal polynomials 316 | const int polyn01[]={1,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,1}; 317 | const int polyn02[]={1,1,0,0,1,1,1,0,1,0,0,0,0,0,0,0,1}; 318 | const int polyn03[]={1,0,1,1,1,1,0,1,1,1,1,1,0,0,0,0,1}; 319 | const int polyn04[]={1,0,1,0,1,0,1,0,0,1,0,1,1,0,1,0,1}; 320 | const int polyn05[]={1,1,1,1,0,1,0,0,1,1,1,1,1,0,0,0,1}; 321 | const int polyn06[]={1,0,1,0,1,1,0,1,1,1,1,0,1,1,1,1,1}; 322 | const int polyn07[]={1,0,1,0,0,1,1,0,1,1,1,1,0,1,0,1,1}; 323 | const int polyn08[]={1,1,1,0,0,1,1,0,1,1,0,0,1,1,1,0,1}; 324 | const int polyn09[]={1,0,0,0,0,1,0,1,0,1,1,1,0,0,0,0,1}; 325 | const int polyn10[]={1,1,1,0,0,1,0,1,1,0,1,0,1,1,1,0,1}; 326 | const int polyn11[]={1,0,1,1,0,1,0,0,0,1,0,1,1,1,0,0,1}; 327 | const int polyn12[]={1,1,0,0,0,1,1,1,0,1,0,1,1,0,0,0,1}; 328 | 329 | // Short polynomials 330 | const int polys01[]={1,1,0,1,0,1,0,0,0,0,0,0,0,0,1}; 331 | const int polys02[]={1,0,0,0,0,0,1,0,1,0,0,1,0,0,1}; 332 | const int polys03[]={1,1,1,0,0,0,1,0,0,1,1,0,0,0,1}; 333 | const int polys04[]={1,0,0,0,1,0,0,1,1,0,1,0,1,0,1}; 334 | const int polys05[]={1,0,1,0,1,0,1,0,1,1,0,1,0,1,1}; 335 | const int polys06[]={1,0,0,1,0,0,0,1,1,1,0,0,0,1,1}; 336 | const int polys07[]={1,0,1,0,0,1,1,1,0,0,1,1,0,1,1}; 337 | const int polys08[]={1,0,0,0,0,1,0,0,1,1,1,1,0,0,1}; 338 | const int polys09[]={1,1,1,1,0,0,0,0,0,1,1,0,0,0,1}; 339 | const int polys10[]={1,0,0,1,0,0,1,0,0,1,0,1,1,0,1}; 340 | const int polys11[]={1,0,0,0,1,0,0,0,0,0,0,1,1,0,1}; 341 | const int polys12[]={1,1,1,1,0,1,1,1,1,0,1,0,0,1,1}; 342 | 343 | int len; 344 | int polyout[3][2000]; 345 | 346 | len = poly_mult( polyn01, 17, polyn02, 17, polyout[0] ); 347 | len = poly_mult( polyn03, 17, polyout[0], len, polyout[1] ); 348 | len = poly_mult( polyn04, 17, polyout[1], len, polyout[0] ); 349 | len = poly_mult( polyn05, 17, polyout[0], len, polyout[1] ); 350 | len = poly_mult( polyn06, 17, polyout[1], len, polyout[0] ); 351 | len = poly_mult( polyn07, 17, polyout[0], len, polyout[1] ); 352 | len = poly_mult( polyn08, 17, polyout[1], len, polyout[0] ); 353 | poly_pack( polyout[0], m_poly_n_8, 128 ); 354 | // display_poly_pack( m_poly_n_8, 128); 355 | 356 | len = poly_mult( polyn09, 17, polyout[0], len, polyout[1] ); 357 | len = poly_mult( polyn10, 17, polyout[1], len, polyout[0] ); 358 | poly_pack( polyout[0], m_poly_n_10, 160 ); 359 | // display_poly_pack( m_poly_n_10, 160); 360 | 361 | len = poly_mult( polyn11, 17, polyout[0], len, polyout[1] ); 362 | len = poly_mult( polyn12, 17, polyout[1], len, polyout[0] ); 363 | poly_pack( polyout[0], m_poly_n_12, 192 ); 364 | // display_poly_pack( m_poly_n_12, 192); 365 | // display_poly( polyout[0], len );//12 366 | 367 | 368 | len = poly_mult( polys01, 15, polys02, 15, polyout[0] ); 369 | len = poly_mult( polys03, 15, polyout[0], len, polyout[1] ); 370 | len = poly_mult( polys04, 15, polyout[1], len, polyout[0] ); 371 | len = poly_mult( polys05, 15, polyout[0], len, polyout[1] ); 372 | len = poly_mult( polys06, 15, polyout[1], len, polyout[0] ); 373 | len = poly_mult( polys07, 15, polyout[0], len, polyout[1] ); 374 | len = poly_mult( polys08, 15, polyout[1], len, polyout[0] ); 375 | len = poly_mult( polys09, 15, polyout[0], len, polyout[1] ); 376 | len = poly_mult( polys10, 15, polyout[1], len, polyout[0] ); 377 | len = poly_mult( polys11, 15, polyout[0], len, polyout[1] ); 378 | len = poly_mult( polys12, 15, polyout[1], len, polyout[0] ); 379 | poly_pack( polyout[0], m_poly_s_12, 168 ); 380 | // display_poly_pack( m_poly_s_12, 168); 381 | 382 | /* 383 | // test 384 | int pt1[] = {1,1}; 385 | int pt2[] = {1,1,1}; 386 | int pt3[] = {1,0,1,1,1,1}; 387 | len = poly_mult( pt1, 2, pt2, 3, polyout[0] ); 388 | len = poly_mult( pt3, 6, polyout[0], len, polyout[1] ); 389 | display_poly( polyout[1], len ); 390 | poly_pack( polyout[1], m_poly_s_12, len ); 391 | display_poly_pack( m_poly_s_12, 8 ); 392 | u32 shift[6]; 393 | shift[0] = 0x80000000; 394 | shift[1] = 0x00000000; 395 | shift[2] = 0x00000000; 396 | shift[3] = 0x00000000; 397 | shift[4] = 0x00000000; 398 | shift[5] = 0x00000000; 399 | 400 | for( int i = 0; i < 192; i++ ) 401 | { 402 | display_poly_pack( shift, 192 ); 403 | reg_6_shift( shift ); 404 | } 405 | 406 | // display_poly( polyout[0], len );//12 407 | // display_poly_pack( m_poly_s_12, 168 );// Wont work because of shift register length 408 | */ 409 | } 410 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvb2_ldpc_encode.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "DVB2.h" 3 | 4 | /* 5 | for( int row = 0; row < rows; row++ ) 6 | { 7 | for( int n = 0; n < 360; n++ ) 8 | { 9 | for( int col = 1; col <= table_name[row][0]; col++ ) 10 | { 11 | // parity bit location, position from start of block 12 | m_ldpc_encode.p[index] = m_format.kldpc + (table_name[row][col] + (n*m_format.q_val))%pbits; 13 | // data bit to be accumulated 14 | m_ldpc_encode.d[index] = im; 15 | index++; 16 | } 17 | im++; 18 | } 19 | } 20 | */ 21 | 22 | #define LDPC_BF( TABLE_NAME, ROWS ) \ 23 | for( int row = 0; row < ROWS; row++ ) \ 24 | { \ 25 | for( int n = 0; n < 360; n++ ) \ 26 | { \ 27 | for( int col = 1; col <= TABLE_NAME[row][0]; col++ ) \ 28 | { \ 29 | m_ldpc_encode.p[index] = (TABLE_NAME[row][col] + (n*q))%pbits; \ 30 | m_ldpc_encode.d[index] = im; \ 31 | index++; \ 32 | } \ 33 | im++; \ 34 | } \ 35 | } 36 | 37 | /* 38 | // 39 | // Generate the lookup tables for the ldpc mode 40 | // 41 | void DVBS2::ldpc_lookup_generate( void ) 42 | { 43 | int im; 44 | int index; 45 | int pbits; 46 | int uc; 47 | int rows; 48 | 49 | index = 0; 50 | im = 0; 51 | 52 | if(m_format.frame_type == FRAME_NORMAL) 53 | { 54 | if(m_format.code_rate == CR_2_3) 55 | { 56 | uc = m_format.kldpc; 57 | pbits = m_format.nldpc - m_format.kldpc; //number of parity bits 58 | rows = 120; 59 | 60 | for( int row = 0; row < rows; row++ )// for each row 61 | { 62 | for( int n = 0; n < 360; n++ ) 63 | { 64 | for( int col = 1; col <= ldpc_tab_2_3N[row][0]; col++ ) 65 | { 66 | // parity bit location, position from start of block 67 | m_ldpc_encode.p[index] = m_format.kldpc + (ldpc_tab_2_3N[row][col] + (n*m_format.q_val))%pbits; 68 | // data bit to be accumulated 69 | m_ldpc_encode.d[index] = im; 70 | index++; 71 | } 72 | im++; 73 | } 74 | } 75 | } 76 | } 77 | m_ldpc_encode.length = index; 78 | } 79 | */ 80 | void DVB2::ldpc_lookup_generate( void ) 81 | { 82 | int im; 83 | int index; 84 | int pbits; 85 | int q; 86 | index = 0; 87 | im = 0; 88 | 89 | pbits = m_format[0].nldpc - m_format[0].kldpc; //number of parity bits 90 | q = m_format[0].q_val; 91 | 92 | if(m_format[0].frame_type == FRAME_NORMAL) 93 | { 94 | if( m_format[0].code_rate == CR_1_4 ) LDPC_BF( ldpc_tab_1_4N, 45 ); 95 | if( m_format[0].code_rate == CR_1_3 ) LDPC_BF( ldpc_tab_1_3N, 60 ); 96 | if( m_format[0].code_rate == CR_2_5 ) LDPC_BF( ldpc_tab_2_5N, 72 ); 97 | if( m_format[0].code_rate == CR_1_2 ) LDPC_BF( ldpc_tab_1_2N, 90 ); 98 | if( m_format[0].code_rate == CR_3_5 ) LDPC_BF( ldpc_tab_3_5N, 108 ); 99 | if( m_format[0].code_rate == CR_2_3 ) LDPC_BF( ldpc_tab_2_3N, 120 ); 100 | if( m_format[0].code_rate == CR_3_4 ) LDPC_BF( ldpc_tab_3_4N, 135 ); 101 | if( m_format[0].code_rate == CR_4_5 ) LDPC_BF( ldpc_tab_4_5N, 144 ); 102 | if( m_format[0].code_rate == CR_5_6 ) LDPC_BF( ldpc_tab_5_6N, 150 ); 103 | if( m_format[0].code_rate == CR_8_9 ) LDPC_BF( ldpc_tab_8_9N, 160 ); 104 | if( m_format[0].code_rate == CR_9_10) LDPC_BF( ldpc_tab_9_10N, 162 ); 105 | } 106 | if(m_format[0].frame_type == FRAME_SHORT) 107 | { 108 | if( m_format[0].code_rate == CR_1_4 ) LDPC_BF( ldpc_tab_1_4S, 9 ); 109 | if( m_format[0].code_rate == CR_1_3 ) LDPC_BF( ldpc_tab_1_3S, 15 ); 110 | if( m_format[0].code_rate == CR_2_5 ) LDPC_BF( ldpc_tab_2_5S, 18 ); 111 | if( m_format[0].code_rate == CR_1_2 ) LDPC_BF( ldpc_tab_1_2S, 20 ); 112 | if( m_format[0].code_rate == CR_3_5 ) LDPC_BF( ldpc_tab_3_5S, 27 ); 113 | if( m_format[0].code_rate == CR_2_3 ) LDPC_BF( ldpc_tab_2_3S, 30 ); 114 | if( m_format[0].code_rate == CR_3_4 ) LDPC_BF( ldpc_tab_3_4S, 33 ); 115 | if( m_format[0].code_rate == CR_4_5 ) LDPC_BF( ldpc_tab_4_5S, 35 ); 116 | if( m_format[0].code_rate == CR_5_6 ) LDPC_BF( ldpc_tab_5_6S, 37 ); 117 | if( m_format[0].code_rate == CR_8_9 ) LDPC_BF( ldpc_tab_8_9S, 40 ); 118 | } 119 | m_ldpc_encode.table_length = index; 120 | } 121 | 122 | void DVB2::ldpc_encode( void ) 123 | { 124 | Bit *d,*p; 125 | // Calculate the number of parity bits 126 | int plen = m_format[0].nldpc - m_format[0].kldpc; 127 | d = m_frame; 128 | p = &m_frame[m_format[0].kldpc]; 129 | // First zero all the parity bits 130 | memset( p, 0, sizeof(Bit)*plen); 131 | 132 | // now do the parity checking 133 | for( int i = 0; i < m_ldpc_encode.table_length; i++ ) 134 | { 135 | p[m_ldpc_encode.p[i]] ^= d[m_ldpc_encode.d[i]]; 136 | } 137 | for( int i = 1; i < plen; i++ ) 138 | { 139 | p[i] ^= p[i-1]; 140 | } 141 | } 142 | void DVB2::ldpc_encode_test( void ) 143 | { 144 | if(1)// m_format.code_rate == CR_1_2 ) 145 | { 146 | printf("\n\nEncode length %d\n",m_ldpc_encode.table_length); 147 | printf("Parity start %d\n",m_format[0].kldpc); 148 | for( int i = 0; i < m_ldpc_encode.table_length; i++ ) 149 | { 150 | if(m_ldpc_encode.d[i] == 0 ) 151 | { 152 | printf("%d+%d\n",m_ldpc_encode.p[i],m_ldpc_encode.d[i]); 153 | } 154 | } 155 | printf("Encode test end\n\n"); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvb2_scrambler.cpp: -------------------------------------------------------------------------------- 1 | #include "DVB2.h" 2 | 3 | void DVB2::init_bb_randomiser(void) 4 | { 5 | int sr = 0x4A80; 6 | for( int i = 0; i < FRAME_SIZE_NORMAL; i++ ) 7 | { 8 | int b = ((sr)^(sr>>1))&1; 9 | m_bb_randomise[i] = b; 10 | sr >>= 1; 11 | if( b ) sr |= 0x4000; 12 | } 13 | } 14 | // 15 | // Randomise the data bits 16 | // 17 | void DVB2::bb_randomise(void) 18 | { 19 | for( int i = 0; i < m_format[0].kbch; i++ ) 20 | { 21 | m_frame[i] ^= m_bb_randomise[i]; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvbs2_interleave.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | #include "DVBS2.h" 3 | // 4 | // The output is bit packed ready for modulating 5 | // 6 | void DVBS2::s2_interleave( void ) 7 | { 8 | int index=0; 9 | int rows=0; 10 | 11 | int frame_size = m_format[0].nldpc; 12 | 13 | if( m_format[0].constellation == M_QPSK ) 14 | { 15 | rows = frame_size/2; 16 | m_payload_symbols = rows; 17 | for( int i = 0; i < rows; i++ ) 18 | { 19 | m_iframe[i] = m_frame[index++]<<1; 20 | m_iframe[i] |= m_frame[index++]; 21 | } 22 | return; 23 | } 24 | 25 | if( m_format[0].constellation == M_8PSK ) 26 | { 27 | if( m_format[0].code_rate == CR_3_5 ) 28 | { 29 | rows = frame_size/3; 30 | m_payload_symbols = rows; 31 | Bit *c1,*c2,*c3; 32 | c1 = &m_frame[rows*2]; 33 | c2 = &m_frame[rows]; 34 | c3 = &m_frame[0]; 35 | for( int i = 0; i < rows; i++ ) 36 | { 37 | m_iframe[i] = (c1[i]<<2) | (c2[i]<<1) | (c3[i]); 38 | } 39 | } 40 | else 41 | { 42 | rows = frame_size/3; 43 | m_payload_symbols = rows; 44 | Bit *c1,*c2,*c3; 45 | c1 = &m_frame[0]; 46 | c2 = &m_frame[rows]; 47 | c3 = &m_frame[rows*2]; 48 | for( int i = 0; i < rows; i++ ) 49 | { 50 | m_iframe[i] = (c1[i]<<2) | (c2[i]<<1) | (c3[i]); 51 | } 52 | } 53 | return; 54 | } 55 | 56 | if( m_format[0].constellation == M_16APSK ) 57 | { 58 | rows = frame_size/4; 59 | m_payload_symbols = rows; 60 | Bit *c1,*c2,*c3,*c4; 61 | c1 = &m_frame[0]; 62 | c2 = &m_frame[rows]; 63 | c3 = &m_frame[rows*2]; 64 | c4 = &m_frame[rows*3]; 65 | for( int i = 0; i < rows; i++ ) 66 | { 67 | m_iframe[i] = (c1[i]<<3) | (c2[i]<<2) | (c3[i]<<1) | (c4[i]); 68 | } 69 | return; 70 | } 71 | 72 | if( m_format[0].constellation == M_32APSK ) 73 | { 74 | rows = frame_size/5; 75 | m_payload_symbols = rows; 76 | Bit *c1,*c2,*c3,*c4,*c5; 77 | c1 = &m_frame[0]; 78 | c2 = &m_frame[rows]; 79 | c3 = &m_frame[rows*2]; 80 | c4 = &m_frame[rows*3]; 81 | c5 = &m_frame[rows*4]; 82 | for( int i = 0; i < rows; i++ ) 83 | { 84 | m_iframe[i] = (c1[i]<<4) | (c2[i]<<3) | (c3[i]<<2) | (c4[i]<<1) | c5[i]; 85 | } 86 | return; 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvbs2_modulator.cpp: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | #include "DVBS2.h" 3 | 4 | #define CP 0x7FFF 5 | void DVBS2::modulator_configuration(void) 6 | { 7 | double r0,r1,r2,r3; 8 | double m = 1.0; 9 | r0 = 1.0;// I am not sure why this needs to be 0.9 but 32APSK does not work if == 1.0 10 | r1 = m; 11 | // BPSK 12 | m_bpsk[0][0].re = (short)((r0*cos(1*M_PI/4.0))*CP); 13 | m_bpsk[0][0].im = (short)((r0*sin(1*M_PI/4.0))*CP); 14 | m_bpsk[0][1].re = (short)((r0*cos(5*M_PI/4.0))*CP); 15 | m_bpsk[0][1].im = (short)((r0*sin(5*M_PI/4.0))*CP); 16 | 17 | m_bpsk[1][0].re = (short)((r0*cos(3*M_PI/4.0))*CP); 18 | m_bpsk[1][0].im = (short)((r0*sin(3*M_PI/4.0))*CP); 19 | m_bpsk[1][1].re = (short)((r0*cos(7*M_PI/4.0))*CP); 20 | m_bpsk[1][1].im = (short)((r0*sin(7*M_PI/4.0))*CP); 21 | 22 | // QPSK 23 | m_qpsk[0].re = (short)((r1*cos(M_PI/4.0))*CP); 24 | m_qpsk[0].im = (short)((r1*sin(M_PI/4.0))*CP); 25 | m_qpsk[1].re = (short)((r1*cos(7*M_PI/4.0))*CP); 26 | m_qpsk[1].im = (short)((r1*sin(7*M_PI/4.0))*CP); 27 | m_qpsk[2].re = (short)((r1*cos(3*M_PI/4.0))*CP); 28 | m_qpsk[2].im = (short)((r1*sin(3*M_PI/4.0))*CP); 29 | m_qpsk[3].re = (short)((r1*cos(5*M_PI/4.0))*CP); 30 | m_qpsk[3].im = (short)((r1*sin(5*M_PI/4.0))*CP); 31 | 32 | // 8PSK 33 | m_8psk[0].re = (short)((r1*cos(M_PI/4.0))*CP); 34 | m_8psk[0].im = (short)((r1*sin(M_PI/4.0))*CP); 35 | m_8psk[1].re = (short)((r1*cos(0.0))*CP); 36 | m_8psk[1].im = (short)((r1*sin(0.0))*CP); 37 | m_8psk[2].re = (short)((r1*cos(4*M_PI/4.0))*CP); 38 | m_8psk[2].im = (short)((r1*sin(4*M_PI/4.0))*CP); 39 | m_8psk[3].re = (short)((r1*cos(5*M_PI/4.0))*CP); 40 | m_8psk[3].im = (short)((r1*sin(5*M_PI/4.0))*CP); 41 | m_8psk[4].re = (short)((r1*cos(2*M_PI/4.0))*CP); 42 | m_8psk[4].im = (short)((r1*sin(2*M_PI/4.0))*CP); 43 | m_8psk[5].re = (short)((r1*cos(7*M_PI/4.0))*CP); 44 | m_8psk[5].im = (short)((r1*sin(7*M_PI/4.0))*CP); 45 | m_8psk[6].re = (short)((r1*cos(3*M_PI/4.0))*CP); 46 | m_8psk[6].im = (short)((r1*sin(3*M_PI/4.0))*CP); 47 | m_8psk[7].re = (short)((r1*cos(6*M_PI/4.0))*CP); 48 | m_8psk[7].im = (short)((r1*sin(6*M_PI/4.0))*CP); 49 | 50 | // 16 APSK 51 | r2 = m; 52 | switch( m_format[0].code_rate ) 53 | { 54 | case CR_2_3: 55 | r1 = r2/3.15; 56 | break; 57 | case CR_3_4: 58 | r1 = r2/2.85; 59 | break; 60 | case CR_4_5: 61 | r1 = r2/2.75; 62 | break; 63 | case CR_5_6: 64 | r1 = r2/2.70; 65 | break; 66 | case CR_8_9: 67 | r1 = r2/2.60; 68 | break; 69 | case CR_9_10: 70 | r1 = r2/2.57; 71 | break; 72 | default: 73 | // Illegal 74 | r1 = 0; 75 | break; 76 | } 77 | 78 | m_16apsk[0].re = (short)((r2*cos(M_PI/4.0))*CP); 79 | m_16apsk[0].im = (short)((r2*sin(M_PI/4.0))*CP); 80 | m_16apsk[1].re = (short)((r2*cos(-M_PI/4.0))*CP); 81 | m_16apsk[1].im = (short)((r2*sin(-M_PI/4.0))*CP); 82 | m_16apsk[2].re = (short)((r2*cos(3*M_PI/4.0))*CP); 83 | m_16apsk[2].im = (short)((r2*sin(3*M_PI/4.0))*CP); 84 | m_16apsk[3].re = (short)((r2*cos(-3*M_PI/4.0))*CP); 85 | m_16apsk[3].im = (short)((r2*sin(-3*M_PI/4.0))*CP); 86 | m_16apsk[4].re = (short)((r2*cos(M_PI/12.0))*CP); 87 | m_16apsk[4].im = (short)((r2*sin(M_PI/12.0))*CP); 88 | m_16apsk[5].re = (short)((r2*cos(-M_PI/12.0))*CP); 89 | m_16apsk[5].im = (short)((r2*sin(-M_PI/12.0))*CP); 90 | m_16apsk[6].re = (short)((r2*cos(11*M_PI/12.0))*CP); 91 | m_16apsk[6].im = (short)((r2*sin(11*M_PI/12.0))*CP); 92 | m_16apsk[7].re = (short)((r2*cos(-11*M_PI/12.0))*CP); 93 | m_16apsk[7].im = (short)((r2*sin(-11*M_PI/12.0))*CP); 94 | m_16apsk[8].re = (short)((r2*cos(5*M_PI/12.0))*CP); 95 | m_16apsk[8].im = (short)((r2*sin(5*M_PI/12.0))*CP); 96 | m_16apsk[9].re = (short)((r2*cos(-5*M_PI/12.0))*CP); 97 | m_16apsk[9].im = (short)((r2*sin(-5*M_PI/12.0))*CP); 98 | m_16apsk[10].re = (short)((r2*cos(7*M_PI/12.0))*CP); 99 | m_16apsk[10].im = (short)((r2*sin(7*M_PI/12.0))*CP); 100 | m_16apsk[11].re = (short)((r2*cos(-7*M_PI/12.0))*CP); 101 | m_16apsk[11].im = (short)((r2*sin(-7*M_PI/12.0))*CP); 102 | m_16apsk[12].re = (short)((r1*cos(M_PI/4.0))*CP); 103 | m_16apsk[12].im = (short)((r1*sin(M_PI/4.0))*CP); 104 | m_16apsk[13].re = (short)((r1*cos(-M_PI/4.0))*CP); 105 | m_16apsk[13].im = (short)((r1*sin(-M_PI/4.0))*CP); 106 | m_16apsk[14].re = (short)((r1*cos(3*M_PI/4.0))*CP); 107 | m_16apsk[14].im = (short)((r1*sin(3*M_PI/4.0))*CP); 108 | m_16apsk[15].re = (short)((r1*cos(-3*M_PI/4.0))*CP); 109 | m_16apsk[15].im = (short)((r1*sin(-3*M_PI/4.0))*CP); 110 | // 32 APSK 111 | r3 = m; 112 | //r2=0.9; 113 | switch( m_format[0].code_rate ) 114 | { 115 | case CR_3_4: 116 | r1 = r3/5.27; 117 | r2 = r1*2.84; 118 | break; 119 | case CR_4_5: 120 | r1 = r3/4.87; 121 | r2 = r1*2.72; 122 | break; 123 | case CR_5_6: 124 | r1 = r3/4.64; 125 | r2 = r1*2.64; 126 | break; 127 | case CR_8_9: 128 | r1 = r3/4.33; 129 | r2 = r1*2.54; 130 | break; 131 | case CR_9_10: 132 | r1 = r3/4.30; 133 | r2 = r1*2.53; 134 | break; 135 | default: 136 | // Illegal 137 | r1 = 0; 138 | r2 = 0; 139 | break; 140 | } 141 | 142 | m_32apsk[0].re = (short)((r2*cos(M_PI/4.0))*CP); 143 | m_32apsk[0].im = (short)((r2*sin(M_PI/4.0))*CP); 144 | m_32apsk[1].re = (short)((r2*cos(5*M_PI/12.0))*CP); 145 | m_32apsk[1].im = (short)((r2*sin(5*M_PI/12.0))*CP); 146 | m_32apsk[2].re = (short)((r2*cos(-M_PI/4.0))*CP); 147 | m_32apsk[2].im = (short)((r2*sin(-M_PI/4.0))*CP); 148 | m_32apsk[3].re = (short)((r2*cos(-5*M_PI/12.0))*CP); 149 | m_32apsk[3].im = (short)((r2*sin(-5*M_PI/12.0))*CP); 150 | m_32apsk[4].re = (short)((r2*cos(3*M_PI/4.0))*CP); 151 | m_32apsk[4].im = (short)((r2*sin(3*M_PI/4.0))*CP); 152 | m_32apsk[5].re = (short)((r2*cos(7*M_PI/12.0))*CP); 153 | m_32apsk[5].im = (short)((r2*sin(7*M_PI/12.0))*CP); 154 | m_32apsk[6].re = (short)((r2*cos(-3*M_PI/4.0))*CP); 155 | m_32apsk[6].im = (short)((r2*sin(-3*M_PI/4.0))*CP); 156 | m_32apsk[7].re = (short)((r2*cos(-7*M_PI/12.0))*CP); 157 | m_32apsk[7].im = (short)((r2*sin(-7*M_PI/12.0))*CP); 158 | m_32apsk[8].re = (short)((r3*cos(M_PI/8.0))*CP); 159 | m_32apsk[8].im = (short)((r3*sin(M_PI/8.0))*CP); 160 | m_32apsk[9].re = (short)((r3*cos(3*M_PI/8.0))*CP); 161 | m_32apsk[9].im = (short)((r3*sin(3*M_PI/8.0))*CP); 162 | m_32apsk[10].re = (short)((r3*cos(-M_PI/4.0))*CP); 163 | m_32apsk[10].im = (short)((r3*sin(-M_PI/4.0))*CP); 164 | m_32apsk[11].re = (short)((r3*cos(-M_PI/2.0))*CP); 165 | m_32apsk[11].im = (short)((r3*sin(-M_PI/2.0))*CP); 166 | m_32apsk[12].re = (short)((r3*cos(3*M_PI/4.0))*CP); 167 | m_32apsk[12].im = (short)((r3*sin(3*M_PI/4.0))*CP); 168 | m_32apsk[13].re = (short)((r3*cos(M_PI/2.0))*CP); 169 | m_32apsk[13].im = (short)((r3*sin(M_PI/2.0))*CP); 170 | m_32apsk[14].re = (short)((r3*cos(-7*M_PI/8.0))*CP); 171 | m_32apsk[14].im = (short)((r3*sin(-7*M_PI/8.0))*CP); 172 | m_32apsk[15].re = (short)((r3*cos(-5*M_PI/8.0))*CP); 173 | m_32apsk[15].im = (short)((r3*sin(-5*M_PI/8.0))*CP); 174 | m_32apsk[16].re = (short)((r2*cos(M_PI/12.0))*CP); 175 | m_32apsk[16].im = (short)((r2*sin(M_PI/12.0))*CP); 176 | m_32apsk[17].re = (short)((r1*cos(M_PI/4.0))*CP); 177 | m_32apsk[17].im = (short)((r1*sin(M_PI/4.0))*CP); 178 | m_32apsk[18].re = (short)((r2*cos(-M_PI/12.0))*CP); 179 | m_32apsk[18].im = (short)((r2*sin(-M_PI/12.0))*CP); 180 | m_32apsk[19].re = (short)((r1*cos(-M_PI/4.0))*CP); 181 | m_32apsk[19].im = (short)((r1*sin(-M_PI/4.0))*CP); 182 | m_32apsk[20].re = (short)((r2*cos(11*M_PI/12.0))*CP); 183 | m_32apsk[20].im = (short)((r2*sin(11*M_PI/12.0))*CP); 184 | m_32apsk[21].re = (short)((r1*cos(3*M_PI/4.0))*CP); 185 | m_32apsk[21].im = (short)((r1*sin(3*M_PI/4.0))*CP); 186 | m_32apsk[22].re = (short)((r2*cos(-11*M_PI/12.0))*CP); 187 | m_32apsk[22].im = (short)((r2*sin(-11*M_PI/12.0))*CP); 188 | m_32apsk[23].re = (short)((r1*cos(-3*M_PI/4.0))*CP); 189 | m_32apsk[23].im = (short)((r1*sin(-3*M_PI/4.0))*CP); 190 | m_32apsk[24].re = (short)((r3*cos(0.0))*CP); 191 | m_32apsk[24].im = (short)((r3*sin(0.0))*CP); 192 | m_32apsk[25].re = (short)((r3*cos(M_PI/4.0))*CP); 193 | m_32apsk[25].im = (short)((r3*sin(M_PI/4.0))*CP); 194 | m_32apsk[26].re = (short)((r3*cos(-M_PI/8.0))*CP); 195 | m_32apsk[26].im = (short)((r3*sin(-M_PI/8.0))*CP); 196 | m_32apsk[27].re = (short)((r3*cos(-3*M_PI/8.0))*CP); 197 | m_32apsk[27].im = (short)((r3*sin(-3*M_PI/8.0))*CP); 198 | m_32apsk[28].re = (short)((r3*cos(7*M_PI/8.0))*CP); 199 | m_32apsk[28].im = (short)((r3*sin(7*M_PI/8.0))*CP); 200 | m_32apsk[29].re = (short)((r3*cos(5*M_PI/8.0))*CP); 201 | m_32apsk[29].im = (short)((r3*sin(5*M_PI/8.0))*CP); 202 | m_32apsk[30].re = (short)((r3*cos(M_PI))*CP); 203 | m_32apsk[30].im = (short)((r3*sin(M_PI))*CP); 204 | m_32apsk[31].re = (short)((r3*cos(-3*M_PI/4.0))*CP); 205 | m_32apsk[31].im = (short)((r3*sin(-3*M_PI/4.0))*CP); 206 | } 207 | //OLD 208 | /* 209 | void DVBS2::modulator_configuration(void) 210 | { 211 | double r0,r1,r2,r3; 212 | double m = 1.0; 213 | r0 = 0.9;// I am not sure why this needs to be 0.9 but 32APSK does not work if == 1.0 214 | r1 = m; 215 | // BPSK 216 | m_bpsk[0][0].re = (short)((r0*cos(M_PI/4.0))*CP); 217 | m_bpsk[0][0].im = (short)((r0*sin(M_PI/4.0))*CP); 218 | m_bpsk[0][1].re = (short)((r0*cos(5.0*M_PI/4.0))*CP); 219 | m_bpsk[0][1].im = (short)((r0*sin(5.0*M_PI/4.0))*CP); 220 | m_bpsk[1][0].re = (short)((r0*cos(5.0*M_PI/4.0))*CP); 221 | m_bpsk[1][0].im = (short)((r0*sin(M_PI/4.0))*CP); 222 | m_bpsk[1][1].re = (short)((r0*cos(M_PI/4.0))*CP); 223 | m_bpsk[1][1].im = (short)((r0*sin(5.0*M_PI/4.0))*CP); 224 | 225 | // QPSK 226 | m_qpsk[0].re = (short)((r1*cos(M_PI/4.0))*CP); 227 | m_qpsk[0].im = (short)((r1*sin(M_PI/4.0))*CP); 228 | m_qpsk[1].re = (short)((r1*cos(7*M_PI/4.0))*CP); 229 | m_qpsk[1].im = (short)((r1*sin(7*M_PI/4.0))*CP); 230 | m_qpsk[2].re = (short)((r1*cos(3*M_PI/4.0))*CP); 231 | m_qpsk[2].im = (short)((r1*sin(3*M_PI/4.0))*CP); 232 | m_qpsk[3].re = (short)((r1*cos(5*M_PI/4.0))*CP); 233 | m_qpsk[3].im = (short)((r1*sin(5*M_PI/4.0))*CP); 234 | 235 | // 8PSK 236 | m_8psk[0].re = (short)((r1*cos(M_PI/4.0))*CP); 237 | m_8psk[0].im = (short)((r1*sin(M_PI/4.0))*CP); 238 | m_8psk[1].re = (short)((r1*cos(0.0))*CP); 239 | m_8psk[1].im = (short)((r1*sin(0.0))*CP); 240 | m_8psk[2].re = (short)((r1*cos(4*M_PI/4.0))*CP); 241 | m_8psk[2].im = (short)((r1*sin(4*M_PI/4.0))*CP); 242 | m_8psk[3].re = (short)((r1*cos(5*M_PI/4.0))*CP); 243 | m_8psk[3].im = (short)((r1*sin(5*M_PI/4.0))*CP); 244 | m_8psk[4].re = (short)((r1*cos(2*M_PI/4.0))*CP); 245 | m_8psk[4].im = (short)((r1*sin(2*M_PI/4.0))*CP); 246 | m_8psk[5].re = (short)((r1*cos(7*M_PI/4.0))*CP); 247 | m_8psk[5].im = (short)((r1*sin(7*M_PI/4.0))*CP); 248 | m_8psk[6].re = (short)((r1*cos(3*M_PI/4.0))*CP); 249 | m_8psk[6].im = (short)((r1*sin(3*M_PI/4.0))*CP); 250 | m_8psk[7].re = (short)((r1*cos(6*M_PI/4.0))*CP); 251 | m_8psk[7].im = (short)((r1*sin(6*M_PI/4.0))*CP); 252 | 253 | // 16 APSK 254 | r2 = m; 255 | switch( m_format[0].code_rate ) 256 | { 257 | case CR_2_3: 258 | r1 = r2/3.15; 259 | break; 260 | case CR_3_4: 261 | r1 = r2/2.85; 262 | break; 263 | case CR_4_5: 264 | r1 = r2/2.75; 265 | break; 266 | case CR_5_6: 267 | r1 = r2/2.70; 268 | break; 269 | case CR_8_9: 270 | r1 = r2/2.60; 271 | break; 272 | case CR_9_10: 273 | r1 = r2/2.57; 274 | break; 275 | default: 276 | // Illegal 277 | r1 = 0; 278 | break; 279 | } 280 | m_16apsk[0].re = (short)((r2*cos(M_PI/4.0))*CP); 281 | m_16apsk[0].im = (short)((r2*sin(M_PI/4.0))*CP); 282 | m_16apsk[1].re = (short)((r2*cos(-M_PI/4.0))*CP); 283 | m_16apsk[1].im = (short)((r2*sin(-M_PI/4.0))*CP); 284 | m_16apsk[2].re = (short)((r2*cos(3*M_PI/4.0))*CP); 285 | m_16apsk[2].im = (short)((r2*sin(3*M_PI/4.0))*CP); 286 | m_16apsk[3].re = (short)((r2*cos(-3*M_PI/4.0))*CP); 287 | m_16apsk[3].im = (short)((r2*sin(-3*M_PI/4.0))*CP); 288 | m_16apsk[4].re = (short)((r2*cos(M_PI/12.0))*CP); 289 | m_16apsk[4].im = (short)((r2*sin(M_PI/12.0))*CP); 290 | m_16apsk[5].re = (short)((r2*cos(-M_PI/12.0))*CP); 291 | m_16apsk[5].im = (short)((r2*sin(-M_PI/12.0))*CP); 292 | m_16apsk[6].re = (short)((r2*cos(11*M_PI/12.0))*CP); 293 | m_16apsk[6].im = (short)((r2*sin(11*M_PI/12.0))*CP); 294 | m_16apsk[7].re = (short)((r2*cos(-11*M_PI/12.0))*CP); 295 | m_16apsk[7].im = (short)((r2*sin(-11*M_PI/12.0))*CP); 296 | m_16apsk[8].re = (short)((r2*cos(5*M_PI/12.0))*CP); 297 | m_16apsk[8].im = (short)((r2*sin(5*M_PI/12.0))*CP); 298 | m_16apsk[9].re = (short)((r2*cos(-5*M_PI/12.0))*CP); 299 | m_16apsk[9].im = (short)((r2*sin(-5*M_PI/12.0))*CP); 300 | m_16apsk[10].re = (short)((r2*cos(7*M_PI/12.0))*CP); 301 | m_16apsk[10].im = (short)((r2*sin(7*M_PI/12.0))*CP); 302 | m_16apsk[11].re = (short)((r2*cos(-7*M_PI/12.0))*CP); 303 | m_16apsk[11].im = (short)((r2*sin(-7*M_PI/12.0))*CP); 304 | m_16apsk[12].re = (short)((r1*cos(M_PI/4.0))*CP); 305 | m_16apsk[12].im = (short)((r1*sin(M_PI/4.0))*CP); 306 | m_16apsk[13].re = (short)((r1*cos(-M_PI/4.0))*CP); 307 | m_16apsk[13].im = (short)((r1*sin(-M_PI/4.0))*CP); 308 | m_16apsk[14].re = (short)((r1*cos(3*M_PI/4.0))*CP); 309 | m_16apsk[14].im = (short)((r1*sin(3*M_PI/4.0))*CP); 310 | m_16apsk[15].re = (short)((r1*cos(-3*M_PI/4.0))*CP); 311 | m_16apsk[15].im = (short)((r1*sin(-3*M_PI/4.0))*CP); 312 | // 32 APSK 313 | r3 = m; 314 | switch( m_format[0].code_rate ) 315 | { 316 | case CR_3_4: 317 | r1 = r3/5.27; 318 | r2 = r1*2.84; 319 | break; 320 | case CR_4_5: 321 | r1 = r3/4.87; 322 | r2 = r1*2.72; 323 | break; 324 | case CR_5_6: 325 | r1 = r3/4.64; 326 | r2 = r1*2.64; 327 | break; 328 | case CR_8_9: 329 | r1 = r3/4.33; 330 | r2 = r1*2.54; 331 | break; 332 | case CR_9_10: 333 | r1 = r3/4.30; 334 | r2 = r1*2.53; 335 | break; 336 | default: 337 | // Illegal 338 | r1 = 0; 339 | r2 = 0; 340 | break; 341 | } 342 | m_32apsk[0].re = (short)((r2*cos(M_PI/4.0))*CP); 343 | m_32apsk[0].im = (short)((r2*sin(M_PI/4.0))*CP); 344 | m_32apsk[1].re = (short)((r2*cos(5*M_PI/12.0))*CP); 345 | m_32apsk[1].im = (short)((r2*sin(5*M_PI/12.0))*CP); 346 | m_32apsk[2].re = (short)((r2*cos(-M_PI/4.0))*CP); 347 | m_32apsk[2].im = (short)((r2*sin(-M_PI/4.0))*CP); 348 | m_32apsk[3].re = (short)((r2*cos(-5*M_PI/12.0))*CP); 349 | m_32apsk[3].im = (short)((r2*sin(-5*M_PI/12.0))*CP); 350 | m_32apsk[4].re = (short)((r2*cos(3*M_PI/4.0))*CP); 351 | m_32apsk[4].im = (short)((r2*sin(3*M_PI/4.0))*CP); 352 | m_32apsk[5].re = (short)((r2*cos(7*M_PI/12.0))*CP); 353 | m_32apsk[5].im = (short)((r2*sin(7*M_PI/12.0))*CP); 354 | m_32apsk[6].re = (short)((r2*cos(-3*M_PI/4.0))*CP); 355 | m_32apsk[6].im = (short)((r2*sin(-3*M_PI/4.0))*CP); 356 | m_32apsk[7].re = (short)((r2*cos(-7*M_PI/12.0))*CP); 357 | m_32apsk[7].im = (short)((r2*sin(-7*M_PI/12.0))*CP); 358 | m_32apsk[8].re = (short)((r3*cos(M_PI/8.0))*CP); 359 | m_32apsk[8].im = (short)((r3*sin(M_PI/8.0))*CP); 360 | m_32apsk[9].re = (short)((r3*cos(3*M_PI/8.0))*CP); 361 | m_32apsk[9].im = (short)((r3*sin(3*M_PI/8.0))*CP); 362 | m_32apsk[10].re = (short)((r3*cos(-M_PI/4.0))*CP); 363 | m_32apsk[10].im = (short)((r3*sin(-M_PI/4.0))*CP); 364 | m_32apsk[11].re = (short)((r3*cos(-M_PI/2.0))*CP); 365 | m_32apsk[11].im = (short)((r3*sin(-M_PI/2.0))*CP); 366 | m_32apsk[12].re = (short)((r3*cos(3*M_PI/4.0))*CP); 367 | m_32apsk[12].im = (short)((r3*sin(3*M_PI/4.0))*CP); 368 | m_32apsk[13].re = (short)((r3*cos(M_PI/2.0))*CP); 369 | m_32apsk[13].im = (short)((r3*sin(M_PI/2.0))*CP); 370 | m_32apsk[14].re = (short)((r3*cos(-7*M_PI/8.0))*CP); 371 | m_32apsk[14].im = (short)((r3*sin(-7*M_PI/8.0))*CP); 372 | m_32apsk[15].re = (short)((r3*cos(-5*M_PI/8.0))*CP); 373 | m_32apsk[15].im = (short)((r3*sin(-5*M_PI/8.0))*CP); 374 | m_32apsk[16].re = (short)((r2*cos(M_PI/12.0))*CP); 375 | m_32apsk[16].im = (short)((r2*sin(M_PI/12.0))*CP); 376 | m_32apsk[17].re = (short)((r1*cos(M_PI/4.0))*CP); 377 | m_32apsk[17].im = (short)((r1*sin(M_PI/4.0))*CP); 378 | m_32apsk[18].re = (short)((r2*cos(-M_PI/12.0))*CP); 379 | m_32apsk[18].im = (short)((r2*sin(-M_PI/12.0))*CP); 380 | m_32apsk[19].re = (short)((r1*cos(-M_PI/4.0))*CP); 381 | m_32apsk[19].im = (short)((r1*sin(-M_PI/4.0))*CP); 382 | m_32apsk[20].re = (short)((r2*cos(11*M_PI/12.0))*CP); 383 | m_32apsk[20].im = (short)((r2*sin(11*M_PI/12.0))*CP); 384 | m_32apsk[21].re = (short)((r1*cos(3*M_PI/4.0))*CP); 385 | m_32apsk[21].im = (short)((r1*sin(3*M_PI/4.0))*CP); 386 | m_32apsk[22].re = (short)((r2*cos(-11*M_PI/12.0))*CP); 387 | m_32apsk[22].im = (short)((r2*sin(-11*M_PI/12.0))*CP); 388 | m_32apsk[23].re = (short)((r1*cos(-3*M_PI/4.0))*CP); 389 | m_32apsk[23].im = (short)((r1*sin(-3*M_PI/4.0))*CP); 390 | m_32apsk[24].re = (short)((r3*cos(0.0))*CP); 391 | m_32apsk[24].im = (short)((r3*sin(0.0))*CP); 392 | m_32apsk[25].re = (short)((r3*cos(M_PI/4.0))*CP); 393 | m_32apsk[25].im = (short)((r3*sin(M_PI/4.0))*CP); 394 | m_32apsk[26].re = (short)((r3*cos(-M_PI/8.0))*CP); 395 | m_32apsk[26].im = (short)((r3*sin(-M_PI/8.0))*CP); 396 | m_32apsk[27].re = (short)((r3*cos(-3*M_PI/8.0))*CP); 397 | m_32apsk[27].im = (short)((r3*sin(-3*M_PI/8.0))*CP); 398 | m_32apsk[28].re = (short)((r3*cos(7*M_PI/8.0))*CP); 399 | m_32apsk[28].im = (short)((r3*sin(7*M_PI/8.0))*CP); 400 | m_32apsk[29].re = (short)((r3*cos(5*M_PI/8.0))*CP); 401 | m_32apsk[29].im = (short)((r3*sin(5*M_PI/8.0))*CP); 402 | m_32apsk[30].re = (short)((r3*cos(M_PI))*CP); 403 | m_32apsk[30].im = (short)((r3*sin(M_PI))*CP); 404 | m_32apsk[31].re = (short)((r3*cos(-3*M_PI/4.0))*CP); 405 | m_32apsk[31].im = (short)((r3*sin(-3*M_PI/4.0))*CP); 406 | } 407 | */ -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvbs2_physical.cpp: -------------------------------------------------------------------------------- 1 | #include "DVBS2.h" 2 | 3 | void DVBS2::b_64_7_code( unsigned char in, int *out ) 4 | { 5 | unsigned long temp,bit; 6 | 7 | temp = 0; 8 | 9 | if(in&0x40) temp ^= g[0]; 10 | if(in&0x20) temp ^= g[1]; 11 | if(in&0x10) temp ^= g[2]; 12 | if(in&0x08) temp ^= g[3]; 13 | if(in&0x04) temp ^= g[4]; 14 | if(in&0x02) temp ^= g[5]; 15 | 16 | bit = 0x80000000; 17 | for( int m = 0; m < 32; m++ ) 18 | { 19 | out[(m*2)] = (temp&bit)?1:0; 20 | out[(m*2)+1] = out[m*2]^(in&0x01); 21 | bit >>= 1; 22 | } 23 | // Randomise it 24 | for( int m = 0; m < 64; m++ ) 25 | { 26 | out[m] = out[m] ^ ph_scram_tab[m]; 27 | } 28 | } 29 | //[MODCOD 6:2 ][TYPE 1:0 ] 30 | void DVBS2::s2_pl_header_encode( u8 modcod, u8 type, int *out) 31 | { 32 | unsigned char code; 33 | 34 | code = (modcod<<2) | type; 35 | //printf("MODCOD %d TYPE %d %d\n",modcod,type,code); 36 | // Add the modcod and type information and scramble it 37 | b_64_7_code( code, out ); 38 | } 39 | void DVBS2::s2_pl_header_create(void) 40 | { 41 | int type, modcod; 42 | 43 | modcod = 0; 44 | 45 | if( m_format[0].frame_type == FRAME_NORMAL ) 46 | type = 0; 47 | else 48 | type = 2; 49 | 50 | if( m_format[0].pilots ) type |= 1; 51 | 52 | // Mode and code rate 53 | if( m_format[0].constellation == M_QPSK ) 54 | { 55 | switch( m_format[0].code_rate ) 56 | { 57 | case CR_1_4: 58 | modcod = 1; 59 | break; 60 | case CR_1_3: 61 | modcod = 2; 62 | break; 63 | case CR_2_5: 64 | modcod = 3; 65 | break; 66 | case CR_1_2: 67 | modcod = 4; 68 | break; 69 | case CR_3_5: 70 | modcod = 5; 71 | break; 72 | case CR_2_3: 73 | modcod = 6; 74 | break; 75 | case CR_3_4: 76 | modcod = 7; 77 | break; 78 | case CR_4_5: 79 | modcod = 8; 80 | break; 81 | case CR_5_6: 82 | modcod = 9; 83 | break; 84 | case CR_8_9: 85 | modcod = 10; 86 | break; 87 | case CR_9_10: 88 | modcod = 11; 89 | break; 90 | default: 91 | modcod = 0; 92 | break; 93 | } 94 | } 95 | 96 | if( m_format[0].constellation == M_8PSK ) 97 | { 98 | switch( m_format[0].code_rate ) 99 | { 100 | case CR_3_5: 101 | modcod = 12; 102 | break; 103 | case CR_2_3: 104 | modcod = 13; 105 | break; 106 | case CR_3_4: 107 | modcod = 14; 108 | break; 109 | case CR_5_6: 110 | modcod = 15; 111 | break; 112 | case CR_8_9: 113 | modcod = 16; 114 | break; 115 | case CR_9_10: 116 | modcod = 17; 117 | break; 118 | default: 119 | modcod = 0; 120 | break; 121 | } 122 | } 123 | 124 | if( m_format[0].constellation == M_16APSK ) 125 | { 126 | switch( m_format[0].code_rate ) 127 | { 128 | case CR_2_3: 129 | modcod = 18; 130 | break; 131 | case CR_3_4: 132 | modcod = 19; 133 | break; 134 | case CR_4_5: 135 | modcod = 20; 136 | break; 137 | case CR_5_6: 138 | modcod = 21; 139 | break; 140 | case CR_8_9: 141 | modcod = 22; 142 | break; 143 | case CR_9_10: 144 | modcod = 23; 145 | break; 146 | default: 147 | modcod = 0; 148 | break; 149 | } 150 | } 151 | 152 | if( m_format[0].constellation == M_32APSK ) 153 | { 154 | switch( m_format[0].code_rate ) 155 | { 156 | case CR_3_4: 157 | modcod = 24; 158 | break; 159 | case CR_4_5: 160 | modcod = 25; 161 | break; 162 | case CR_5_6: 163 | modcod = 26; 164 | break; 165 | case CR_8_9: 166 | modcod = 27; 167 | break; 168 | case CR_9_10: 169 | modcod = 28; 170 | break; 171 | default: 172 | modcod = 0; 173 | break; 174 | } 175 | } 176 | // Now create the PL header. 177 | int b[90]; 178 | // Add the sync sequence SOF 179 | for( int i = 0; i < 26; i++ ) b[i] = ph_sync_seq[i]; 180 | // Add the mode and code 181 | s2_pl_header_encode( modcod, type, &b[26] ); 182 | 183 | // BPSK modulate and add the header 184 | for( int i = 0; i < 90; i++ ) 185 | { 186 | m_pl[i] = m_bpsk[i&1][b[i]]; 187 | } 188 | } 189 | // 190 | // m_symbols is the total number of complex symbols in the frame 191 | // Modulate the data starting at symbol 90 192 | // 193 | int DVBS2::s2_pl_data_pack( void ) 194 | { 195 | int m = 0; 196 | int n = 90;// Jump over header 197 | int blocks = m_payload_symbols/90; 198 | int block_count = 0; 199 | 200 | // See if PSK 201 | if( m_format[0].constellation == M_QPSK ) 202 | { 203 | for( int i = 0; i < blocks; i++ ) 204 | { 205 | for( int j = 0; j < 90; j++ ) 206 | { 207 | m_pl[n++] = m_qpsk[m_iframe[m++]]; 208 | } 209 | block_count = (block_count+1)%16; 210 | if((block_count == 0)&&(i>= 1; 33 | if( xb ) x |= 0x20000; 34 | 35 | ya = parity_chk( y, 0x04A1 ); 36 | yb = parity_chk( y, 0xFF60 ); 37 | yc = y&1; 38 | 39 | y >>= 1; 40 | if( ya ) y |= 0x20000; 41 | 42 | zna = xc ^ yc; 43 | znb = xa ^ yb; 44 | rn = (znb<<1) + zna; 45 | m_cscram[i] = rn; 46 | } 47 | } 48 | 49 | void DVBS2::pl_scramble_symbols( scmplx *fs, int len ) 50 | { 51 | scmplx x; 52 | 53 | // Start at the end of the PL Header. 54 | 55 | for( int n = 0; n < len; n++ ) 56 | { 57 | x = fs[n]; 58 | switch( m_cscram[n] ) 59 | { 60 | case 0: 61 | // Do nothing 62 | break; 63 | case 1: 64 | fs[n].re = -x.im; 65 | fs[n].im = x.re; 66 | break; 67 | case 2: 68 | fs[n].re = -fs[n].re; 69 | fs[n].im = -fs[n].im; 70 | break; 71 | case 03: 72 | x = fs[n]; 73 | fs[n].re = x.im; 74 | fs[n].im = -x.re; 75 | break; 76 | } 77 | } 78 | } 79 | void DVBS2::pl_scramble_dummy_symbols( int len ) 80 | { 81 | scmplx x; 82 | int p = 0; 83 | 84 | x = m_bpsk[0][0]; 85 | 86 | for( int n = 90; n < len; n++ ) 87 | { 88 | switch( m_cscram[p] ) 89 | { 90 | case 0: 91 | // Do nothing 92 | m_pl_dummy[n].re = x.re; 93 | m_pl_dummy[n].im = x.im; 94 | break; 95 | case 1: 96 | m_pl_dummy[n].re = -x.im; 97 | m_pl_dummy[n].im = x.re; 98 | break; 99 | case 2: 100 | m_pl_dummy[n].re = -x.re; 101 | m_pl_dummy[n].im = -x.im; 102 | break; 103 | case 3: 104 | m_pl_dummy[n].re = x.im; 105 | m_pl_dummy[n].im = -x.re; 106 | break; 107 | } 108 | p++; 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /libdvbmod/DVB-S2/dvbs2_tables.cpp: -------------------------------------------------------------------------------- 1 | #include "DVBS2.h" 2 | // 3 | // Modcod error correction 4 | // 5 | 6 | const unsigned long DVBS2::g[6]= 7 | { 8 | 0x55555555,0x33333333,0x0F0F0F0F,0x00FF00FF,0x0000FFFF,0xFFFFFFFF 9 | }; 10 | 11 | const int DVBS2::ph_scram_tab[64]= 12 | { 13 | 0,1,1,1,0,0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,0,0,1,1,1,1,0,0,1,0,0,1, 14 | 0,1,0,1,0,0,1,1,0,1,0,0,0,0,1,0,0,0,1,0,1,1,0,1,1,1,1,1,1,0,1,0 15 | }; 16 | const int DVBS2::ph_sync_seq[26]= 17 | { 18 | 0,1,1,0,0,0,1,1,0,1,0,0,1,0,1,1,1,0,1,0,0,0,0,0,1,0 19 | }; 20 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This is the interface module in and out of the dvb_t 3 | // encoder 4 | // 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | //#include 12 | //#include "dvb_gen.h" 13 | #include "../dvb.h" 14 | #include "dvb_t.h" 15 | 16 | //#include "dvb_capture_ctl.h" 17 | 18 | DVBTFormat m_format; 19 | double m_sample_rate; 20 | // 21 | // Called externally to send the next 22 | // transport frame. It encodes the frame 23 | // then calls the modulator if a complete frame is ready 24 | // 25 | /*void dvb_t_encode_and_modulate( uint8_t *tp, uint8_t *dibit ) 26 | { 27 | int len; 28 | len = dvb_encode_frame( tp, dibit ); 29 | dvb_t_enc_dibit( dibit, len ); 30 | } 31 | */ 32 | double dvb_t_get_sample_rate( void ) 33 | { 34 | double srate = 8000000.0/7.0; 35 | 36 | switch( m_format.chan ) 37 | { 38 | case CH_8M: 39 | srate = srate*8.0; 40 | break; 41 | case CH_7M: 42 | srate = srate*7.0; 43 | break; 44 | case CH_6M: 45 | srate = srate*6.0; 46 | break; 47 | case CH_4M: 48 | srate = srate*4.0*2.0; 49 | break; 50 | case CH_3M: 51 | srate = srate*3.0*2.0; 52 | break; 53 | case CH_2M: 54 | srate = srate*2.0*2.0; 55 | break; 56 | case CH_1M: 57 | srate = srate*1.0*2.0; 58 | break; 59 | case CH_500K: 60 | srate = srate*0.5*4.0; 61 | break; 62 | default: 63 | break; 64 | } 65 | return srate; 66 | } 67 | double dvb_t_get_symbol_rate( void ) 68 | { 69 | double symbol_len = 1;//default value 70 | double srate = dvb_t_get_sample_rate(); 71 | if( m_format.tm == TM_2K ) symbol_len = M2KS; 72 | if( m_format.tm == TM_8K ) symbol_len = M8KS; 73 | switch( m_format.gi ) 74 | { 75 | case GI_132: 76 | symbol_len += symbol_len/32; 77 | break; 78 | case GI_116: 79 | symbol_len += symbol_len/16; 80 | break; 81 | case GI_18: 82 | symbol_len += symbol_len/8; 83 | break; 84 | case GI_14: 85 | symbol_len += symbol_len/4; 86 | break; 87 | default: 88 | symbol_len += symbol_len/4; 89 | break; 90 | } 91 | if(( m_format.chan == CH_4M ) || 92 | ( m_format.chan == CH_3M ) || 93 | ( m_format.chan == CH_2M ) || 94 | ( m_format.chan == CH_1M ) ) 95 | { 96 | srate = srate/2; 97 | } 98 | if( m_format.chan == CH_500K) 99 | { 100 | srate = srate/4; 101 | } 102 | return srate/symbol_len; 103 | } 104 | // 105 | // Initialise the module 106 | // 107 | // 108 | void dvb_t_init( void ) 109 | { 110 | //sys_config info; 111 | // Encode the correct parameters 112 | //dvb_config_get( &info ); 113 | //FixMe Need to set parameters 114 | 115 | //m_format = info.dvbt_fmt; // <<<<<<<<<<<<<<<<<<<<<===================================== 116 | m_sample_rate = dvb_t_get_sample_rate(); 117 | build_tx_sym_tabs(); 118 | dvb_t_build_p_tables(); 119 | init_dvb_t_fft(); 120 | init_dvb_t_enc(); 121 | build_tp_block(); 122 | init_reference_frames(); 123 | dvb_t_modulate_init(); 124 | } 125 | // 126 | // Called when altering the DVB-T mode form the GUI 127 | // 128 | // This does not work yet. 129 | // 130 | void dvb_t_re_init( void ) 131 | { 132 | dvb_t_init(); 133 | } 134 | // 135 | // Returns FFT resources 136 | // 137 | void dvb_t_deinit( void ) 138 | { 139 | deinit_dvb_t_fft(); 140 | } 141 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t.h: -------------------------------------------------------------------------------- 1 | #ifndef __DVB_T_H__ 2 | #define __DVB_T_H__ 3 | 4 | #ifdef USE_AVFFT 5 | 6 | #define __STDC_CONSTANT_MACROS 7 | 8 | extern "C" { 9 | #include 10 | #include 11 | #include 12 | } 13 | #else 14 | #include "fftw3.h" 15 | #include "complex.h" 16 | #endif 17 | 18 | #include "../dvb.h" 19 | //#include "Sources/dvb_gen.h" 20 | 21 | #define SYMS_IN_FRAME 68 22 | 23 | #ifdef USE_AVFFT 24 | #define fft_complex FFTComplex 25 | #define FLOAT float 26 | #else 27 | #define fft_complex fftw_complex 28 | #define FLOAT double 29 | #endif 30 | 31 | // Minimum cell nr 32 | #define K2MIN 0 33 | #define K8MIN 0 34 | 35 | // Max cell nr 36 | #define K2MAX 1704 37 | #define K8MAX 6816 38 | #define SF_NR 4 39 | 40 | // Size of FFT 41 | #define M2KS 2048 42 | #define M4KS 4096 43 | #define M8KS 8192 44 | #define M16KS 16384 45 | 46 | // Number of data cells 47 | #define M2SI 1512 48 | #define M8SI 6048 49 | 50 | // FFT bin number to start at 51 | #define M8KSTART 688 52 | #define M2KSTART 172 53 | 54 | #define BIL 126 55 | #define M_QPSK 0 56 | #define M_QAM16 1 57 | #define M_QAM64 2 58 | 59 | #define BCH_POLY 0x4377 60 | //#define BCH_RPOLY 0x7761 61 | #define BCH_RPOLY 0x3761 62 | 63 | // Definition of mode, these correspond to the values in the TPS 64 | #define FN_1_SP 0 65 | #define FN_2_SP 1 66 | #define FN_3_SP 2 67 | #define FN_4_SP 3 68 | 69 | #define CO_QPSK 0 70 | #define CO_16QAM 1 71 | #define CO_64QAM 2 72 | 73 | #define SF_NH 0 74 | #define SF_A1 1 75 | #define SF_A2 2 76 | #define SF_A4 3 77 | 78 | #define CR_12 0 79 | #define CR_23 1 80 | #define CR_34 2 81 | #define CR_56 3 82 | #define CR_78 4 83 | 84 | #define GI_132 0 85 | #define GI_116 1 86 | #define GI_18 2 87 | #define GI_14 3 88 | 89 | #define TM_2K 0 90 | #define TM_8K 1 91 | 92 | #define CH_8M 0 93 | #define CH_7M 1 94 | #define CH_6M 2 95 | #define CH_4M 3 96 | #define CH_3M 4 97 | #define CH_2M 5 98 | #define CH_1M 6 99 | #define CH_500K 7 100 | 101 | typedef struct{ 102 | uint8_t co; 103 | uint8_t sf; 104 | uint8_t gi; 105 | uint8_t tm; 106 | uint8_t chan; 107 | int fec; 108 | }DVBTFormat; 109 | 110 | #define AVG_E8 (1.0/600.0) 111 | //#define AVG_E2 (1.0/1704.0) 112 | #define AVG_E2 (1.0/150.0) 113 | 114 | // Prototypes 115 | 116 | // dvb_t_tp.c 117 | void build_tp_block( void ); 118 | 119 | // dvb_t_ta.c 120 | void dvb_t_configure( DVBTFormat *p ); 121 | 122 | // dvb_t_sym.c 123 | void init_reference_frames( void ); 124 | void reference_symbol_reset( void ); 125 | int reference_symbol_seq_get( void ); 126 | int reference_symbol_seq_update( void ); 127 | 128 | //dvb_t_i.c 129 | void dvb_t_build_p_tables( void ); 130 | 131 | // dvb_t_enc.c 132 | void init_dvb_t_enc( void ); 133 | void dvb_t_enc_dibit( uint8_t *in, int length ); 134 | //void dvb_t_encode_and_modulate( uint8_t *in, uint8_t *dibit ); 135 | 136 | // dvb_t_mod.c 137 | void dvb_t_select_constellation_table( void ); 138 | void dvb_t_calculate_guard_period( void ); 139 | void dvb_t_modulate( uint8_t *syms ); 140 | void dvb_t_write_samples( short *s, int len ); 141 | void dvb_t_modulate_init( void ); 142 | 143 | // dvb_t_linux_fft.c 144 | void init_dvb_t_fft( void ); 145 | void deinit_dvb_t_fft( void ); 146 | void fft_2k_test( fft_complex *out ); 147 | void dvbt_fft_modulate( fft_complex *in, int guard ); 148 | 149 | // dvb_t.cpp 150 | void dvb_t_init( void ); 151 | void dvb_t_deinit( void ); 152 | void dvb_t_re_init( void ); 153 | double dvb_t_get_sample_rate( void ); 154 | double dvb_t_get_symbol_rate( void ); 155 | 156 | // dvb_t_qam_tab.cpp 157 | void build_tx_sym_tabs( void ); 158 | 159 | // Video bitrate 160 | int dvb_t_raw_bitrate(void); 161 | 162 | // dvb_t_lpf.cpp 163 | fft_complex *dvbt_filter( fft_complex *in, int length ); 164 | 165 | #endif 166 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_bits.cpp: -------------------------------------------------------------------------------- 1 | //#include "dvb_gen.h" 2 | #include "dvb_t.h" 3 | //#include "dvb_config.h" 4 | 5 | extern DVBTFormat m_format; 6 | 7 | // 7 MHz Channel 8 | const int dvb_t_bitrates[60]= 9 | { 10 | 4354000, 4838000, 5123000, 5278000, 11 | 5806000, 6451000, 6830000, 7037000, 12 | 6532000, 7257000, 7684000, 7917000, 13 | 7257000, 8064000, 8538000, 8797000, 14 | 7620000, 8467000, 8965000, 9237000, 15 | 16 | 8709000, 9676000, 10246000, 10556000, 17 | 11612000, 12902000, 13661000, 14075000, 18 | 13063000, 14515000, 15369000, 15834000, 19 | 14515000, 16127000, 17076000, 17594000, 20 | 15240000, 16934000, 17930000, 18473000, 21 | 22 | 13063000, 14515000, 15369000, 15834000, 23 | 17418000, 19353000, 20491000, 21112000, 24 | 19595000, 21772000, 23053000, 23751000, 25 | 21772000, 24191000, 25614000, 26390000, 26 | 22861000, 25401000, 26895000, 27710000 27 | }; 28 | // 29 | // Return the channel usuable bit rate in bps 30 | // 31 | int dvb_t_raw_bitrate(void) 32 | { 33 | int index,rate; 34 | 35 | if( m_format.co == CO_QPSK ) index = 0; 36 | if( m_format.co == CO_16QAM ) index = 20; 37 | if( m_format.co == CO_64QAM ) index = 40; 38 | 39 | if( m_format.fec == FEC_12 ) index += 0; 40 | if( m_format.fec == FEC_23 ) index += 4; 41 | if( m_format.fec == FEC_34 ) index += 8; 42 | if( m_format.fec == FEC_56 ) index += 12; 43 | if( m_format.fec == FEC_78 ) index += 16; 44 | 45 | if( m_format.gi == GI_14 ) index += 0; 46 | if( m_format.gi == GI_18 ) index += 1; 47 | if( m_format.gi == GI_116 ) index += 2; 48 | if( m_format.gi == GI_132 ) index += 3; 49 | 50 | rate = 0; 51 | if( m_format.chan == CH_8M ) rate = (dvb_t_bitrates[index]*8)/7; 52 | if( m_format.chan == CH_7M ) rate = dvb_t_bitrates[index]; 53 | if( m_format.chan == CH_6M ) rate = (dvb_t_bitrates[index]*6)/7; 54 | if( m_format.chan == CH_4M ) rate = (dvb_t_bitrates[index]*8)/14; 55 | if( m_format.chan == CH_3M ) rate = (dvb_t_bitrates[index]*6)/14; 56 | if( m_format.chan == CH_2M ) rate = (dvb_t_bitrates[index]*8)/28; 57 | if( m_format.chan == CH_1M ) rate = (dvb_t_bitrates[index]*8)/56; 58 | if( m_format.chan == CH_500K ) rate = (dvb_t_bitrates[index]*8)/112; 59 | 60 | return( rate ); 61 | } 62 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_enc.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module encodes and sends the DVB-T signal. 3 | // 4 | // 5 | #include 6 | #include "dvb_t.h" 7 | 8 | extern DVBTFormat m_format; 9 | 10 | // Bit Interleaver lookup table 11 | extern int gb_bi[6][BIL]; 12 | 13 | // Symbol interleaver arrays 14 | extern int gb_h2k[M2SI]; 15 | extern int gb_h8k[M8SI]; 16 | 17 | // Symbol interleaver array 18 | static uint8_t m_sio[M8SI]; 19 | static uint8_t m_sii[M8SI]; 20 | static int m_si_x; 21 | static int m_count; 22 | 23 | // Bit interleaver array 24 | static uint8_t m_bi[6][BIL]; 25 | static int m_i_x; 26 | 27 | // 28 | // Symbol interleaver called once per symbol 29 | // 30 | void symbol_interleave( void ) 31 | { 32 | int i; 33 | int sn = reference_symbol_seq_get(); 34 | 35 | if( m_format.tm == TM_2K ) 36 | { 37 | if((sn&1) == 0 ) 38 | { 39 | // Even symbols 40 | for( i = 0; i < M2SI; i++ ) 41 | { 42 | m_sio[gb_h2k[i]] = m_sii[i]; 43 | } 44 | } 45 | else 46 | { 47 | // Odd symbols 48 | for( i = 0; i < M2SI; i++ ) 49 | { 50 | m_sio[i] = m_sii[gb_h2k[i]]; 51 | } 52 | } 53 | } 54 | 55 | if( m_format.tm == TM_8K ) 56 | { 57 | if((sn&1) == 0 ) 58 | { 59 | // Even symbols 60 | for( i = 0; i < M8SI; i++ ) 61 | { 62 | m_sio[gb_h8k[i]] = m_sii[i]; 63 | } 64 | } 65 | else 66 | { 67 | // Odd symbols 68 | for( i = 0; i < M8SI; i++ ) 69 | { 70 | m_sio[i] = m_sii[gb_h8k[i]]; 71 | } 72 | } 73 | } 74 | 75 | // Call the modulator as a complete symbol is ready 76 | dvb_t_modulate( m_sio ); 77 | m_si_x = 0;//reset the symbol interleaver input counter 78 | } 79 | // 80 | // Input array, output array, bit interleave lookup table 81 | // 82 | void inline bit_interleave( uint8_t *in, uint8_t *out, int *tab ) 83 | { 84 | int i; 85 | for( i = 0; i < BIL; i++ ) 86 | { 87 | out[i] = in[tab[i]]; 88 | } 89 | } 90 | // 91 | // Done one full bit interleaver at a time (126 bits) 92 | // 93 | void qpsk_bit_interleave( void ) 94 | { 95 | int i; 96 | uint8_t bi[2][BIL]; 97 | bit_interleave( m_bi[0], bi[0], gb_bi[0] ); 98 | bit_interleave( m_bi[1], bi[1], gb_bi[1] ); 99 | // Pack the symbols 100 | for( i = 0; i < BIL; i++ ) 101 | { 102 | m_sii[m_si_x] = bi[0][i]<<1; 103 | m_sii[m_si_x] |= bi[1][i]; 104 | m_si_x++; 105 | } 106 | if((m_format.tm == TM_2K)&&(m_si_x==M2SI)) symbol_interleave(); 107 | if((m_format.tm == TM_8K)&&(m_si_x==M8SI)) symbol_interleave(); 108 | } 109 | void qam16_bit_interleave( void ) 110 | { 111 | int i; 112 | uint8_t bi[4][BIL]; 113 | bit_interleave( m_bi[0], bi[0], gb_bi[0] ); 114 | bit_interleave( m_bi[1], bi[1], gb_bi[1] ); 115 | bit_interleave( m_bi[2], bi[2], gb_bi[2] ); 116 | bit_interleave( m_bi[3], bi[3], gb_bi[3] ); 117 | // Pack the symbols 118 | for( i = 0; i < BIL; i++ ) 119 | { 120 | m_sii[m_si_x] = bi[0][i]<<3; 121 | m_sii[m_si_x] |= bi[1][i]<<2; 122 | m_sii[m_si_x] |= bi[2][i]<<1; 123 | m_sii[m_si_x] |= bi[3][i]; 124 | m_si_x++; 125 | } 126 | if((m_format.tm == TM_2K)&&(m_si_x==M2SI)) symbol_interleave(); 127 | if((m_format.tm == TM_8K)&&(m_si_x==M8SI)) symbol_interleave(); 128 | } 129 | void qam64_bit_interleave( void ) 130 | { 131 | int i; 132 | uint8_t bi[6][BIL]; 133 | bit_interleave( m_bi[0], bi[0], gb_bi[0] ); 134 | bit_interleave( m_bi[1], bi[1], gb_bi[1] ); 135 | bit_interleave( m_bi[2], bi[2], gb_bi[2] ); 136 | bit_interleave( m_bi[3], bi[3], gb_bi[3] ); 137 | bit_interleave( m_bi[4], bi[4], gb_bi[4] ); 138 | bit_interleave( m_bi[5], bi[5], gb_bi[5] ); 139 | 140 | // Pack the symbols 141 | for( i = 0; i < BIL; i++ ) 142 | { 143 | m_sii[m_si_x] = bi[0][i]<<5; 144 | m_sii[m_si_x] |= bi[1][i]<<4; 145 | m_sii[m_si_x] |= bi[2][i]<<3; 146 | m_sii[m_si_x] |= bi[3][i]<<2; 147 | m_sii[m_si_x] |= bi[4][i]<<1; 148 | m_sii[m_si_x] |= bi[5][i]; 149 | m_si_x++; 150 | } 151 | if((m_format.tm == TM_2K)&&(m_si_x==M2SI)) symbol_interleave(); 152 | if((m_format.tm == TM_8K)&&(m_si_x==M8SI)) symbol_interleave(); 153 | } 154 | // 155 | // This currently only supports non H mode 156 | // Input is a dibit array 157 | // 158 | void dvb_t_enc_dibit( uint8_t *in, int length ) 159 | { 160 | int i; 161 | // printf("Len %d\n",length); 162 | 163 | // Two bits per symbol 164 | 165 | if( m_format.co == CO_QPSK ) 166 | { 167 | for( i = 0; i < length; i++ ) 168 | { 169 | m_bi[0][m_i_x] = in[i]&1; 170 | m_bi[1][m_i_x] = in[i]>>1; 171 | m_i_x++; 172 | if( m_i_x == BIL ) 173 | { 174 | m_i_x = 0; 175 | qpsk_bit_interleave(); 176 | } 177 | } 178 | } 179 | 180 | // 4 bits per symbol 181 | 182 | if( m_format.co == CO_16QAM ) 183 | { 184 | for( i = 0; i < length; i++ ) 185 | { 186 | switch(m_count) 187 | { 188 | case 0: 189 | m_bi[0][m_i_x] = in[i]&1; 190 | m_bi[2][m_i_x] = in[i]>>1; 191 | break; 192 | case 1: 193 | m_bi[1][m_i_x] = in[i]&1; 194 | m_bi[3][m_i_x] = in[i]>>1; 195 | m_i_x++; 196 | if( m_i_x == BIL ) 197 | { 198 | m_i_x = 0; 199 | qam16_bit_interleave(); 200 | } 201 | break; 202 | default: 203 | break; 204 | } 205 | m_count = (m_count + 1)%2; 206 | } 207 | } 208 | 209 | // 6 bits per symbol 210 | 211 | if( m_format.co == CO_64QAM ) 212 | { 213 | for( i = 0; i < length; i++ ) 214 | { 215 | switch(m_count) 216 | { 217 | case 0: 218 | m_bi[0][m_i_x] = in[i]&1; 219 | m_bi[2][m_i_x] = in[i]>>1; 220 | break; 221 | case 1: 222 | m_bi[4][m_i_x] = in[i]&1; 223 | m_bi[1][m_i_x] = in[i]>>1; 224 | break; 225 | case 2: 226 | m_bi[3][m_i_x] = in[i]&1; 227 | m_bi[5][m_i_x] = in[i]>>1; 228 | m_i_x++; 229 | if( m_i_x == BIL ) 230 | { 231 | m_i_x = 0; 232 | qam64_bit_interleave(); 233 | } 234 | break; 235 | default: 236 | break; 237 | } 238 | m_count = (m_count + 1)%3; 239 | } 240 | } 241 | } 242 | void init_dvb_t_enc( void ) 243 | { 244 | m_si_x = 0; 245 | m_i_x = 0; 246 | m_count = 0; 247 | } 248 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_i.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | //#include "dvb_gen.h" 3 | #include "dvb_t.h" 4 | 5 | // Symbol interleaver arrays 6 | int gb_h2k[M2SI]; 7 | int gb_h8k[M8SI]; 8 | 9 | // Bit interleaver arrays 10 | int gb_bi[6][BIL]; 11 | 12 | // PRBS seq 13 | int m_sync_prbs[M8KS]; 14 | 15 | int permutate_bits_8k( int in ) 16 | { 17 | int out = 0; 18 | out |= in&0x001 ? (1<<7) : 0; 19 | out |= in&0x002 ? (1<<1) : 0; 20 | out |= in&0x004 ? (1<<4) : 0; 21 | out |= in&0x008 ? (1<<2) : 0; 22 | out |= in&0x010 ? (1<<9) : 0; 23 | out |= in&0x020 ? (1<<6) : 0; 24 | out |= in&0x040 ? (1<<8) : 0; 25 | out |= in&0x080 ? (1<<10): 0; 26 | out |= in&0x100 ? (1<<0) : 0; 27 | out |= in&0x200 ? (1<<3) : 0; 28 | out |= in&0x400 ? (1<<11): 0; 29 | out |= in&0x800 ? (1<<5) : 0; 30 | return out; 31 | } 32 | int permutate_bits_2k( int in ) 33 | { 34 | int out = 0; 35 | out |= in&0x001 ? (1<<4) : 0; 36 | out |= in&0x002 ? (1<<3) : 0; 37 | out |= in&0x004 ? (1<<9) : 0; 38 | out |= in&0x008 ? (1<<6) : 0; 39 | out |= in&0x010 ? (1<<2) : 0; 40 | out |= in&0x020 ? (1<<8) : 0; 41 | out |= in&0x040 ? (1<<1) : 0; 42 | out |= in&0x080 ? (1<<5) : 0; 43 | out |= in&0x100 ? (1<<7) : 0; 44 | out |= in&0x200 ? (1<<0) : 0; 45 | return out; 46 | } 47 | // 48 | // Build the symbol permutation array 49 | // 50 | // Called only once 51 | void build_h_2k( void ) 52 | { 53 | int i,b9,b0,b3,q; 54 | int sr; 55 | int tmp[M2KS]; 56 | 57 | // Create R' 58 | tmp[0] = 0; 59 | tmp[1] = 0; 60 | tmp[2] = 1; 61 | sr = 1; 62 | 63 | for( i = 3; i < M2KS; i++ ) 64 | { 65 | b0 = sr&0x01; 66 | b3 = (sr>>3)&0x01; 67 | b9 = b0^b3?0x200:0; 68 | sr = (sr>>1); 69 | sr |= b9; 70 | tmp[i] = sr; 71 | } 72 | // Create R 73 | for( i = 0; i < M2KS; i++ ) 74 | { 75 | tmp[i] = ((i%2)<<10) + permutate_bits_2k( tmp[i] ); 76 | } 77 | // Build iterpolation lookup table 78 | 79 | for( i = 0, q = 0; i < M2KS; i++ ) 80 | { 81 | if( tmp[i] < M2SI) 82 | { 83 | gb_h2k[q] = tmp[i]; 84 | q++; 85 | } 86 | } 87 | } 88 | // 89 | // Build the symbol permutation array 90 | // 91 | // Called only once 92 | void build_h_8k( void ) 93 | { 94 | int i,b11,b0,b1,b4,b6,q; 95 | int sr; 96 | int tmp[M8KS]; 97 | 98 | // Create R' 99 | tmp[0] = 0; 100 | tmp[1] = 0; 101 | tmp[2] = 1; 102 | sr = 1; 103 | 104 | for( i = 3; i < M8KS; i++ ) 105 | { 106 | b0 = sr&0x01; 107 | b1 = (sr>>1)&0x01; 108 | b4 = (sr>>4)&0x01; 109 | b6 = (sr>>6)&0x01; 110 | b11 = b0^b1^b4^b6 ?0x800:0; 111 | sr = (sr>>1); 112 | sr |= b11; 113 | tmp[i] = sr; 114 | } 115 | // Create R 116 | for( i = 0; i < M8KS; i++ ) 117 | { 118 | tmp[i] = ((i%2)<<12) + permutate_bits_8k( tmp[i] ); 119 | } 120 | // Build iterpolation lookup table 121 | 122 | for( i = 0, q = 0; i < M8KS; i++ ) 123 | { 124 | if( tmp[i] < M8SI) 125 | { 126 | gb_h8k[q] = tmp[i]; 127 | q++; 128 | } 129 | } 130 | } 131 | // Called only once 132 | void build_bit( void ) 133 | { 134 | int w; 135 | for( w = 0; w < BIL; w++ ) 136 | { 137 | gb_bi[0][w] = w; 138 | gb_bi[1][w] = (w+63)%BIL; 139 | gb_bi[2][w] = (w+105)%BIL; 140 | gb_bi[3][w] = (w+42)%BIL; 141 | gb_bi[4][w] = (w+21)%BIL; 142 | gb_bi[5][w] = (w+84)%BIL; 143 | } 144 | } 145 | void build_prbs_seq( void ) 146 | { 147 | int i; 148 | int s = 0x7FF; 149 | 150 | for( i = 0; i < M8KS; i++ ) 151 | { 152 | m_sync_prbs[i] = s&1; 153 | s |= (s&1)^((s>>2)&1) ? 0x800 : 0; 154 | s >>= 1; 155 | } 156 | } 157 | void dvb_t_build_p_tables( void ) 158 | { 159 | build_h_8k(); 160 | build_h_2k(); 161 | build_bit(); 162 | build_prbs_seq(); 163 | } 164 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_linux_fft.cpp: -------------------------------------------------------------------------------- 1 | #include "math.h" 2 | #include 3 | #include 4 | //#include "an_capture.h" 5 | #include "../dvb.h" 6 | #include "dvb_t.h" 7 | 8 | #ifndef M_PI 9 | #define M_PI 3.14159265358979323846264338327 10 | #endif 11 | 12 | extern DVBTFormat m_format; 13 | extern double m_sample_rate; 14 | 15 | #ifdef USE_AVFFT 16 | static FFTContext *m_avfft_2k_context; 17 | static FFTContext *m_avfft_4k_context; 18 | static FFTContext *m_avfft_8k_context; 19 | static FFTContext *m_avfft_16k_context; 20 | static fft_complex *m_fft_in; 21 | static fft_complex *m_fft_out; 22 | #else 23 | static fftw_plan m_fftw_2k_plan; 24 | static fftw_plan m_fftw_4k_plan; 25 | static fftw_plan m_fftw_8k_plan; 26 | static fftw_plan m_fftw_16k_plan; 27 | static fft_complex *m_fft_in; 28 | static fft_complex *m_fft_out; 29 | #endif 30 | // 31 | // Taper table 32 | // 33 | double m_taper[M16KS+(M16KS/4)]; 34 | 35 | void create_taper_table(int N, int IR, int GI) 36 | { 37 | N = N*IR;// FFT size 38 | int CP = N/GI;//Cyclic prefix 39 | int ALPHA = 32;// Rx Alpha 40 | int NT = 2*(N/(ALPHA*2));//Taper length 41 | int idx = 0; 42 | int n = -NT/2; 43 | 44 | for( int i = 0; i < NT; i++ ){ 45 | m_taper[idx++] = 0.5*(1.0+cos((M_PI*n)/NT)); 46 | n++; 47 | } 48 | for( int i = 0; i < (N+CP)-(2*NT); i++ ){ 49 | m_taper[idx++] = 1.0; 50 | } 51 | for( int i = 0; i < NT; i++ ){ 52 | m_taper[idx++] = m_taper[i]; 53 | } 54 | } 55 | 56 | // sinc correction coefficients 57 | int m_N; 58 | int m_IR; 59 | double m_c[M16KS]; 60 | 61 | void create_correction_table( int N, int IR ) 62 | { 63 | double x,sinc; 64 | double f = 0.0; 65 | double fsr = m_sample_rate; 66 | double fstep = fsr / (N*IR); 67 | 68 | for( int i = 0; i < N/2; i++ ) 69 | { 70 | if( f == 0 ) 71 | sinc = 1.0; 72 | else{ 73 | x = M_PI*f/fsr; 74 | sinc = sin(x)/x; 75 | } 76 | m_c[i+(N/2)] = 1.0/sinc; 77 | m_c[(N/2)-i-1] = 1.0/sinc; 78 | f += fstep; 79 | } 80 | } 81 | 82 | static void fft_2k( fft_complex *in, fft_complex *out ) 83 | { 84 | 85 | // Copy the data into the correct bins 86 | // memcpy(&m_fft_in[M2KS/2], &in[0], sizeof(fft_complex)*M2KS/2); 87 | // memcpy(&m_fft_in[0], &in[M2KS/2], sizeof(fft_complex)*M2KS/2); 88 | 89 | int i,m; 90 | m = (M2KS/2); 91 | for( i = 0; i < (M2KS); i++ ) 92 | { 93 | m_fft_in[m][0] = in[i][0]*m_c[i]; 94 | m_fft_in[m][1] = in[i][1]*m_c[i]; 95 | m = (m+1)%(M2KS); 96 | } 97 | 98 | #ifdef USE_AVFFT 99 | av_fft_permute( m_avfft_2k_context, m_fft_in ); 100 | av_fft_calc( m_avfft_2k_context, m_fft_in ); 101 | #else 102 | fftw_execute_dft( m_fftw_2k_plan, m_fft_in, out ); 103 | #endif 104 | return; 105 | } 106 | static void fft_4k( fft_complex *in, fft_complex *out ) 107 | { 108 | // Zero the unused parts of the array 109 | memset(&m_fft_in[M4KS/4],0,sizeof(fft_complex)*M4KS/2); 110 | // Copy the data into the correct bins 111 | //memcpy(&m_fft_in[M4KS*3/4], &in[0], sizeof(fft_complex)*M2KS/2); 112 | //memcpy(&m_fft_in[0], &in[M2KS/2], sizeof(fft_complex)*M2KS/2); 113 | 114 | int i,m; 115 | m = (M4KS/2)+(M4KS/4); 116 | for( i = 0; i < (M2KS); i++ ) 117 | { 118 | m_fft_in[m][0] = in[i][0]*m_c[i]; 119 | m_fft_in[m][1] = in[i][1]*m_c[i]; 120 | m = (m+1)%(M2KS*2); 121 | } 122 | 123 | #ifdef USE_AVFFT 124 | av_fft_permute( m_avfft_4k_context, m_fft_in ); 125 | av_fft_calc( m_avfft_4k_context, m_fft_in ); 126 | #else 127 | fftw_execute_dft( m_fftw_4k_plan, m_fft_in, out ); 128 | #endif 129 | return; 130 | } 131 | // 132 | // Interpolate by 4 using an 8K FFT 133 | // 134 | static void fft_2k_nb( fft_complex *in, fft_complex *out ) 135 | { 136 | // Zero the unused parts of the array 137 | memset(&m_fft_in[M8KS/8],0,sizeof(fft_complex)*M8KS*6/8); 138 | // Copy the data into the correct bins 139 | // Copy the data into the correct bins 140 | // memcpy(&m_fft_in[M8KS*7/8], &in[0], sizeof(fft_complex)*M2KS/2); 141 | // memcpy(&m_fft_in[0], &in[M2KS/2], sizeof(fft_complex)*M2KS/2); 142 | 143 | int i,m; 144 | m = (M8KS)-(M8KS/8); 145 | for( i = 0; i < (M2KS); i++ ) 146 | { 147 | m_fft_in[m][0] = in[i][0]*m_c[i]; 148 | m_fft_in[m][1] = in[i][1]*m_c[i]; 149 | m = (m+1)%M2KS; 150 | } 151 | 152 | #ifdef USE_AVFFT 153 | av_fft_permute( m_avfft_8k_context, m_fft_in ); 154 | av_fft_calc( m_avfft_8k_context, m_fft_in ); 155 | #else 156 | fftw_execute_dft( m_fftw_8k_plan, m_fft_in, out ); 157 | #endif 158 | } 159 | static void fft_8k( fft_complex *in, fft_complex *out ) 160 | { 161 | // Copy the data into the correct bins 162 | // memcpy(&m_fft_in[M8KS/2], &in[0], sizeof(fft_complex)*M8KS/2); 163 | // memcpy(&m_fft_in[0], &in[M8KS/2], sizeof(fft_complex)*M8KS/2); 164 | 165 | int i,m; 166 | m = (M8KS/2); 167 | for( i = 0; i < (M8KS); i++ ) 168 | { 169 | m_fft_in[m][0] = in[i][0]*m_c[i]; 170 | m_fft_in[m][1] = in[i][1]*m_c[i]; 171 | m = (m+1)%M8KS; 172 | } 173 | 174 | #ifdef USE_AVFFT 175 | av_fft_permute( m_avfft_8k_context, m_fft_in ); 176 | av_fft_calc( m_avfft_8k_context, m_fft_in ); 177 | #else 178 | fftw_execute_dft( m_fftw_8k_plan, m_fft_in, out ); 179 | #endif 180 | } 181 | static void fft_16k( fft_complex *in, fft_complex *out ) 182 | { 183 | // Zero the unused parts of the array 184 | memset(&m_fft_in[M8KS/2],0,sizeof(fft_complex)*M8KS); 185 | // Copy the data into the correct bins 186 | // memcpy(&m_fft_in[M8KS*3/2], &in[0], sizeof(fft_complex)*M8KS/2); 187 | // memcpy(&m_fft_in[0], &in[M8KS/2], sizeof(fft_complex)*M8KS/2); 188 | 189 | int i,m; 190 | m = (M8KS)+(M8KS/2); 191 | for( i = 0; i < (M8KS); i++ ) 192 | { 193 | m_fft_in[m][0] = in[i][0]*m_c[i]; 194 | m_fft_in[m][1] = in[i][1]*m_c[i]; 195 | m = (m+1)%(M8KS*2); 196 | } 197 | 198 | #ifdef USE_AVFFT 199 | av_fft_permute( m_avfft_16k_context, m_fft_in ); 200 | av_fft_calc( m_avfft_16k_context, m_fft_in ); 201 | #else 202 | fftw_execute_dft( m_fftw_16k_plan, m_fft_in, out ); 203 | #endif 204 | } 205 | // 206 | // Chooses the corect FFT, adds the guard interval and sends to the modulator 207 | // 208 | void dvbt_fft_modulate( fft_complex *in, int guard ) 209 | { 210 | int size = 0; 211 | fft_complex *out; 212 | 213 | if( m_format.tm == TM_2K) 214 | { 215 | switch( m_format.chan ) 216 | { 217 | case CH_8M: 218 | case CH_7M: 219 | case CH_6M: 220 | fft_2k( in, m_fft_out ); 221 | size = M2KS; 222 | break; 223 | case CH_4M: 224 | case CH_3M: 225 | case CH_2M: 226 | case CH_1M: 227 | fft_4k( in, m_fft_out ); 228 | size = M4KS; 229 | guard = guard*2; 230 | break; 231 | case CH_500K: 232 | fft_2k_nb( in, m_fft_out ); 233 | size = M8KS; 234 | guard = guard*4; 235 | #ifdef USE_AVFFT 236 | // Guard 237 | dvbt_clip( &m_fft_in, size ); 238 | dvbt_modulate( &m_fft_in[size-guard], guard); 239 | // Data 240 | dvbt_modulate( m_fft_in, size ); 241 | #endif 242 | #ifdef FIXME 243 | // Clip the FFT outputs 244 | dvbt_clip( m_fft_out, size ); 245 | dvbt_modulate( &m_fft_in[size-guard], guard); 246 | // Guard 247 | //out = dvbt_filter( &m_fft_out[size-guard], guard ); 248 | //dvbt_modulate( out, guard); 249 | // Data 250 | //out = dvbt_filter( m_fft_out, size ); 251 | //dvbt_modulate( out, size ); 252 | dvbt_modulate( m_fft_in, size ); 253 | #endif 254 | return; 255 | break; 256 | } 257 | } 258 | if( m_format.tm == TM_8K) 259 | { 260 | switch( m_format.chan ) 261 | { 262 | case CH_8M: 263 | case CH_7M: 264 | case CH_6M: 265 | fft_8k( in, m_fft_out ); 266 | size = M8KS; 267 | break; 268 | case CH_4M: 269 | case CH_3M: 270 | case CH_2M: 271 | case CH_1M: 272 | // case CH_500K: 273 | fft_16k( in, m_fft_out ); 274 | size = M16KS; 275 | guard = guard*2; 276 | break; 277 | } 278 | } 279 | // fft_complex *out; 280 | #ifdef USE_AVFFT 281 | // Guard 282 | dvbt_clip( &m_fft_in, size ); 283 | dvbt_modulate( &m_fft_in[size-guard], guard); 284 | // Data 285 | dvbt_modulate( m_fft_in, size ); 286 | #endif 287 | #ifdef FIXME 288 | // Clip the FFT outputs 289 | dvbt_clip( m_fft_out, size ); 290 | // Guard 291 | //out = dvbt_filter( &m_fft_out[size-guard], guard ); 292 | //dvbt_modulate( out, guard); 293 | 294 | //dvbt_modulate( &m_fft_out[size-guard], guard); 295 | dvbt_modulate( &m_fft_out[size-guard], &m_taper[0], guard); 296 | // Data 297 | //out = dvbt_filter( m_fft_out, size ); 298 | //dvbt_modulate( out, size ); 299 | //dvbt_modulate( m_fft_out, size ); 300 | dvbt_modulate( m_fft_out, &m_taper[guard], size ); 301 | #endif 302 | } 303 | /* 304 | void fft_2k_test( fftw_complex *out ) 305 | { 306 | memset(fftw_in, 0, sizeof(fftw_complex)*M2KS); 307 | int m = (M2KS/2)+32;//1704; 308 | fftw_in[m][0] = 0.7; 309 | 310 | fftw_one( m_fftw_2k_plan, fftw_in, out ); 311 | return; 312 | } 313 | */ 314 | void init_dvb_t_fft( void ) 315 | { 316 | // 317 | // Plans 318 | // 319 | #ifdef USE_AVFFT 320 | m_avfft_2k_context = av_fft_init (11, 1); 321 | m_avfft_4k_context = av_fft_init (12, 1); 322 | m_avfft_8k_context = av_fft_init (13, 1); 323 | m_avfft_16k_context = av_fft_init (14, 1); 324 | m_fft_in = (fft_complex*)av_malloc(sizeof(fft_complex)*M16KS); 325 | m_fft_out = (fft_complex*)av_malloc(sizeof(fft_complex)*M16KS); 326 | #else 327 | 328 | FILE *fp; 329 | m_fft_in = (fft_complex*)fftw_malloc(sizeof(fft_complex)*M16KS); 330 | m_fft_out = (fft_complex*)fftw_malloc(sizeof(fft_complex)*M16KS); 331 | if((fp=fopen("fftw_wisdom","r"))!=NULL) 332 | { 333 | fftw_import_wisdom_from_file(fp); 334 | 335 | m_fftw_2k_plan = fftw_plan_dft_1d(M2KS, m_fft_in, m_fft_out, FFTW_BACKWARD,0); 336 | m_fftw_4k_plan = fftw_plan_dft_1d(M4KS, m_fft_in, m_fft_out, FFTW_BACKWARD, 0); 337 | m_fftw_8k_plan = fftw_plan_dft_1d(M8KS, m_fft_in, m_fft_out, FFTW_BACKWARD, 0); 338 | m_fftw_16k_plan = fftw_plan_dft_1d(M16KS, m_fft_in, m_fft_out, FFTW_BACKWARD, 0); 339 | fftw_import_wisdom_from_file(fp); 340 | } 341 | else 342 | { 343 | 344 | if((fp=fopen("fftw_wisdom","w"))!=NULL) 345 | { 346 | m_fftw_2k_plan = fftw_plan_dft_1d(M2KS, m_fft_in, m_fft_out, FFTW_BACKWARD, FFTW_MEASURE ); 347 | m_fftw_4k_plan = fftw_plan_dft_1d(M4KS, m_fft_in, m_fft_out, FFTW_BACKWARD, FFTW_MEASURE ); 348 | m_fftw_8k_plan = fftw_plan_dft_1d(M8KS, m_fft_in, m_fft_out, FFTW_BACKWARD, FFTW_MEASURE ); 349 | m_fftw_16k_plan = fftw_plan_dft_1d(M16KS, m_fft_in, m_fft_out, FFTW_BACKWARD, FFTW_MEASURE); 350 | if(fp!=NULL) fftw_export_wisdom_to_file(fp); 351 | } 352 | } 353 | 354 | #endif 355 | if( m_format.tm == TM_2K) 356 | { 357 | m_N = M2KS; 358 | switch( m_format.chan ) 359 | { 360 | case CH_8M: 361 | case CH_7M: 362 | case CH_6M: 363 | m_IR = 1; 364 | break; 365 | case CH_4M: 366 | case CH_3M: 367 | case CH_2M: 368 | case CH_1M: 369 | m_IR = 2; 370 | break; 371 | case CH_500K: 372 | m_IR = 4; 373 | break; 374 | } 375 | } 376 | if( m_format.tm == TM_8K) 377 | { 378 | m_N = M8KS; 379 | switch( m_format.chan ) 380 | { 381 | case CH_8M: 382 | case CH_7M: 383 | case CH_6M: 384 | m_IR = 1; 385 | break; 386 | case CH_4M: 387 | case CH_3M: 388 | case CH_2M: 389 | case CH_1M: 390 | m_IR = 2; 391 | break; 392 | } 393 | } 394 | int GI; 395 | switch(m_format.gi) 396 | { 397 | case GI_132: 398 | GI = 32; 399 | break; 400 | case GI_116: 401 | GI = 16; 402 | break; 403 | case GI_18: 404 | GI = 8; 405 | break; 406 | case GI_14: 407 | GI = 4; 408 | break; 409 | default: 410 | GI = 4; 411 | break; 412 | } 413 | 414 | create_correction_table( m_N, m_IR ); 415 | create_taper_table(m_N, m_IR, GI ); 416 | } 417 | void deinit_dvb_t_fft( void ) 418 | { 419 | #ifdef USE_AVFFT 420 | av_free(m_fft_in); 421 | av_free(m_fft_out); 422 | #else 423 | fftw_free(m_fft_in); 424 | fftw_free(m_fft_out); 425 | #endif 426 | } 427 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_lpf.cpp: -------------------------------------------------------------------------------- 1 | #include "../dvb.h" 2 | #include "dvb_t.h" 3 | 4 | // This modules is an LPF filter used for filtering the shoulders and aliases 5 | // on the ouput of the DVB-T iFFT 6 | // It operates in place 7 | // 8 | /* 9 | 10 | FIR filter designed with 11 | http://t-filter.appspot.com 12 | 13 | sampling frequency: 1000000 Hz 14 | 15 | * 0 Hz - 108000 Hz 16 | gain = 1 17 | desired ripple = 0.1 dB 18 | actual ripple = 0.3163245849364087 dB 19 | 20 | * 125000 Hz - 500000 Hz 21 | gain = 0 22 | desired attenuation = -30 dB 23 | actual attenuation = -17.351411726038933 dB 24 | 25 | */ 26 | 27 | #define FILTER_TAP_NUM 63 28 | 29 | static double filter_taps[FILTER_TAP_NUM] = { 30 | 0.01564319265083877, 31 | -0.05360372433912335, 32 | 0.008823966495059024, 33 | 0.01946696271674653, 34 | 0.014144626255836222, 35 | 0.004361238484562726, 36 | -0.005195423651821919, 37 | -0.011502589504731202, 38 | -0.012265050466923388, 39 | -0.007043621874215022, 40 | 0.0020889937904723698, 41 | 0.010969950321719045, 42 | 0.014955015997906912, 43 | 0.011280887944933924, 44 | 0.0008716627692732737, 45 | -0.011560064444749683, 46 | -0.019385421771133744, 47 | -0.017467384086196223, 48 | -0.005266970802671308, 49 | 0.012249886250828589, 50 | 0.026253392081978875, 51 | 0.027933912094048476, 52 | 0.01345208497392874, 53 | -0.012893898586358688, 54 | -0.039351373824861875, 55 | -0.05065241375456205, 56 | -0.034240265488211456, 57 | 0.013331179663418256, 58 | 0.0835727661521914, 59 | 0.15836967807309296, 60 | 0.21526028205130704, 61 | 0.2365899530831242, 62 | 0.21526028205130704, 63 | 0.15836967807309296, 64 | 0.0835727661521914, 65 | 0.013331179663418256, 66 | -0.034240265488211456, 67 | -0.05065241375456205, 68 | -0.039351373824861875, 69 | -0.012893898586358688, 70 | 0.01345208497392874, 71 | 0.027933912094048476, 72 | 0.026253392081978875, 73 | 0.012249886250828589, 74 | -0.005266970802671308, 75 | -0.017467384086196223, 76 | -0.019385421771133744, 77 | -0.011560064444749683, 78 | 0.0008716627692732737, 79 | 0.011280887944933924, 80 | 0.014955015997906912, 81 | 0.010969950321719045, 82 | 0.0020889937904723698, 83 | -0.007043621874215022, 84 | -0.012265050466923388, 85 | -0.011502589504731202, 86 | -0.005195423651821919, 87 | 0.004361238484562726, 88 | 0.014144626255836222, 89 | 0.01946696271674653, 90 | 0.008823966495059024, 91 | -0.05360372433912335, 92 | 0.01564319265083877 93 | }; 94 | fft_complex m_mem[FILTER_TAP_NUM];// Circular buffer 95 | fft_complex *m_out = NULL; 96 | int m_ip; 97 | int m_length = 0; 98 | 99 | // 100 | // This return a pointer to the filtered data 101 | // 102 | fft_complex *dvbt_filter( fft_complex *in, int length ) 103 | { 104 | int op = 0; 105 | // Allocate memory if needed 106 | if( length > m_length ) 107 | { 108 | if( m_out != NULL ) fftw_free(m_out); 109 | m_length = sizeof(fft_complex)*length; 110 | // m_out = (fft_complex*)malloc(m_length); 111 | m_out = (fft_complex*)fftw_malloc(m_length); 112 | } 113 | 114 | for( int i = 0; i < length; i++ ) 115 | { 116 | m_mem[m_ip][0] = in[i][0]; 117 | m_mem[m_ip][1] = in[i][1]; 118 | m_ip = (m_ip+1)%FILTER_TAP_NUM; 119 | 120 | m_out[op][0] = m_out[op][1] = 0; 121 | int k = m_ip; 122 | for( int n = 0; n < FILTER_TAP_NUM; n++ ) 123 | { 124 | m_out[op][0] += filter_taps[n]*m_mem[k][0]; 125 | m_out[op][1] += filter_taps[n]*m_mem[k][1]; 126 | k = (k+1)%FILTER_TAP_NUM; 127 | } 128 | op++; 129 | } 130 | return m_out; 131 | } 132 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_mod.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This is the dvb modulator. 3 | // 4 | // It takes the pre-built reference symbols 5 | // add the unknown data, calls the FFT 6 | // attaches the guard samples and sends 7 | // the result to the transmitter 8 | // 9 | #include 10 | #include 11 | #include "dvb_t.h" 12 | #include "../dvb.h" 13 | 14 | // External 15 | extern DVBTFormat m_format; 16 | 17 | // Constellation tables 18 | extern fft_complex a1_qpsk[4]; 19 | extern fft_complex a1_qam16[16]; 20 | extern fft_complex a1_qam64[64]; 21 | extern fft_complex a2_qam16[16]; 22 | extern fft_complex a2_qam64[64]; 23 | extern fft_complex a4_qam16[16]; 24 | extern fft_complex a4_qam64[64]; 25 | 26 | extern fft_complex rt_2k[SYMS_IN_FRAME*SF_NR][M2KS]; 27 | extern int dt_2k[SYMS_IN_FRAME*SF_NR][M2KS]; 28 | extern fft_complex rt_8k[SYMS_IN_FRAME*SF_NR][M8KS]; 29 | extern int dt_8k[SYMS_IN_FRAME*SF_NR][M8KS]; 30 | 31 | // Local 32 | 33 | // Where it is all at, choose the largest size. 34 | static fft_complex m_tx_in_frame[M8KS]; 35 | 36 | // Table used to map binary onto constellation 37 | const fft_complex *m_co_tab; 38 | 39 | // Number of guard symbols 40 | int m_guard; 41 | 42 | // 43 | // Calculate the number of samples to add for the guard period. 44 | // 45 | void dvb_t_calculate_guard_period( void ) 46 | { 47 | int d; 48 | 49 | switch( m_format.gi ) 50 | { 51 | case GI_132: 52 | d = 32; 53 | break; 54 | case GI_116: 55 | d = 16; 56 | break; 57 | case GI_18: 58 | d = 8; 59 | break; 60 | case GI_14: 61 | d = 4; 62 | break; 63 | default: 64 | d = 4; 65 | break; 66 | } 67 | 68 | if( m_format.tm == TM_2K ) 69 | { 70 | m_guard = M2KS/d; 71 | } 72 | 73 | if( m_format.tm == TM_8K ) 74 | { 75 | m_guard = M8KS/d; 76 | } 77 | } 78 | 79 | // 80 | // Select the required constellation for transmission. 81 | // 82 | void dvb_t_select_constellation_table( void ) 83 | { 84 | if(m_format.co == CO_QPSK ) 85 | { 86 | m_co_tab = a1_qpsk; 87 | } 88 | 89 | if(m_format.co == CO_16QAM ) 90 | { 91 | if((m_format.sf == SF_NH)||(m_format.sf == SF_A1)) 92 | { 93 | m_co_tab = a1_qam16; 94 | } 95 | if(m_format.sf == SF_A2) 96 | { 97 | m_co_tab = a2_qam16; 98 | } 99 | if( m_format.sf == SF_A4 ) 100 | { 101 | m_co_tab = a4_qam16; 102 | } 103 | } 104 | 105 | if(m_format.co == CO_64QAM ) 106 | { 107 | if((m_format.sf == SF_NH)||(m_format.sf == SF_A1)) 108 | { 109 | m_co_tab = a1_qam64; 110 | } 111 | if(m_format.sf == SF_A2) 112 | { 113 | m_co_tab = a2_qam64; 114 | } 115 | if( m_format.sf == SF_A4 ) 116 | { 117 | m_co_tab = a4_qam64; 118 | } 119 | } 120 | } 121 | // Compensate for the filter response 122 | void dvb_t_2k_compensation( fft_complex *s ) 123 | { 124 | fft_complex *f,*l; 125 | double div; 126 | f = &s[M2KSTART]; 127 | l = &s[M2KSTART+K2MAX-1]; 128 | 129 | div = 2; 130 | 131 | for( int i = 0; i < 300; i++ ) 132 | { 133 | div *= 0.997; 134 | *f[0]*=div; 135 | *f[1]*=div; 136 | *l[0]*=div; 137 | *l[1]*=div; 138 | f++;l--; 139 | if( div <= 1.0 ) break; 140 | } 141 | } 142 | 143 | // 144 | // An array of binary symbols are passed to this 145 | // routine. These are converted to QPSK/QAM. IFFTed 146 | // guard period added and then sent for sample 147 | // rate conversion before being written to the USRP2. 148 | // 149 | void dvb_t_modulate( uint8_t *syms ) 150 | { 151 | int i,r; 152 | fft_complex *fm; 153 | 154 | r = reference_symbol_seq_update(); 155 | 156 | if( m_format.tm == TM_2K ) 157 | { 158 | fm = &m_tx_in_frame[M2KSTART]; 159 | // Add the reference tones 160 | memcpy( fm, rt_2k[r], sizeof(fft_complex)*(K2MAX+1)); 161 | // add the data tsymbols 162 | for (i = 0; i < M2SI; i++) 163 | { 164 | fm[dt_2k[r][i]][0] = m_co_tab[syms[i]][0]; 165 | fm[dt_2k[r][i]][1] = m_co_tab[syms[i]][1]; 166 | } 167 | // dvb_t_2k_compensation( m_tx_in_frame ); 168 | // fft_2k_test( m_tx_out_frame ); 169 | dvbt_fft_modulate( m_tx_in_frame, m_guard ); 170 | } 171 | 172 | if( m_format.tm == TM_8K ) 173 | { 174 | fm = &m_tx_in_frame[M8KSTART]; 175 | // Add the reference tones 176 | memcpy( fm, rt_8k[r], sizeof(fft_complex)*(K8MAX+1)); 177 | // add the data symbols 178 | for (i = 0; i < M8SI; i++) 179 | { 180 | fm[dt_8k[r][i]][0] = m_co_tab[syms[i]][0]; 181 | fm[dt_8k[r][i]][1] = m_co_tab[syms[i]][1]; 182 | } 183 | dvbt_fft_modulate( m_tx_in_frame, m_guard ); 184 | } 185 | } 186 | void dvb_t_modulate_init( void ) 187 | { 188 | // Clear the transmit frame 189 | memset( m_tx_in_frame, 0, sizeof(scmplx)*M8KS); 190 | dvb_t_calculate_guard_period(); 191 | dvb_t_select_constellation_table(); 192 | } 193 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_qam_tab.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "dvb_t.h" 3 | //#include "dvb_config.h" 4 | 5 | extern DVBTFormat m_format; 6 | 7 | const fft_complex c_qpsk[4] = 8 | { 9 | {1, 1}, 10 | {1, -1}, 11 | {-1, 1}, 12 | {-1,-1} 13 | }; 14 | 15 | const fft_complex c_qam16[16] = 16 | { 17 | {3, 3}, 18 | {3, 1}, 19 | {1, 3}, 20 | {1, 1}, 21 | {3,-3}, 22 | {3,-1}, 23 | {1,-3}, 24 | {1,-1}, 25 | {-3, 3}, 26 | {-3, 1}, 27 | {-1, 3}, 28 | {-1, 1}, 29 | {-3,-3}, 30 | {-3,-1}, 31 | {-1,-3}, 32 | {-1,-1} 33 | }; 34 | const fft_complex c_qam64[64] = 35 | { 36 | {7, 7}, 37 | {7, 5}, 38 | {5, 7}, 39 | {5, 5}, 40 | {7, 1}, 41 | {7, 3}, 42 | {5, 1}, 43 | {5, 3}, 44 | {1, 7}, 45 | {1, 5}, 46 | {3, 7}, 47 | {3, 5}, 48 | {1, 1}, 49 | {1, 3}, 50 | {3, 1}, 51 | {3, 3}, 52 | {7, -7}, 53 | {7, -5}, 54 | {5, -7}, 55 | {5, -5}, 56 | {7, -1}, 57 | {7, -3}, 58 | {5, -1}, 59 | {5, -3}, 60 | {1, -7}, 61 | {1, -5}, 62 | {3, -7}, 63 | {3, -5}, 64 | {1, -1}, 65 | {1, -3}, 66 | {3, -1}, 67 | {3, -3}, 68 | {-7, 7}, 69 | {-7, 5}, 70 | {-5, 7}, 71 | {-5, 5}, 72 | {-7, 1}, 73 | {-7, 3}, 74 | {-5, 1}, 75 | {-5, 3}, 76 | {-1, 7}, 77 | {-1, 5}, 78 | {-3, 7}, 79 | {-3, 5}, 80 | {-1, 1}, 81 | {-1, 3}, 82 | {-3, 1}, 83 | {-3, 3}, 84 | {-7,-7}, 85 | {-7,-5}, 86 | {-5,-7}, 87 | {-5,-5}, 88 | {-7,-1}, 89 | {-7,-3}, 90 | {-5,-1}, 91 | {-5,-3}, 92 | {-1,-7}, 93 | {-1,-5}, 94 | {-3,-7}, 95 | {-3,-5}, 96 | {-1,-1}, 97 | {-1,-3}, 98 | {-3,-1}, 99 | {-3,-3} 100 | }; 101 | // 102 | // These are the tables used to generate the tx symbols 103 | // 104 | fft_complex a1_qpsk[4]; 105 | fft_complex a1_qam16[16]; 106 | fft_complex a1_qam64[64]; 107 | fft_complex a2_qam16[16]; 108 | fft_complex a2_qam64[64]; 109 | fft_complex a4_qam16[16]; 110 | fft_complex a4_qam64[64]; 111 | // 112 | // Look up tables for pilot tones 113 | // 114 | FLOAT pc_stab_cont[2]; 115 | FLOAT pc_stab_scat[2]; 116 | FLOAT pc_stab_tps[2]; 117 | 118 | void build_tx_sym_tabs( void ) 119 | { 120 | int i; 121 | double tr,ti,f,a; 122 | 123 | // Find the correct average energy to use 124 | 125 | if( m_format.tm == TM_8K ) 126 | a = AVG_E8; 127 | else 128 | a = AVG_E2; 129 | 130 | // QPSK factor 131 | f = 1.0/sqrt(2.0); 132 | 133 | for( i = 0; i < 4; i++ ) 134 | { 135 | a1_qpsk[i][0] = c_qpsk[i][0]*f*a; 136 | a1_qpsk[i][1] = c_qpsk[i][1]*f*a; 137 | } 138 | // QAM16 factor 139 | f = 1.0/sqrt(10); 140 | 141 | for( i = 0; i < 16; i++ ) 142 | { 143 | a1_qam16[i][0] = c_qam16[i][0]*f*a; 144 | a1_qam16[i][1] = c_qam16[i][1]*f*a; 145 | } 146 | // QAM 64 factor 147 | f = 1.0/sqrt(42); 148 | 149 | for( i = 0; i < 64; i++ ) 150 | { 151 | a1_qam64[i][0] = c_qam64[i][0]*f*a; 152 | a1_qam64[i][1] = c_qam64[i][1]*f*a; 153 | } 154 | // QAM16 A2 factor 155 | f = 1.0/sqrt(20); 156 | 157 | for( i = 0; i < 16; i++ ) 158 | { 159 | tr = c_qam16[i][0]; 160 | ti = c_qam16[i][1]; 161 | tr = tr > 0 ? tr+1 : tr-1; 162 | ti = ti > 0 ? ti+1 : ti-1; 163 | 164 | a2_qam16[i][0] = tr*f*a; 165 | a2_qam16[i][1] = ti*f*a; 166 | } 167 | // QAM64 A2 factor 168 | f = 1.0/sqrt(60); 169 | 170 | for( i = 0; i < 64; i++ ) 171 | { 172 | tr = c_qam64[i][0]; 173 | ti = c_qam64[i][1]; 174 | tr = tr > 0 ? tr+1 : tr-1; 175 | ti = ti > 0 ? ti+1 : ti-1; 176 | 177 | a2_qam64[i][0] = tr*f*a; 178 | a2_qam64[i][1] = ti*f*a; 179 | } 180 | // QAM16 A4 factor 181 | f = 1.0/sqrt(52); 182 | 183 | for( i = 0; i < 16; i++ ) 184 | { 185 | tr = c_qam16[i][0]; 186 | ti = c_qam16[i][1]; 187 | tr = tr > 0 ? tr+3 : tr-3; 188 | ti = ti > 0 ? ti+3 : ti-3; 189 | 190 | a4_qam16[i][0] = tr*f*a; 191 | a4_qam16[i][1] = ti*f*a; 192 | } 193 | // QAM64 A4 factor 194 | f = 1.0/sqrt(108); 195 | 196 | for( i = 0; i < 64; i++ ) 197 | { 198 | tr = c_qam64[i][0]; 199 | ti = c_qam64[i][1]; 200 | tr = tr > 0 ? tr+3 : tr-3; 201 | ti = ti > 0 ? ti+3 : ti-3; 202 | 203 | a4_qam64[i][0] = tr*f*a; 204 | a4_qam64[i][1] = ti*f*a; 205 | } 206 | // Pilot tones (Fixed) 207 | f = 4.0/3.0; 208 | pc_stab_cont[0] = 1.0*f*a; 209 | pc_stab_cont[1] = -1.0*f*a; 210 | 211 | pc_stab_scat[0] = 1.0*f*a; 212 | pc_stab_scat[1] = -1.0*f*a; 213 | // TP tones 214 | f = 1.0; 215 | pc_stab_tps[0] = 1.0*f*a; 216 | pc_stab_tps[1] = -1.0*f*a; 217 | 218 | } 219 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_stab.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Tables required for producing ODFM tables 3 | // 4 | //#include "dvb_gen.h" 5 | #include "dvb_t_sym.h" 6 | 7 | int sptab_2k[PPS_2K_TAB_LEN]= 8 | { 9 | 0, 48, 54,87,141,156,192,201,255,279,282,333,432,450, 10 | 483,525,531,618,636,714,759,765,780,804,873,888,918, 11 | 939,942,969,984,1050,1101,1107,1110,1137,1140,1146, 12 | 1206,1269,1323,1377,1491,1683,1704 13 | }; 14 | int sttab_2k[TPS_2K_TAB_LEN]= 15 | { 16 | 34,50,209,346,413,569,595,688,790,901, 17 | 1073,1219,1262,1286,1469,1594,1687 18 | }; 19 | 20 | int sptab_8k[PPS_8K_TAB_LEN]= 21 | { 22 | 0, 48, 54,87,141,156,192,201,255,279,282,333,432,450, 23 | 483,525,531,618,636,714,759,765,780,804,873,888, 24 | 918,939,942,969,984,1050,1101,1107,1110,1137,1140, 25 | 1146,1206,1269,1323,1377,1491,1683,1704,1752, 26 | 1758,1791,1845,1860,1896,1905,1959,1983,1986, 27 | 2037,2136,2154,2187,2229,2235,2322,2340,2418, 28 | 2463,2469,2484,2508,2577,2592,2622,2643,2646, 29 | 2673,2688,2754,2805,2811,2814,2841,2844,2850, 30 | 2910,2973,3027,3081,3195,3387,3408,3456,3462, 31 | 3495,3549,3564,3600,3609,3663,3687,3690,3741, 32 | 3840,3858,3891,3933,3939,4026,4044,4122,4167, 33 | 4173,4188,4212,4281,4296,4326,4347,4350,4377, 34 | 4392,4458,4509,4515,4518,4545,4548,4554,4614, 35 | 4677,4731,4785,4899,5091,5112,5160,5166,5199, 36 | 5253,5268,5304,5313,5367,5391,5394,5445,5544, 37 | 5562,5595,5637,5643,5730,5748,5826,5871,5877, 38 | 5892,5916,5985,6000,6030,6051,6054,6081,6096, 39 | 6162,6213,6219,6222,6249,6252,6258,6318,6381, 40 | 6435,6489,6603,6795,6816 41 | }; 42 | int sttab_8k[TPS_8K_TAB_LEN]= 43 | { 44 | 34,50,209,346,413,569,595,688,790,901,1073,1219,1262,1286,1469, 45 | 1594,1687,1738,1754,1913,2050,2117,2273,2299,2392,2494,2605, 46 | 2777,2923,2966,2990,3173,3298,3391,3442,3458,3617,3754,3821, 47 | 3977,4003,4096,4198,4309,4481,4627,4670,4694,4877,5002,5095, 48 | 5146,5162,5321,5458,5525,5681,5707,5800,5902,6013,6185,6331, 49 | 6374,6398,6581,6706,6799 50 | }; 51 | 52 | 53 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_sym.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // This module builds reference super frames for both modes 3 | // and is used as a template when transmitting actual frames 4 | // 5 | #include 6 | #include 7 | 8 | //#include "dvb_gen.h" 9 | #include "dvb_t.h" 10 | #include "dvb_t_sym.h" 11 | 12 | extern int sptab_2k[PPS_2K_TAB_LEN]; 13 | extern int sttab_2k[TPS_2K_TAB_LEN]; 14 | 15 | extern int sptab_8k[PPS_8K_TAB_LEN]; 16 | extern int sttab_8k[TPS_8K_TAB_LEN]; 17 | 18 | // Pilot tone BPSK 19 | extern FLOAT pc_stab_cont[2]; 20 | extern FLOAT pc_stab_scat[2]; 21 | extern FLOAT pc_stab_tps[2]; 22 | 23 | extern int m_sync_prbs[M8KS]; 24 | 25 | // first index is whether the seq starts with a 0 or 1 and 26 | // Which frame number it is in a superframe 27 | // 2nd index is the symbol number 28 | // output is the index into the modulation table 0,1 29 | 30 | extern uint8_t sstd[4][SYMS_IN_FRAME]; 31 | extern DVBTFormat m_format; 32 | 33 | fft_complex rt_2k[SYMS_IN_FRAME*SF_NR][M2KS]; 34 | int dt_2k[SYMS_IN_FRAME*SF_NR][M2KS]; 35 | fft_complex rt_8k[SYMS_IN_FRAME*SF_NR][M8KS]; 36 | int dt_8k[SYMS_IN_FRAME*SF_NR][M8KS]; 37 | 38 | int m_l_count; 39 | 40 | // 41 | // Build the pilot tone reference table 42 | // 43 | void build_2k_sf_ref( void ) 44 | { 45 | int l,k,i,p,s; 46 | // Zap everything 47 | memset( rt_2k, 0,sizeof(scmplx)*SYMS_IN_FRAME*SF_NR*M2KS); 48 | 49 | // Add continuous pilot tones to all symbols in frame 50 | for( l = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 51 | { 52 | for( i = 0; i < PPS_2K_TAB_LEN; i++ ) 53 | { 54 | k = sptab_2k[i];// Tone to do 55 | rt_2k[l][k][0] = pc_stab_cont[m_sync_prbs[k]]; 56 | } 57 | } 58 | 59 | // Add the scattered pilot tones 60 | for( l = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 61 | { 62 | for( p = 0; p < K2MAX; p++ ) 63 | { 64 | k = K2MIN + (3*(l%4))+(12*p); 65 | if( k < K2MAX ) 66 | { 67 | rt_2k[l][k][0] = pc_stab_scat[m_sync_prbs[k]]; 68 | } 69 | } 70 | } 71 | 72 | // Add the TP information to the 4 frames in the superframe 73 | // Frame 1 74 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 75 | { 76 | s = l; 77 | for( i = 0; i < TPS_2K_TAB_LEN; i++ ) 78 | { 79 | k = sttab_2k[i];// tone to do 80 | rt_2k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]][l]]; 81 | } 82 | } 83 | // Frame 2 84 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 85 | { 86 | s = l+SYMS_IN_FRAME; 87 | for( i = 0; i < TPS_2K_TAB_LEN; i++ ) 88 | { 89 | k = sttab_2k[i];//tone to do 90 | rt_2k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+2][l]]; 91 | } 92 | } 93 | // Frame 3 94 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 95 | { 96 | s = l+(SYMS_IN_FRAME*2); 97 | for( i = 0; i < TPS_2K_TAB_LEN; i++ ) 98 | { 99 | k = sttab_2k[i];// tone to do 100 | rt_2k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+4][l]]; 101 | } 102 | } 103 | // Frame 4 104 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 105 | { 106 | s = l+(SYMS_IN_FRAME*3); 107 | for( i = 0; i < TPS_2K_TAB_LEN; i++ ) 108 | { 109 | k = sttab_2k[i];// tone to do 110 | rt_2k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+6][l]]; 111 | } 112 | } 113 | // Now build the data tone reference table 114 | for( l = 0, i = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 115 | { 116 | i = 0; 117 | for( k = K2MIN; k <= K2MAX; k++ ) 118 | { 119 | if(rt_2k[l][k][0] == 0 ) dt_2k[l][i++]=k; 120 | } 121 | } 122 | } 123 | 124 | void build_8k_sf_ref( void ) 125 | { 126 | int l,k,i,p,s; 127 | // Zap everything 128 | memset( rt_8k, 0,sizeof(scmplx)*SYMS_IN_FRAME*SF_NR*M8KS); 129 | 130 | // Add continuos pilot tones 131 | for( l = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 132 | { 133 | for( i = 0; i < PPS_8K_TAB_LEN; i++ ) 134 | { 135 | k = sptab_8k[i];//Tone to do 136 | rt_8k[l][k][0] = pc_stab_cont[m_sync_prbs[k]]; 137 | } 138 | } 139 | // Add the scattered pilot tones 140 | for( l = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 141 | { 142 | for( p = 0; p < K8MAX; p++ ) 143 | { 144 | k = K8MIN + (3*(l%4))+(12*p); 145 | if( k < K8MAX ) 146 | { 147 | rt_8k[l][k][0] = pc_stab_scat[m_sync_prbs[k]]; 148 | } 149 | } 150 | } 151 | // Add the TP information to the 4 frames in the superframe 152 | // Frame 0 153 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 154 | { 155 | s = l; 156 | for( i = 0; i < TPS_8K_TAB_LEN; i++ ) 157 | { 158 | k = sttab_8k[i]; 159 | rt_8k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]][l]]; 160 | } 161 | } 162 | // Frame 2 163 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 164 | { 165 | s = l+SYMS_IN_FRAME; 166 | for( i = 0; i < TPS_8K_TAB_LEN; i++ ) 167 | { 168 | k = sttab_8k[i]; 169 | rt_8k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+2][l]]; 170 | } 171 | } 172 | // Frame 3 173 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 174 | { 175 | s = l+(SYMS_IN_FRAME*2); 176 | for( i = 0; i < TPS_8K_TAB_LEN; i++ ) 177 | { 178 | k = sttab_8k[i]; 179 | rt_8k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+4][l]]; 180 | } 181 | } 182 | // Frame 4 183 | for( l = 0; l < SYMS_IN_FRAME; l++ ) 184 | { 185 | s = l+(SYMS_IN_FRAME*3); 186 | for( i = 0; i < TPS_8K_TAB_LEN; i++ ) 187 | { 188 | k = sttab_8k[i]; 189 | rt_8k[s][k][0] = pc_stab_tps[sstd[m_sync_prbs[k]+6][l]]; 190 | } 191 | } 192 | // Now build the data tone reference table 193 | for( l = 0, i = 0; l < (SYMS_IN_FRAME*SF_NR); l++ ) 194 | { 195 | i = 0; 196 | for( k = K8MIN; k <= K8MAX; k++ ) 197 | { 198 | if(rt_8k[l][k][0] == 0 )dt_8k[l][i++]=k; 199 | } 200 | } 201 | } 202 | void reference_symbol_reset( void ) 203 | { 204 | m_l_count = 0; 205 | } 206 | // 207 | // This is required by the symbol interleaver 208 | // 209 | 210 | int reference_symbol_seq_get( void ) 211 | { 212 | return m_l_count; 213 | } 214 | 215 | int reference_symbol_seq_update( void ) 216 | { 217 | int c = m_l_count; 218 | m_l_count = (m_l_count+1)%(SYMS_IN_FRAME*SF_NR); 219 | return c; 220 | } 221 | 222 | // 223 | // Build a reference super frame, this only needs to be done 224 | // at program start-up and when the transmitter mode is changed. 225 | // 226 | void init_reference_frames( void ) 227 | { 228 | build_2k_sf_ref(); 229 | build_8k_sf_ref(); 230 | reference_symbol_reset(); 231 | } 232 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_sym.h: -------------------------------------------------------------------------------- 1 | #define TPS_2K_TAB_LEN 17 2 | #define TPS_8K_TAB_LEN 68 3 | #define PPS_2K_TAB_LEN 45 4 | #define PPS_8K_TAB_LEN 177 5 | -------------------------------------------------------------------------------- /libdvbmod/DVB-T/dvb_t_tp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "dvb_t.h" 4 | //#include "dvb_config.h" 5 | 6 | #define M_K 53 7 | #define M_N 67 8 | 9 | // Externally visible 10 | extern DVBTFormat m_format; 11 | int m_bit_modulo; 12 | 13 | // TP information 8 versions 14 | uint8_t sstd[8][SYMS_IN_FRAME]; 15 | // 16 | // The Poly has been bit reversed 17 | // 18 | int bch( int bit, int en, long *shift ) 19 | { 20 | if(en) 21 | { 22 | if( bit^(*shift&1)) 23 | { 24 | *shift ^= BCH_RPOLY; 25 | *shift |= (1<<(M_N-M_K)); 26 | } 27 | } 28 | else 29 | { 30 | bit = *shift&1; 31 | } 32 | *shift>>=1; 33 | 34 | return bit; 35 | } 36 | 37 | void dvb_t_bch_encode( uint8_t *b ) 38 | { 39 | int i; 40 | long shift = 0; 41 | // 42 | // Information bits. 43 | // 44 | for( i = 0; i < M_K; i++ ) 45 | { 46 | if(b[i]) 47 | { 48 | bch( 1, 1, &shift ); 49 | } 50 | else 51 | { 52 | bch( 0, 1, &shift ); 53 | } 54 | } 55 | // 56 | // Now the parity bits 57 | // 58 | for( i = 0; i < M_N-M_K; i++ ) 59 | { 60 | b[i+M_K] = bch( 0, 0, &shift ); 61 | } 62 | } 63 | // 64 | // Differentially encode the tables 65 | // The correct magnitudes will be set during the 66 | // frame building process 67 | // 68 | void build_diff_tp_tables( uint8_t *in, uint8_t *out ) 69 | { 70 | int i; 71 | 72 | out[0] = in[0]; 73 | 74 | for( i = 1; i < SYMS_IN_FRAME; i++ ) 75 | { 76 | if( in[i] == 0 ) 77 | out[i] = out[i-1]; 78 | else 79 | out[i] = out[i-1]^1; 80 | } 81 | } 82 | void build_tp_block( void ) 83 | { 84 | int i; 85 | 86 | uint8_t s[4][SYMS_IN_FRAME]; 87 | 88 | 89 | // Length 90 | s[0][17] = 0; 91 | s[0][18] = 1; 92 | s[0][19] = 0; 93 | s[0][20] = 1; 94 | s[0][21] = 1; 95 | s[0][22] = 1; 96 | 97 | 98 | // Constellation patterns 99 | 100 | if( m_format.co == CO_QPSK ) 101 | { 102 | s[0][25] = 0; 103 | s[0][26] = 0; 104 | m_bit_modulo = 2; 105 | } 106 | if( m_format.co == CO_16QAM ) 107 | { 108 | s[0][25] = 0; 109 | s[0][26] = 1; 110 | m_bit_modulo = 4; 111 | } 112 | if( m_format.co == CO_64QAM ) 113 | { 114 | s[0][25] = 1; 115 | s[0][26] = 0; 116 | m_bit_modulo = 6; 117 | } 118 | 119 | // Signalling format for a values 120 | if( m_format.sf == SF_NH ) 121 | { 122 | s[0][27] = 0; 123 | s[0][28] = 0; 124 | s[0][29] = 0; 125 | } 126 | if( m_format.sf == SF_A1 ) 127 | { 128 | s[0][27] = 0; 129 | s[0][28] = 0; 130 | s[0][29] = 1; 131 | } 132 | if( m_format.sf == SF_A2 ) 133 | { 134 | s[0][27] = 0; 135 | s[0][28] = 1; 136 | s[0][29] = 0; 137 | } 138 | if( m_format.sf == SF_A4 ) 139 | { 140 | s[0][27] = 0; 141 | s[0][28] = 1; 142 | s[0][29] = 1; 143 | } 144 | 145 | // Code rates 146 | 147 | if( m_format.fec == CR_12 ) 148 | { 149 | s[0][30] = 0; 150 | s[0][31] = 0; 151 | s[0][32] = 0; 152 | } 153 | if( m_format.fec == CR_23 ) 154 | { 155 | s[0][30] = 0; 156 | s[0][31] = 0; 157 | s[0][32] = 1; 158 | } 159 | if( m_format.fec == CR_34 ) 160 | { 161 | s[0][30] = 0; 162 | s[0][31] = 1; 163 | s[0][32] = 0; 164 | } 165 | if( m_format.fec == CR_56 ) 166 | { 167 | s[0][30] = 0; 168 | s[0][31] = 1; 169 | s[0][32] = 1; 170 | } 171 | if( m_format.fec == CR_78 ) 172 | { 173 | s[0][30] = 1; 174 | s[0][31] = 0; 175 | s[0][32] = 0; 176 | } 177 | 178 | if( m_format.fec == CR_12 ) 179 | { 180 | s[0][33] = 0; 181 | s[0][34] = 0; 182 | s[0][35] = 0; 183 | } 184 | if( m_format.fec == CR_23 ) 185 | { 186 | s[0][33] = 0; 187 | s[0][34] = 0; 188 | s[0][35] = 1; 189 | } 190 | if( m_format.fec == CR_34 ) 191 | { 192 | s[0][33] = 0; 193 | s[0][34] = 1; 194 | s[0][35] = 0; 195 | } 196 | if( m_format.fec == CR_56 ) 197 | { 198 | s[0][33] = 0; 199 | s[0][34] = 1; 200 | s[0][35] = 1; 201 | } 202 | if( m_format.fec == CR_78 ) 203 | { 204 | s[0][33] = 1; 205 | s[0][34] = 0; 206 | s[0][35] = 0; 207 | } 208 | 209 | // Guard intervals 210 | 211 | if( m_format.gi == GI_132 ) 212 | { 213 | s[0][36] = 0; 214 | s[0][37] = 0; 215 | } 216 | if( m_format.gi == GI_116 ) 217 | { 218 | s[0][36] = 0; 219 | s[0][37] = 1; 220 | } 221 | if( m_format.gi == GI_18 ) 222 | { 223 | s[0][36] = 1; 224 | s[0][37] = 0; 225 | } 226 | if( m_format.gi == GI_14 ) 227 | { 228 | s[0][36] = 1; 229 | s[0][37] = 1; 230 | } 231 | 232 | // Transmission mode 233 | 234 | if( m_format.tm == TM_2K ) 235 | { 236 | s[0][38] = 0; 237 | s[0][39] = 0; 238 | } 239 | if( m_format.tm == TM_8K ) 240 | { 241 | s[0][38] = 0; 242 | s[0][39] = 1; 243 | } 244 | 245 | // Stuff with zero 246 | 247 | for( i = 40; i < 54; i++ ) 248 | { 249 | s[0][i] = 0; 250 | } 251 | // Duplicate the frames 252 | memcpy(s[1],s[0],sizeof(uint8_t)*SYMS_IN_FRAME); 253 | memcpy(s[2],s[0],sizeof(uint8_t)*SYMS_IN_FRAME); 254 | memcpy(s[3],s[0],sizeof(uint8_t)*SYMS_IN_FRAME); 255 | // Sync sequences 256 | s[0][1] = 0; s[1][1] = 1; 257 | s[0][2] = 0; s[1][2] = 1; 258 | s[0][3] = 1; s[1][3] = 0; 259 | s[0][4] = 1; s[1][4] = 0; 260 | s[0][5] = 0; s[1][5] = 1; 261 | s[0][6] = 1; s[1][6] = 0; 262 | s[0][7] = 0; s[1][7] = 1; 263 | s[0][8] = 1; s[1][8] = 0; 264 | s[0][9] = 1; s[1][9] = 0; 265 | s[0][10] = 1; s[1][10] = 0; 266 | s[0][11] = 1; s[1][11] = 0; 267 | s[0][12] = 0; s[1][12] = 1; 268 | s[0][13] = 1; s[1][13] = 0; 269 | s[0][14] = 1; s[1][14] = 0; 270 | s[0][15] = 1; s[1][15] = 0; 271 | s[0][16] = 0; s[1][16] = 1; 272 | memcpy(&s[2][1],&s[0][1],sizeof(uint8_t)*16); 273 | memcpy(&s[3][1],&s[1][1],sizeof(uint8_t)*16); 274 | // 275 | // Signalling format for each frame 276 | // 277 | // Frame 1 278 | s[0][23] = 0; 279 | s[0][24] = 0; 280 | // Frame 2 281 | s[1][23] = 0; 282 | s[1][24] = 1; 283 | // Frame 3 284 | s[2][23] = 1; 285 | s[2][24] = 0; 286 | // Frame 4 287 | s[3][23] = 1; 288 | s[3][24] = 1; 289 | 290 | // Add BCH code 291 | dvb_t_bch_encode( &s[0][1] ); 292 | dvb_t_bch_encode( &s[1][1] ); 293 | dvb_t_bch_encode( &s[2][1] ); 294 | dvb_t_bch_encode( &s[3][1] ); 295 | 296 | // Generate differentially encoded tables 297 | s[0][0] = 0; 298 | build_diff_tp_tables( s[0], sstd[0] ); 299 | s[0][0] = 1; 300 | build_diff_tp_tables( s[0], sstd[1] ); 301 | 302 | s[1][0] = 0; 303 | build_diff_tp_tables( s[1], sstd[2] ); 304 | s[1][0] = 1; 305 | build_diff_tp_tables( s[1], sstd[3] ); 306 | 307 | s[2][0] = 0; 308 | build_diff_tp_tables( s[2], sstd[4] ); 309 | s[2][0] = 1; 310 | build_diff_tp_tables( s[2], sstd[5] ); 311 | 312 | s[3][0] = 0; 313 | build_diff_tp_tables( s[3], sstd[6] ); 314 | s[3][0] = 1; 315 | build_diff_tp_tables( s[3], sstd[7] ); 316 | 317 | } 318 | -------------------------------------------------------------------------------- /libdvbmod/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile template for Static library. 2 | # 1. Compile every *.cpp in the folder 3 | # 2. All obj files under obj folder 4 | # 3. static library .a at lib folder 5 | # 4. run 'make dirmake' before calling 'make' 6 | 7 | 8 | CC = g++ 9 | OUT_FILE_NAME = libdvbmod.a 10 | 11 | CFLAGS= -fPIC -O2 -g -Wall -c -fpermissive 12 | LDFLAGS = -lm -lrt -lpthread 13 | 14 | INC = -I../Import 15 | 16 | OBJ_DIR=./obj 17 | 18 | OUT_DIR=./lib 19 | 20 | # Enumerating of every *.cpp as *.o and using that as dependency. 21 | # filter list of .c files in a directory. 22 | # FILES =dump_l.c \ 23 | # kter.c \ 24 | # 25 | # $(OUT_FILE_NAME): $(patsubst %.c,$(OBJ_DIR)/%.o,$(wildcard $(FILES))) 26 | 27 | 28 | # Enumerating of every *.cpp as *.o and using that as dependency 29 | $(OUT_FILE_NAME):\ 30 | $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard *.cpp))\ 31 | $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard DVB-S/*.cpp)) \ 32 | $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard DVB-S2/*.cpp)) 33 | #$(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard DVB-T/*.cpp)) \ 34 | $(patsubst %.cpp,$(OBJ_DIR)/%.o,$(wildcard DVB-S2/*.cpp)) 35 | ar -r -o $(OUT_DIR)/$@ $^ 36 | 37 | 38 | 39 | #Compiling every *.cpp to *.o 40 | $(OBJ_DIR)/%.o: %.cpp dirmake 41 | $(CC) -c $(INC) $(CFLAGS) -o $@ $< 42 | 43 | dirmake: 44 | @mkdir -p $(OUT_DIR) 45 | @mkdir -p $(OBJ_DIR) 46 | 47 | @mkdir -p $(OBJ_DIR)/DVB-S 48 | @mkdir -p $(OBJ_DIR)/DVB-S2 49 | @mkdir -p $(OBJ_DIR)/DVB-T 50 | 51 | clean: 52 | rm -f $(OBJ_DIR)/*.o $(OUT_DIR)/$(OUT_FILE_NAME) Makefile.bak 53 | rm -f $(OBJ_DIR)/DVB-S/*.o 54 | rm -f $(OBJ_DIR)/DVB-S2/*.o 55 | rm -f $(OBJ_DIR)/DVB-T/*.o 56 | 57 | rebuild: clean build 58 | -------------------------------------------------------------------------------- /libdvbmod/dvb.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef DVB_H_ 3 | #define DVB_H_ 4 | 5 | #include 6 | #include 7 | #include "dvb_types.h" 8 | 9 | /*#include "express.h" 10 | #include "dvb_gen.h" 11 | #include "dvb_config.h" 12 | #include "dvb_buffer.h" 13 | */ 14 | typedef enum { FEC_14, FEC_13, FEC_25, FEC_12, FEC_35, FEC_23, FEC_34, FEC_45, FEC_56, FEC_89, FEC_78, FEC_910 }Fec; 15 | 16 | #define TAPS 12 17 | #define ITP 5 18 | #define BLOCKS 80 19 | #define TMP_CSIZE 200 20 | 21 | #define DVB_FILTER_BLK_LEN (TAPS*BLOCKS) 22 | 23 | #define S_VERSION "2.03" 24 | 25 | #define S_DVB_S "DVB-S" 26 | #define S_DVB_S2 "DVB-S2" 27 | #define S_DVB_C "DVB-C" 28 | #define S_DVB_T "DVB-T" 29 | #define S_DVB_T2 "DVB-T2" 30 | #define S_EXPRESS_AUTO "Express Auto" 31 | #define S_EXPRESS_16 "Express 16 bit" 32 | #define S_EXPRESS_8 "Express 8 bit" 33 | #define S_EXPRESS_TS "Express TS" 34 | #define S_EXPRESS_UDP "Express UDP" 35 | #define S_USRP2 "USRP2" 36 | #define S_NONE "NONE" 37 | #define S_DIGILITE "Digilite" 38 | #define S_UDP_TS "UDP TS" 39 | #define S_UDP_PS "UDP PS" 40 | #define S_PVRXXX "PVRXXX" 41 | #define S_PVRHD "PVRHD" 42 | #define S_FIREWIRE "FIREWIRE" 43 | #define S_FEC_1_2 "1/2" 44 | #define S_FEC_2_3 "2/3" 45 | #define S_FEC_3_4 "3/4" 46 | #define S_FEC_5_6 "5/6" 47 | #define S_FEC_7_8 "7/8" 48 | #define S_FEC_1_4 "1/4" 49 | #define S_FEC_1_3 "1/3" 50 | #define S_FEC_2_5 "2/5" 51 | #define S_FEC_3_5 "3/5" 52 | #define S_FEC_4_5 "4/5" 53 | #define S_FEC_5_6 "5/6" 54 | #define S_FEC_8_9 "8/9" 55 | #define S_FEC_9_10 "9/10" 56 | #define S_M_QPSK "QPSK" 57 | #define S_M_8PSK "8PSK" 58 | #define S_M_16APSK "16APSK" 59 | #define S_M_16QAM "16QAM" 60 | #define S_M_32APSK "32APSK" 61 | #define S_M_64QAM "64QAM" 62 | #define S_YES "Yes" 63 | #define S_NO "No" 64 | #define S_RO_0_35 "0.35" 65 | #define S_RO_0_25 "0.25" 66 | #define S_RO_0_20 "0.20" 67 | #define S_FFT_2K "2K" 68 | #define S_FFT_8K "8K" 69 | #define S_GP_1_4 "1/4" 70 | #define S_GP_1_8 "1/8" 71 | #define S_GP_1_16 "1/16" 72 | #define S_GP_1_32 "1/32" 73 | #define S_CH_8MHZ "8MHz" 74 | #define S_CH_7MHZ "7MHz" 75 | #define S_CH_6MHZ "6MHz" 76 | #define S_CH_4MHZ "4MHz" 77 | #define S_CH_3MHZ "3MHz" 78 | #define S_CH_2MHZ "2MHz" 79 | #define S_CH_1MHZ "1MHz" 80 | #define S_CH_500KHZ "500KHz" 81 | #define S_FM_NORMAL "Normal" 82 | #define S_FM_SHORT "Short" 83 | #define S_ALPHA_NH "Alpha NH" 84 | #define S_ALPHA_1 "Alpha 1" 85 | #define S_ALPHA_2 "Alpha 2" 86 | #define S_ALPHA_4 "Alpha 4" 87 | 88 | 89 | #endif -------------------------------------------------------------------------------- /libdvbmod/dvb_types.h: -------------------------------------------------------------------------------- 1 | #ifndef DVB_TYPES_H 2 | #define DVB_TYPES_H 3 | 4 | 5 | typedef struct { 6 | short re; 7 | short im; 8 | }scmplx; 9 | 10 | 11 | //#define scmplx fftw_complex 12 | 13 | typedef struct{ 14 | double re; 15 | double im; 16 | }dcmplx; 17 | 18 | typedef struct{ 19 | float re; 20 | float im; 21 | }fcmplx; 22 | 23 | 24 | #endif // DVB_TYPES_H 25 | -------------------------------------------------------------------------------- /libdvbmod/libdvbmod.cpp: -------------------------------------------------------------------------------- 1 | #include "libdvbmod.h" 2 | #include "./DVB-S2/DVBS2.h" 3 | #include "./DVB-S/dvbs.h" 4 | #include "math.h" 5 | #include 6 | 7 | #define UPSAMPLE_MAX 4 8 | size_t m_upsample = 1; 9 | float CoefFec[12] = {1 / 4.0, 1 / 3.0, 2 / 5.0, 1 / 2.0, 3 / 5.0, 2 / 3.0, 3 / 4.0, 4 / 5.0, 5 / 6.0, 8 / 9.0, 7 / 8.0, 9 / 10.0}; 10 | DVBS2 DvbS2Modulator; 11 | 12 | static size_t DVBS2Length = 0; 13 | static sfcmplx *dvbs_symbols_short; 14 | static short *dvbs2_symbols_map; 15 | 16 | static DVB2FrameFormat S2Format; 17 | 18 | int Dvbs2Init(int SRate, int CodeRate, int Constellation, int PilotesOn, int RollOff, int Upsample, bool ShortFrame) 19 | { 20 | 21 | if (ShortFrame) 22 | { 23 | S2Format.frame_type = FRAME_SHORT; 24 | fprintf(stderr, "DVB ShortFrame\n"); 25 | } 26 | else 27 | { 28 | S2Format.frame_type = FRAME_NORMAL; 29 | fprintf(stderr, "DVB LongFrame\n"); 30 | } 31 | 32 | S2Format.code_rate = CodeRate; 33 | S2Format.constellation = Constellation; 34 | S2Format.pilots = PilotesOn; 35 | S2Format.broadcasting = 1; 36 | S2Format.roll_off = RollOff; 37 | S2Format.null_deletion = 0; 38 | S2Format.dummy_frame = 0; 39 | DvbS2Modulator.s2_set_configure(&S2Format); 40 | m_upsample = Upsample; 41 | 42 | int FrameSize = (S2Format.frame_type == FRAME_NORMAL) ? FRAME_SIZE_NORMAL : FRAME_SIZE_SHORT; 43 | fprintf(stderr, "Frame Size=%d\n", FrameSize); 44 | dvbs_symbols_short = (sfcmplx *)malloc(FrameSize * m_upsample * sizeof(sfcmplx)); 45 | dvbs2_symbols_map = (short *)malloc(FrameSize * sizeof(short)); //Should be less bet never mind and fixme free it !!! 46 | 47 | return (int)(SRate * DvbS2Modulator.s2_get_efficiency()); 48 | } 49 | 50 | int Dvbs2AddTsPacket(uint8_t *Packet) 51 | { 52 | DVBS2Length = DvbS2Modulator.s2_add_ts_frame(Packet); 53 | return DVBS2Length * m_upsample; 54 | } 55 | 56 | sfcmplx *Dvbs2_get_IQ(void) 57 | { 58 | if (m_upsample > 1) 59 | { 60 | static sfcmplx Zero; 61 | Zero.im = 0; 62 | Zero.re = 0; 63 | sfcmplx *FrameS2IQ = (sfcmplx *)DvbS2Modulator.pl_get_frame(); 64 | 65 | for (size_t i = 0; i < DVBS2Length; i++) 66 | { 67 | for (size_t j = 0; j < m_upsample; j++) 68 | { 69 | dvbs_symbols_short[i * m_upsample + j] = (j == 0) ? FrameS2IQ[i] : Zero; 70 | //dvbs_symbols_short[i*m_upsample+j].im*=m_upsample; 71 | //dvbs_symbols_short[i*m_upsample+j].re*=m_upsample; 72 | } 73 | } 74 | return dvbs_symbols_short; 75 | } 76 | else 77 | { 78 | 79 | return (sfcmplx *)DvbS2Modulator.pl_get_frame(); 80 | } 81 | } 82 | 83 | //Dirty trick to MAP !!! Could be improved 84 | // Instead of packing before, we use a reverse oq I/Q and map it inverse on DVBS... 85 | /* 86 | short *Dvbs2_get_MapIQ(int *len) 87 | { 88 | //QPSK 64800/12Symbols=5400 89 | //QPSK 16200/12Symbols=1350 90 | 91 | sfcmplx *FrameS2IQ=(sfcmplx*)DvbS2Modulator.pl_get_frame(); 92 | 93 | int shift=0; 94 | int MapLen=0; 95 | for(size_t i=0;i> j) & 0x3)]; 524 | } 525 | } 526 | } 527 | #endif 528 | -------------------------------------------------------------------------------- /libdvbmod/libdvbmod.h: -------------------------------------------------------------------------------- 1 | #ifndef LIBDVBMOD_H_ 2 | #define LIBDVBMOD_H_ 3 | //#define WITH_ARM 4 | #include 5 | // ********************** S2 MODULATOR 6 | // Code rates 7 | #define CR_1_4 0 8 | #define CR_1_3 1 9 | #define CR_2_5 2 10 | #define CR_1_2 3 11 | #define CR_3_5 4 12 | #define CR_2_3 5 13 | #define CR_3_4 6 14 | #define CR_4_5 7 15 | #define CR_5_6 8 16 | #define CR_8_9 9 17 | #define CR_7_8 10 18 | #define CR_9_10 11 19 | 20 | // Constellation 21 | #define M_QPSK 0 22 | #define M_8PSK 1 23 | #define M_16APSK 2 24 | #define M_32APSK 3 25 | 26 | // Rolloff 27 | #define RO_0_35 0 28 | #define RO_0_25 1 29 | #define RO_0_20 2 30 | #define RO_RESERVED 3 31 | 32 | typedef struct { 33 | short re; 34 | short im; 35 | }sfcmplx; 36 | 37 | extern int Dvbs2Init(int SRate,int CodeRate,int Constellation,int PilotesOn,int RollOff,int Upsample=1,bool ShortFrame=true); 38 | extern int Dvbs2AddTsPacket(uint8_t *Packet); 39 | extern sfcmplx *Dvbs2_get_IQ(void); 40 | extern short *Dvbs2_get_MapIQ(int *len); 41 | 42 | extern int DvbsInit(int SRate, int CodeRate, int Constellation = M_QPSK,int Upsample=1); 43 | extern int DvbsAddTsPacket(uint8_t *Packet); 44 | extern sfcmplx *Dvbs_get_IQ(void); 45 | extern short *Dvbs_get_MapIQ(int *len); 46 | #ifdef WITH_ARM 47 | #ifdef __arm__ 48 | extern int DvbsInit(int SRate, int CodeRate); 49 | extern int DvbsAddTsPacket(uint8_t *Packet); 50 | extern sfcmplx *Dvbs_get_IQ(void); 51 | #endif 52 | #endif 53 | #endif 54 | -------------------------------------------------------------------------------- /libdvbmod/libdvbmod.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 15.0 23 | {96163F30-C318-4CF5-97B0-DFB367FDDC68} 24 | Win32Proj 25 | libdvbmod 26 | 10.0.14393.0 27 | 28 | 29 | 30 | StaticLibrary 31 | true 32 | v141 33 | Unicode 34 | 35 | 36 | StaticLibrary 37 | false 38 | v141 39 | true 40 | Unicode 41 | 42 | 43 | StaticLibrary 44 | true 45 | v141 46 | Unicode 47 | 48 | 49 | StaticLibrary 50 | false 51 | v141 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | C:\Users\Dell\Documents\libdvbmod\fftw-3.3.5-dll32\;$(IncludePath) 75 | 76 | 77 | C:\Users\Dell\Documents\libdvbmod\fftw-3.3.5-dll32\;$(VC_IncludePath);$(WindowsSDK_IncludePath); 78 | 79 | 80 | 81 | 82 | 83 | Level3 84 | Disabled 85 | WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions) 86 | 87 | 88 | Windows 89 | 90 | 91 | 92 | 93 | 94 | 95 | Level3 96 | Disabled 97 | _DEBUG;_LIB;%(PreprocessorDefinitions) 98 | 99 | 100 | Windows 101 | 102 | 103 | 104 | 105 | Level3 106 | 107 | 108 | MaxSpeed 109 | true 110 | true 111 | WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions) 112 | 113 | 114 | Windows 115 | true 116 | true 117 | 118 | 119 | 120 | 121 | Level3 122 | 123 | 124 | MaxSpeed 125 | true 126 | true 127 | NDEBUG;_LIB;%(PreprocessorDefinitions) 128 | 129 | 130 | Windows 131 | true 132 | true 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | --------------------------------------------------------------------------------