bool IQDump::initialize(int argc, char *argv[]) throw() { using namespace gpstk::StringUtils; CommandOptionWithAnyArg inputOpt('i', "input", "Where to get the IQ input from. The default is stdin."), quantizationOpt('q', "quantization", "What type of IQ stream; 1, 2 or f. The default is f."), bandsOpt('b', "bands", "The number of complex samples per epoch. The default is 2."); CommandOptionNoArg statsOpt('s', "stats", "Compute stats on values."); if (!BasicFramework::initialize(argc,argv)) return false; stats = statsOpt.getCount()>0; char quantization='f'; if (quantizationOpt.getCount()) quantization = quantizationOpt.getValue()[0][0]; switch (quantization) { case '1': input = new IQ1Stream(); break; case '2': input = new IQ2Stream(); break; case 'f': default: input = new IQFloatStream(); break; } if (inputOpt.getCount()) { input->open(inputOpt.getValue()[0].c_str()); } else { using std::basic_ios; input->copyfmt(std::cin); input->clear(std::cin.rdstate()); input->basic_ios<char>::rdbuf(std::cin.rdbuf()); input->filename = "<stdin>"; } if (debugLevel) cout << "Taking input from: " << input->filename << endl << "IQStream type: " << input->desc << endl; input->debugLevel = debugLevel; if (bandsOpt.getCount()) bands = asInt(bandsOpt.getValue()[0]); return true; }
bool RxSim::initialize(int argc, char *argv[]) throw() { using namespace gpstk::StringUtils; CommandOptionWithAnyArg codeOpt('c', "code", "The code/carrier to track. ARG takes the form of " "code:carrier:prn:offset:doppler. Code is either c or p. " "Carrier is either 1 or 2. Prn is an integer between 1 and 32. " "Offset is a number in us, Doppler is a number in Hz. Currently, " "only one signal can be specified. For example, to track P code " "on L2 for PRN 3, with no initial time or doppler offset, " "specify -c p:2:3:0:0"), dllAlphaOpt('\0', "dllAlpha", "The gain on the phase update for the code tracker. The " "default is 1e-5 chips/tick"), dllBetaOpt('\0', "dllBeta", "The gain on the frequency update for the code tracker. The " "default is 1e-12 chips/tick"), pllAlphaOpt('\0', "pllAlpha", "The gain on the phase update for the carrier tracker. The " "default is 0.4 cycles/tick"), pllBetaOpt('\0', "pllBeta", "The gain on the frequency update for the carrier tracker. " "The default is 0.1 cycles / iad_period"), sampleRateOpt('r',"sample-rate", "Specifies the nominal sample rate, in MHz. The " "default is 20 MHz."), interFreqOpt('x',"inter-freq", "Specifies the intermediate frequency of the receiver," " in MHz. Default is 0.42 MHz. If there is no down-" "conversion, the IF should be the L1 or L2 carrier" " frequency" ), quantizationOpt('q', "quantization", "They quantization applied to the data. 1, 2 or f. " "The default is f."), gainOpt('g', "gain", "Gain to apply to the if prior to digitization, in dB. Default is 0."), timeLimitOpt('t', "time-limit", "Limit the amount of data to process. Specify time in ms. Defaults to all data."), inputOpt('i', "input", "Where to get the IQ samples from. The default is to use stdin."); CommandOptionWithNumberArg bandsOpt('b', "bands", "The number of complex samples per epoch. The default is 2."); if (!BasicFramework::initialize(argc,argv)) return false; if (timeLimitOpt.getCount()) timeLimit = asDouble(timeLimitOpt.getValue()[0]) * 1e-3; if (!codeOpt.getCount()) { cout << "Must specify a code/carrier to track. Bye." << endl; return false; } string val=codeOpt.getValue()[0]; const char delim(':'); if (numWords(val, delim) != 5) { cout << "Error in code parameter:" << val << endl; return false; } string code = lowerCase(word(val, 0, delim)); band = asInt(word(val, 1, delim)); int prn = asInt(word(val, 2, delim)); double offset = asDouble(word(val, 3, delim)) * 1e-6; double doppler = asDouble(word(val, 4, delim)); CodeGenerator* codeGenPtr; double chipFreq; switch (code[0]) { case 'c': codeGenPtr = new CACodeGenerator(prn); chipFreq = CA_CHIP_FREQ_GPS; break; case 'p': codeGenPtr = new PCodeGenerator(prn); chipFreq = PY_CHIP_FREQ_GPS; break; default: cout << "Unsupported code: " << code << endl; return false; } if (sampleRateOpt.getCount()) timeStep = 1/(asDouble(sampleRateOpt.getValue().front()) * 1e6 ); if (interFreqOpt.getCount()) interFreq = asDouble(interFreqOpt.getValue().front()) * 1e6; // Note that this object is responsible for destroying // the codeGenPtr object cc = new CCReplica(timeStep, chipFreq, interFreq, codeGenPtr); double chips = offset / cc->codeChipLen; cc->moveCodePhase(chips); cc->setCodeFreqOffsetHz(doppler); cc->setCarrierFreqOffsetHz(doppler); double spacing = 0.5 * cc->codeChipLen; if (spacing < timeStep) spacing = timeStep; tr = new EMLTracker(*cc, spacing); if (dllAlphaOpt.getCount()) tr->dllAlpha = asDouble(dllAlphaOpt.getValue()[0]); if (dllBetaOpt.getCount()) tr->dllBeta = asDouble(dllBetaOpt.getValue()[0]); if (pllAlphaOpt.getCount()) tr->pllAlpha = asDouble(pllAlphaOpt.getValue()[0]); if (pllBetaOpt.getCount()) tr->pllBeta = asDouble(pllBetaOpt.getValue()[0]); tr->debugLevel = debugLevel; char quantization='f'; if (quantizationOpt.getCount()) quantization = quantizationOpt.getValue()[0][0]; switch (quantization) { case '1': input = new IQ1Stream(); break; case '2': input = new IQ2Stream(); break; case 'f': default: input = new IQFloatStream(); break; } if (inputOpt.getCount()) { input->open(inputOpt.getValue()[0].c_str()); } else { using std::basic_ios; input->copyfmt(std::cin); input->clear(std::cin.rdstate()); input->basic_ios<char>::rdbuf(std::cin.rdbuf()); input->filename = "<stdin>"; } if (bandsOpt.getCount()) input->bands = asInt(bandsOpt.getValue()[0]); if (gainOpt.getCount()) { double gainDb = StringUtils::asDouble(gainOpt.getValue()[0]); gain = exp10(gainDb/10.); } if (verboseLevel) { cout << "# Taking input from " << input->filename << " (" << input->bands << " samples/epoch)" << endl << "# Rx gain level: " << gain << endl; tr->dump(cout, 1); } return true; }
//----------------------------------------------------------------------------- bool Acquire::initialize(int argc, char *argv[]) throw() { using namespace gpstk::StringUtils; CommandOptionWithAnyArg bandsOpt('b',"bands", "The number of complex samples per epoch. The default is 2. "), periodsOpt('p',"CA-periods", "The number of C/A periods to consider. Default is one, " "odd values recommended because of possible NAV change."), sampleRateOpt('r',"rate", "Specifies the nominal sample rate, in MHz. The " "default is 20 MHz."), interFreqOpt('x',"inter-freq", "Specifies the intermediate frequency of the receiver," " in MHz. Default is 0.42 MHz."), quantizationOpt('q', "quantization", "The quantization applied to the data. 1, 2 or f. " "The default is f."), prnOpt('c',"PRN", "The PRN of the code to acquire. Enter 0 to acquire " "all PRN codes (1 through 32). Default is 1."), inputOpt('i', "input", "Where to get the IQ samples from. The default is to use " "standard input."), searchWidthOpt('w',"search-width", "Width of the doppler search in Hz. " "For example, 20000 would search from -10000 to 10000 Hz. " "Default is 20000."), binWidthOpt('f',"bin-width", "Width of the frequency bins in Hz. Default is 200. " "Bin width should be at most 1000Hz/numPeriods, so " "the default is for up to 5 periods."), heightOpt('z',"height", "The cutoff correlation height for acquisition. This only " "affects our output. A SNR measure should replace this " "eventually. Default is 40"); if (!BasicFramework::initialize(argc,argv)) return false; if (bandsOpt.getCount()) bands = asInt(bandsOpt.getValue()[0]); if (periodsOpt.getCount()) { periods = asInt(periodsOpt.getValue()[0]); numSamples = sampleRate*1e-3*periods; } if (sampleRateOpt.getCount()) { sampleRate = asDouble(sampleRateOpt.getValue().front()) * 1e6; numSamples = sampleRate*1e-3*periods; } if (interFreqOpt.getCount()) interFreq = asDouble(interFreqOpt.getValue().front()) * 1e6; if (prnOpt.getCount()) prn = asInt(prnOpt.getValue()[0]); char quantization='f'; if (quantizationOpt.getCount()) quantization = quantizationOpt.getValue()[0][0]; switch (quantization) { case '1': input = new IQ1Stream(); break; case '2': input = new IQ2Stream(); break; case 'f': default: input = new IQFloatStream(); break; } if (inputOpt.getCount()) { input->open(inputOpt.getValue()[0].c_str()); } else { using std::basic_ios; input->copyfmt(std::cin); input->clear(std::cin.rdstate()); input->basic_ios<char>::rdbuf(std::cin.rdbuf()); input->filename = "<stdin>"; } if(searchWidthOpt.getCount()) { freqSearchWidth = asDouble(searchWidthOpt.getValue().front()); bins = freqSearchWidth / freqBinWidth + 1; } if(binWidthOpt.getCount()) { freqBinWidth = asDouble(binWidthOpt.getValue().front()); bins = freqSearchWidth / freqBinWidth + 1; } if(heightOpt.getCount()) { height = asInt(heightOpt.getValue().front()); } return true; }
bool Corltr::initialize(int argc, char *argv[]) throw() { using namespace gpstk::StringUtils; CommandOptionWithAnyArg windowOpt('w', "window", "Specifies how wide a window to use, in us. The default " "is 1023 us."), sampleRateOpt('r',"sample-rate", "Specifies the nominal sample rate, in MHz. The " "default is 20 MHz."), interFreqOpt('x',"inter-freq", "Specifies the intermediate frequency of the receiver," " in MHz. Default is 0.42 MHz. If there is no down-" "conversion, the IF should be the L1 or L2 carrier" " frequency" ), quantizationOpt('q', "quantization", "The quantization applied to the data. 1, 2 or f. " "The default is f."), codeOpt('c', "code", "The code/carrier to track. ARG takes the form of " "code:carrier:prn:offset:doppler. Code is either c or p. " "Carrier is either 1 or 2. Prn is an integer between 1 and 32. " "Offset is a number in us, Doppler is a number in Hz. Currently, " "only one signal can be specified. For example, to track P code " "on L2 for PRN 3, with no initial time or doppler offset, " "specify -c p:2:3:0:0"), freqErrOpt('f', "freq-err", "Specify the frequency error on the local receiver's " "oscilator, in ppm. The default is 0 ppm"), inputOpt('i', "input", "Where to get the IQ samples from. The default is to use " "standard input."); CommandOptionWithNumberArg stepsOpt('s', "steps", "The number of 1/4 chip steps to take. Defaults to 4092."), bandsOpt('b', "bands", "The number of complex samples per epoch. The default is 2."); CommandOptionNoArg peakOnlyOpt('p', "peak", "Only output the peak correlation/snr values."); if (!BasicFramework::initialize(argc,argv)) return false; peakOnly = peakOnlyOpt.getCount()>0; if (sampleRateOpt.getCount()) timeStep = 1/(asDouble(sampleRateOpt.getValue().front()) * 1e6 ); if (interFreqOpt.getCount()) interFreq = asDouble(interFreqOpt.getValue().front()) * 1e6; if (windowOpt.getCount()) window = asDouble(windowOpt.getValue().front()) * 1e-6; else window = 1.023e-3; if (freqErrOpt.getCount()) freqErr = StringUtils::asDouble(freqErrOpt.getValue()[0]) * 1e-6; else freqErr = 0; char quantization='f'; if (quantizationOpt.getCount()) quantization = quantizationOpt.getValue()[0][0]; switch (quantization) { case '1': input = new IQ1Stream(); break; case '2': input = new IQ2Stream(); break; case 'f': default: input = new IQFloatStream(); break; } if (inputOpt.getCount()) { input->open(inputOpt.getValue()[0].c_str()); } else { using std::basic_ios; input->copyfmt(std::cin); input->clear(std::cin.rdstate()); input->basic_ios<char>::rdbuf(std::cin.rdbuf()); input->filename = "<stdin>"; } if (verboseLevel) cout << "# IQStream type: " << input->desc << endl; if (bandsOpt.getCount()) bands = asInt(bandsOpt.getValue()[0]); if (stepsOpt.getCount()) steps = asInt(stepsOpt.getValue()[0]); if (!codeOpt.getCount()) { cout << "Must specify a code/carrier to track. Bye." << endl; return false; } string val=codeOpt.getValue()[0]; const char delim(':'); if (numWords(val, delim) != 5) { cout << "Error in code parameter:" << val << endl; return false; } string code = lowerCase(word(val, 0, delim)); int band = asInt(word(val, 1, delim)); #pragma unused(band) int prn = asInt(word(val, 2, delim)); offset = asDouble(word(val, 3, delim)) * 1e-6; doppler = asDouble(word(val, 4, delim)); CodeGenerator* codeGenPtr; double chipFreq; switch (code[0]) { case 'c': codeGenPtr = new CACodeGenerator(prn); chipFreq = CA_CHIP_FREQ_GPS; break; case 'p': codeGenPtr = new PCodeGenerator(prn); chipFreq = PY_CHIP_FREQ_GPS; break; default: cout << "Unsupported code: " << code << endl; return false; } cc = new CCReplica(timeStep, chipFreq, interFreq, codeGenPtr); return true; }
bool GpsSim::initialize(int argc, char *argv[]) throw() { CommandOptionWithAnyArg codeOpt('c', "code", "Generate the signal defined by the argument. ARG takes " "the form of code:carrier:prn:offset:doppler:nav. Code is either " "c, p, or cp. Carrier is either 1 or 2. Prn is an integer between 1 " "and 32. Offset is a number in microseconds. Doppler is a number " "in Hz. Nav is 0, c, p, or cp. For example, to generate C/A on L1 for " "PRN 15 with zero time-offset, zero doppler, a dummy nav signal " "on both C/A and P, then specify -c c:1:15:0:p. This option " "may be repeated to simulate multiple signals."); CommandOptionNoArg codeOnlyOpt('\0', "code-only", "Only generate the codes. No carrier, no hetrodyning."); CommandOptionWithAnyArg sampleRateOpt('r',"sample-rate", "Specifies the nominal sample rate, in MHz. The " "default is 20 MHz."); CommandOptionWithAnyArg interFreqOpt('x',"inter-freq", "Specifies the intermediate frequency of the receiver," " in MHz. Default is 0.42 MHz."); CommandOptionWithAnyArg quantizationOpt('q', "quantization", "What type of IQ stream; 1, 2 or f. The default is f."); CommandOptionWithAnyArg gainOpt('g', "gain", "Gain to apply to the if prior to digitization, in dB. Default is 0."); CommandOptionWithAnyArg noiseGainOpt('n', "noise", "Specify the gain (in dB) for the receiver's noise. The " "default is 0 dB"); CommandOptionWithAnyArg freqErrOpt('f', "freq-err", "Specify the frequency error on the local receiver's " "oscilator, in ppm. The default is 0 ppm"); CommandOptionWithAnyArg runTimeOpt('t', "run-time", "How long (in ms) to run the simulation for. The default is 20 ms"); CommandOptionWithAnyArg outputOpt('o', "output", "Where to write the output. The default is stdout"); if (!BasicFramework::initialize(argc,argv)) return false; using namespace gpstk::StringUtils; char quantization='f'; if (quantizationOpt.getCount()) quantization = quantizationOpt.getValue()[0][0]; switch (quantization) { case '1': output = new IQ1Stream(); break; case '2': output = new IQ2Stream(); break; case 'f': default: output = new IQFloatStream(); break; } if (sampleRateOpt.getCount()){ rx_sample_rate = asDouble(sampleRateOpt.getValue().front()) * 1e6; time_step = 1.0/rx_sample_rate; samples_per_period = rx_sample_rate / 1e6;} if (interFreqOpt.getCount()){ interFreq = asDouble(interFreqOpt.getValue().front()) * 1e6; rx_L1_LO = gpstk::L1_FREQ_GPS - interFreq; rx_L2_LO = gpstk::L2_FREQ_GPS - interFreq;} if (outputOpt.getCount()) { output->open(outputOpt.getValue()[0].c_str(), ios::out); } else { using std::basic_ios; output->copyfmt(std::cout); output->clear(std::cout.rdstate()); output->basic_ios<char>::rdbuf(std::cout.rdbuf()); output->filename = "<stdout>"; } if (debugLevel) cout << "Writing data to " << output->filename << endl; if (gainOpt.getCount()) { double gainDb = StringUtils::asDouble(gainOpt.getValue()[0]); gain = exp10(gainDb/10); if (debugLevel) cout << "# Rx gain level: " << gainDb << " db (" << gain << ")" << endl; } if (noiseGainOpt.getCount()) { double gain_local = StringUtils::asDouble(noiseGainOpt.getValue()[0]); noise_amplitude *= exp10(gain_local/10); if (debugLevel) cout << "# Noise level: " << gain_local << " db" << endl; } if (codeOnlyOpt.getCount()) codeOnly = true; if (freqErrOpt.getCount()) freqErr = StringUtils::asDouble(freqErrOpt.getValue()[0]) * 1e-6; else freqErr = 0; if (debugLevel) cout << "# Receiver frequency error: " << freqErr * 1e6 << " ppm" << endl; if (runTimeOpt.getCount()) { double rt = asDouble(runTimeOpt.getValue()[0]); periods_to_generate = static_cast<long unsigned>(rt*1.0e6); } if (debugLevel) cout << "# Running for : " << periods_to_generate << " periods (" << 1e3 * periods_to_generate/1.0e6 << " msec)" << endl; // Compute the local oscilator frequencies, units seem to be radians/sample omega_lo.resize(LO_COUNT); omega_lo[0] = 2.0*gpstk::PI*rx_L1_LO/rx_sample_rate; omega_lo[1] = 2.0*gpstk::PI*rx_L2_LO/rx_sample_rate; vector<double> lo(LO_COUNT); lo[0] = omega_lo[0]/time_step / 2 /PI; lo[1] = omega_lo[1]/time_step / 2 /PI; if (debugLevel) cout << "# LO 1: " << setw(7) << lo[0] * 1e-6<< " MHz" << " 2: " << setw(7) << lo[1] * 1e-6<< " MHz" << endl << "# IF 1: " << setw(7) << (L1_FREQ_GPS - lo[0]) * 1e-3<< " kHz" << " 2: " << setw(7) << (L2_FREQ_GPS - lo[1]) * 1e-3<< " kHz" << endl; for (int i=0; i < codeOpt.getCount(); i++) { string val=codeOpt.getValue()[i]; const char delim(':'); if (numWords(val, delim) != 6) { cout << "Error in code parameter:" << val << endl; exit(-1); } string code = lowerCase(word(val, 0, delim)); int band = asInt(word(val, 1, delim)); int prn = asInt(word(val, 2, delim)); double offset = asDouble(word(val, 3, delim)); double doppler = asDouble(word(val, 4, delim)); string nav = lowerCase(word(val, 5, delim)); if (code.size() > 2 || nav.size() > 2 || band <1 || band > LO_COUNT || prn < 1 || prn >32) { cout << "code:" << code << " band:" << band << " prn:" << prn << " offset:" << offset << " nav:" << nav << endl << "Error in specifying code. Ignoring this code." << endl; exit(-1); } // This is the number of P code chips in one sample. If this // is not around or less than 1/2, we have a problem double sampleRate = 1.0/(rx_sample_rate); //sec double chips_per_sample_base = gpstk::PY_CHIP_FREQ_GPS * sampleRate; switch(band) { case 1: doppler *= sampleRate / L1_MULT_GPS; break; case 2: doppler *= sampleRate / L2_MULT_GPS; break; } doppler *= 1-freqErr; chips_per_sample_base *= 1-freqErr; // Create and configure the SV source SVSource* src = new SVSource(prn, band); src->zchips_per_sample = chips_per_sample_base; src->doppler = doppler; src->ca_modulation = isLike(code, "c"); src->p_modulation = isLike(code, "p"); src->ca_nav = isLike(nav, "c") && src->ca_modulation; src->p_nav = isLike(nav, "p") && src->p_modulation; src->p_amplitude = p_amplitude; src->ca_amplitude = ca_amplitude; // offset needs to be provided to the SVSource in units of P chips src->slewZChipFraction(offset * gpstk::PY_CHIP_FREQ_GPS * 1.0e-6); if (codeOnlyOpt.getCount()) src->code_only = true; if (debugLevel) src->dump(cout); sv_sources.push_back(src); } return true; }