www.pudn.com > opengpssim.zip > ogsxmit.c
/* ************************************************************************ * * * GPS Simulation * * * * -------------------------------------------------------------------- * * * * Module: ogsxmit.cpp * * * * Version: 0.1 * * * * Date: 17.02.02 * * * * Author: G. Beyerle * * * * -------------------------------------------------------------------- * * * * Copyright (C) 2002-2006 Georg Beyerle * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * * -------------------------------------------------------------------- * * * * The files 'gpsfuncs.cpp', 'gpsrcvr.cpp' and 'gp2021.cpp' are modi- * * fied versions of the files with the same name from Clifford Kelley's * * OpenSourceGPS distribution. The unmodified files can be obtained * * from http://www.home.earthlink.net/~cwkelley * * * * -------------------------------------------------------------------- * * * * GPS signal transmitter * * * ************************************************************************ */ /* ******************************* changes ******************************** dd.mm.yy - ************************************************************************ */ // to do: // - fill struct iono_data und struct UTC_data / 17.2.02 // - parity bits // - check calc of parity in parity_check() /* ------------------------------- includes ------------------------------- */ #include#include #include #include #include #include #include "ogsdefine.h" #include "ogsstructs.h" #include "ogsprototypes.h" #include "ogslibrary.h" #include "boxmuller.h" #define MAIN #include "ogsextern.h" #undef MAIN /* ------------------------------- defines -------------------------------- */ //#define XMTRBUFLEN 500000 #define XMTRBUFLEN 150000 //#define XMTRBUFLEN 1000 /* ------------------------------- structs -------------------------------- */ typedef struct { int active, inhibited; int prn; // satellite id long carrier_cycle_counter; // # of positive going zero crossings of i_lo long code_phase_counter; long carrier_dco_incr, // 26 bit, frq res. is 42.57475 mHz carrier_dco_phase, // carrier cycle fraction / phase in 2pi/1024 increments code_dco_phase, code_dco_incr; int epoch_counter, epoch_1ms, // 0,...,19; 1 msec (1 C/A) code epoch epoch_20ms; // 0,...,49; 20 msec (20 C/A, 1 data bit) epoch } XMTRINFO; XMTRINFO XmtrInfo[NOFSAT+1]; /* ------------------------------- globals -------------------------------- */ //static double const SampleFrq = 5.714e6; //static double const CarrierFrq = 1.405396825e6; //static double const CodeFrq = 1.023e6; static double SampleTime = 0; char *NavFrame[NOFSAT+1]; static int HalfChip_Counter[NOFSAT+1]; // phase counters static unsigned long Carrier_Cycle[NOFSAT+1], Code_Cycle[NOFSAT+1], CACode_Counter[NOFSAT+1]; // 0,...,20*1500-1 static double Carrier_DCO_Cycle[NOFSAT+1]; //static int Carrier_DCO_I[] = {-1,1,2, 2, 1,-1,-2,-2}; static int Carrier_DCO_I[] = {2, 2, 1, -1, -2, -2, -1, 1}; static unsigned char XmtrBuf[XMTRBUFLEN]; static char *NavBit[NOFSAT+1]; static float QuantThresh, // quantization theshold Noise_dB, // noise added to signal Noise_Ampl, // noise added to signal MaxTime; static float Latitude, Longitude; // receiver location char ProgramName[] = "ogsxmit"; static char Version[] = "0.1.1"; extern char *OutputFileName; extern char *NavFilePattern; extern int OverWrite; extern long CounterStartValue; /* -------------------------- prototypen (global) ------------------------- */ void getargs( int argc, char *argv[]); /* ------------------------------ procedures ------------------------------ */ void usage( void) { printf( "usage: %s [options]\n", ProgramName); printf( "version %s (compiled %s %s) \n", Version, __DATE__, __TIME__); printf( " options:\n"); printf( " -h : print this message \n"); printf( " -v : verbose \n"); printf( " -f : overwrite existing files \n"); printf( " -n : navigation file pattern \n"); printf( " -o : write data to 'data/' ['ogsraw.dat'] \n"); exit(0); } void check_options( void) { if ( !NavFilePattern) { printf( "No navigation file selected (option -n)."); exit(-1); } return; } // // read parameters from file // adapted from read_rcvr_par() (c) Clifford Kelley // static void read_xmit_par( void) { char infile[] = "xmit_par.dat", *tmpstr; FILE *in; tmpstr = conmalloc( strlen( OGSBinDir) + strlen( infile) + 1); strcpy( tmpstr, OGSBinDir); strcat( tmpstr, infile); if (( in = fopen( tmpstr, "rt")) == NULL) { printf( "Error opening parameter file '%s'.\n", tmpstr); perror( NULL); exit( 0); } else { #define SPSIZE 200 int loop = 1, ret; char buf[SPSIZE]; char sep[] = ":"; /* list of token separators */ char *token; printf( "Read parameter from file '%s' ...\n", tmpstr); while ( !feof( in) && loop) { fgets( buf, SPSIZE, in); if ( buf[0] == '#') continue; token = strtok( buf, sep); // format is : if ( token) { ret = read_key_value_pair_float( token, "Quantiz. Threshold", &QuantThresh, sep); if ( !ret) ret = read_key_value_pair_float( token, "Noise [dB]", &Noise_dB, sep); if ( !ret) ret = read_key_value_pair_float( token, "Max. Time [sec]", &MaxTime, sep); if ( !ret) ret = read_key_value_pair_float( token, "latitude [deg]", &Latitude, sep); if ( !ret) ret = read_key_value_pair_float( token, "longitude [deg]", &Longitude, sep); if ( !ret) { token = strtok( NULL, sep); if ( token) { printf( "unkown keyword >%s< in file %s\n", buf, tmpstr); exit( -1); } } } else // --- token is NULL --- loop = 0; } // --- while ( !feof( in) && loop) --- } fclose( in); if ( Verbose) { printf( "Finished reading parameter file %s.\n", tmpstr); printf( "Press ENTER\n"); getchar(); } if ( tmpstr) free( tmpstr); return; } // // initialize carrier and code counter increments // static void init_struct_xmitter( void) { int i; for ( i=1; i<=NOFSAT; i++) { XmtrInfo[i].carrier_dco_incr = 0x1f7b1b9L; // 33010105 * 42.57475 mHz = 1405396.968 Hz XmtrInfo[i].code_dco_incr = 0x16ea4a8L; // 24028328 * 42.57475 mHz = 1023000.058 Hz // start nav message at bit position CounterStartValue (out of 1500) CACode_Counter[i] = 20 * CounterStartValue; } return; } // // calculate GPS C/A signal // static int calc_raw_sgn( void) { int i, j, cidx, didx, nidx, prn; int sgn = 0; int savsgn; short int ca_prompt; char navbit; float sgnflt; char d; // float tmp, savtmp; // nofprn = 0; for ( prn=1; prn<=NOFSAT; prn++) { if ( NavBit[prn]) { // // increment carrier and code cycle counter // Carrier_Cycle[prn] += XmtrInfo[prn].carrier_dco_incr; Code_Cycle[prn] += XmtrInfo[prn].code_dco_incr; // printf(" Carrier_Cycle[%d] = %d\n", prn, Carrier_Cycle[prn]); // printf(" Code_Cycle[%d] = %d\n", prn, Code_Cycle[prn]); // // carrier DCO: 2^27 = 0x8000000 corresponds to 1 carrier cycle (1.4 MHz) // if ( Carrier_Cycle[prn] & (0x1 << 27)) { Carrier_Cycle[prn] &= ~(0x1f << 27); // clear top 5 bits XmtrInfo[prn].carrier_cycle_counter += 1; } // // code DCO: 2^26 = 0x4000000 corresponds to 1/2 chip (2*1.023 MHz) // 2^27 = 0x8000000 corresponds to 1 chip (1.023 MHz) // if ( Code_Cycle[prn] & (0x1 << 26)) { Code_Cycle[prn] &= ~(0x3f << 26); // clear top 6 bits HalfChip_Counter[prn] += 1; } if ( HalfChip_Counter[prn] == 2046) { HalfChip_Counter[prn] = 0; CACode_Counter[prn] += 1; // printf("CACode_Counter[%d] = %d\n", prn, CACode_Counter[prn]); // getchar(); } // wrap around after 1 frame (5 subframes, 5x300 bits) CACode_Counter[prn] = CACode_Counter[prn] % (20*NAVMSGLEN); // // index in sin/cos look-up table (8-phase) // cidx = (Carrier_Cycle[prn] >> 24) & 0x7; didx = HalfChip_Counter[prn]; // now 0,...,2046 didx = (didx % 2046) / 2; // C/A code // assert( didx >= 0 && didx < 1023); // assert( prn >= 1 && prn < 32); ca_prompt = CACode[prn][didx]; // didx=0,...,1022 // for (i=1;i<=32;i++) // for (j=0;j<1023;j++) // { // if ( abs( CACode[i][j]) != 1) // printf("CACode[%d][%d] = %d\n", i,j,CACode[i][j]); // } // getchar(); // if (!( ca_prompt == 1 || ca_prompt == -1)) // { // printf( "ca_prompt = %d\n", ca_prompt); // printf("CACode[%d][%d] = %d\n", prn,didx,CACode[prn][didx]); // getchar(); // } // C/A code nidx = CACode_Counter[prn] / 20; // 20 C/A periods <-> 1 bit // assert( nidx >= 0 && nidx < NAVMSGLEN); navbit = NavBit[prn][nidx%NAVMSGLEN]; // nidx=0,...,1499 // printf("navbit = %d\n", navbit); // resolution is 1/1024 cycles XmtrInfo[prn].carrier_dco_phase = (long)( Carrier_DCO_Cycle[prn] * 1024); sgn += Carrier_DCO_I[cidx] * ca_prompt * navbit; // assert( sgn == 0); // sgn += Carrier_DCO_I[cidx] * ca_prompt; #if 0 if ( 0) { static int ii; printf( "cidx = %d", cidx); printf( " ca = %d", ca_prompt); printf( " carcyc = %.4f", (double)(Carrier_Cycle[prn]) / (double)(0x1L<<27)); // 24+3! printf( " CACode1 = %d", CACode[prn][ii]); printf( " DCO = %d", Carrier_DCO_I[ii%8]); printf( " sgn = %d\n", sgn); if (ii > 20) getchar(); ii += 1; } #endif // printf("sgn = %d\n", sgn); // printf("Carrier_DCO_I = %d, cidx=%d\n", Carrier_DCO_I[cidx], cidx); // printf("ca_prompt = %d, didx = %d\n", ca_prompt, didx); // printf("navbit = %d\n", navbit); // printf("cidx=%d, didx=%d, nidx = %d\n", cidx, didx, nidx); // getchar(); // nofprn += 1; } // --- if ( NavBit[prn]) --- } // --- for ( prn=1; prn <= NOFSAT; prn++) --- // add white noise if ( Noise_Ampl > 0) { sgnflt = (float)( sgn) + Noise_Ampl * randn( 0.0, 1.0); // printf("sgn=%d, sgnflt=%e (Noise_Ampl=%e)\n", sgn, sgnflt, Noise_Ampl); // getchar(); // printf( "noise = %e\n", tmp); // getchar(); // printf("sgn = %d, noise = %e, sum = %e \n", sgn, tmp, sgnflt); // printf("sizeof( float) = %d \n", sizeof( float)); // getchar(); } else sgnflt = (float)( sgn); // quantize and map to [0,1,2,3] sgn = ( sgnflt >= 0.0) ? 1 : -1; if ( fabs( sgnflt) > QuantThresh) sgn *= 3; // map -3,-1,1,3 to 0,1,2,3 sgn = (sgn+3) / 2; return (sgn); } // // main function // int main( int argc, char *argv[]) { int j, nof, sgn, ofs; long i, nofwritten; unsigned long cntMSB; // char outfile[] = "ogsraw.dat"; // default output file name // navfilefmt[] = "navmsg-in-%02d.dat", // navfile[sizeof(navfilefmt)]; // d <= 2 digits! char *outpath, *navpath, *ptr, *navfilefmt, *navfile; float t, dt; // 30 sec <-> 1500 nav bits double samplfrq = 40e6 / 7.0; // sampling frequency double nofsamples = 0.0; FILE *Fp, *FpNav; set_directories( argv[0]); // process options getargs( argc, argv); check_options(); // if ( OutputFileName) // ptr = OutputFileName; // else // ptr = outfile; outpath = conmalloc( strlen( OGSDataDir) + strlen( OutputFileName) + 1); strcpy( outpath, OGSDataDir); strcat( outpath, OutputFileName); // welcome printf("-------------------------------- OpenGPSSim ---------------------------------\n"); printf("ogsxmit version %s\n", Version); printf("Copyright (C) 2001-2006 G. Beyerle, A. Tabernero, C. Kelley and others. \n"); printf("ogsxmit comes with ABSOLUTELY NO WARRANTY; for details see file 'warranty'.\n"); printf("This is free software, and you are welcome to redistribute it under \n"); printf("certain conditions; see file 'copying' for details. \n"); printf("-----------------------------------------------------------------------------\n"); // initialize init_struct_xmitter(); // read parameter controlling signal transmission read_xmit_par(); if ( Noise_dB > -1000.0) Noise_Ampl = pow( 10.0, (double)( Noise_dB)/20.0); else Noise_Ampl = 0.0; srand(1); // initialize random generator // calculate C/A-code and store in global CACode[1,...,NOFSATS][1,..,NOFCHIPS] calc_cacode(); if ( !OverWrite) { Fp = fopen( outpath, "rb"); if ( Fp) { printf("Data file '%s' already exists.\nPlease remove it and try again.\n", outpath); exit(0); } } Fp = fopen( outpath, "wb"); if ( !Fp) { printf( "error opening file '%s'\n", outpath); perror( NULL); exit(-1); } // FILE *TmpFp; // TmpFp = fopen( "C:/home/Src/osgpsim/data/osgraw-c-chr.dat", "w"); // if ( !TmpFp) // { // perror( NULL); // exit(-1); // } // printf( "*** opened C:/home/Src/osgpsim/data/osgraw-c-chr.dat\n"); printf( "\nRead navigation data bits from file(s) ...\n"); // printf( "NavFilePattern = %s\n", NavFilePattern); // getchar(); ptr = strstr( NavFilePattern, "PRN"); if ( !ptr) { printf( "Substring 'PRN' not found in %s.\n", NavFilePattern); exit(-1); } ofs = ptr - NavFilePattern; navfilefmt = conmalloc( strlen( NavFilePattern) + 4); navfile = conmalloc( strlen( NavFilePattern) + 4); strcpy( navfilefmt, NavFilePattern); strcpy( navfilefmt + ofs, "%02d"); strcpy( navfilefmt + ofs + 4, ptr + 3); // printf( "navfilefmt = %s\n", navfilefmt); // getchar(); navpath = conmalloc( strlen( OGSDataDir) + strlen( navfilefmt) + 1); for ( i=1; i<=NOFSAT; i++) { sprintf( navfile, navfilefmt, i); strcpy( navpath, OGSDataDir); strcat( navpath, navfile); FpNav = fopen( navpath, "rb"); if ( FpNav) { printf( " '%s'.\n", navpath); NavBit[i] = (char*) malloc( NAVMSGLEN); if ( !NavBit[i]) { printf( "malloc() failed in %s at line %d\n", __FILE__, __LINE__); exit(-1); } nof = fread( NavBit[i], sizeof( char), NAVMSGLEN, FpNav); if ( nof < NAVMSGLEN) { printf( "read only %d bytes from file '%s'.\n", nof, navpath); exit(-1); } // else // printf( "read %d bytes from file '%s'.\n", nof, navpath); fclose( FpNav); // re-write: 0 -> -1, 1 -> 1 for ( j=0; j 0) ? 1 : -1; } } int foundone = 0; for ( i=1; i<=NOFSAT; i++) { if ( NavBit[i]) foundone = 1; } if ( !foundone) { printf("Not a single file found for pattern >%s<.\n", NavFilePattern); exit(-1); } // for (i=1;i<=32;i++) // for (j=0;j<1023;j++) // { // if ( abs( CACode[i][j]) != 1) // printf("CACode[%d][%d] = %d\n", i,j,CACode[i][j]); // } // TmpFP = fopen( "c:/tmp/testdata.dat", "w"); // if ( !TmpFP) // { // printf( "Error opening file 'c:/tmp/testdata.dat'\n"); // perror( NULL); // exit(-1); // } printf( "\n"); printf( "construct GPS signal, add noise, quantize\n"); printf( "and write to file '%s' ...\n", outpath); // we store 4 times 2 bit (4 level) signal samples into one byte, // fill XmtrBuf[XMTRBUFLEN] and write to file // 4 samples per byte dt = XMTRBUFLEN * 4.0 / samplfrq; for ( t=0; t