diff --git a/Makefile b/Makefile index b741004..4f6933f 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,8 @@ all: gps-sdr-sim SHELL=/bin/bash CC=gcc -CFLAGS=-fopenmp -O3 -Wall -LDFLAGS=-lm -fopenmp +CFLAGS=-O3 -Wall +LDFLAGS=-lm gps-sdr-sim: gpssim.o ${CC} $< ${LDFLAGS} -o $@ @@ -15,5 +15,6 @@ clean: rm -f gpssim.o gps-sdr-sim *.bin time: gps-sdr-sim + time ./gps-sdr-sim -e brdc3540.14n -u circle.csv -b 1 time ./gps-sdr-sim -e brdc3540.14n -u circle.csv -b 8 time ./gps-sdr-sim -e brdc3540.14n -u circle.csv -b 16 diff --git a/README.md b/README.md index a784fe5..8283b44 100644 --- a/README.md +++ b/README.md @@ -10,15 +10,12 @@ to RF using software-defined radio (SDR) platforms, such as 2. Create an empty project for a console application. 3. On the Solution Explorer at right, add "gpssim.c" and "getopt.c" to the Souce Files folder. 4. Select "Release" in Solution Configurations drop-down list. -5. Open the Property Pages dialog box and expand the Configuration Properties. -6. Expand the C/C++ node and select the Language property page. -7. Enable the OpenMP Support (/openmp). -8. Build the solution. +5. Build the solution. ### Building with GCC ``` -$ gcc gpssim.c -lm -fopenmp -o gps-sdr-sim +$ gcc gpssim.c -lm -O3 -o gps-sdr-sim ``` ### Generating the GPS signal file @@ -40,11 +37,23 @@ then used to generate the digitized I/Q samples for the GPS signal. The bladeRF command line interface requires I/Q pairs stored as signed 16-bit integers, while the hackrf_transfer and gps-sdr-sim-uhd.py -supports signed bytes. +support signed bytes. HackRF and bladeRF require 2.6 MHz sample rate, while the USRP2 requires 2.5 MHz (an even integral decimator of 100 MHz). +The simulation start time can be specified if the corresponding set of ephemerides +is available. Otherwise the first time of ephemeris in the RINEX navigation file +is selected. + +The maximum simulation duration time is defined by USER_MOTION_SIZE to +prevent the output file from getting too large. + +The output file size can be reduced by using "-b 1" option to store +four 1-bit I/Q samples into a single byte. +You can use [bladeplayer](https://github.com/osqzss/gps-sdr-sim/tree/master/player) +for bladeRF to playback the compressed file. + ``` Usage: gps-sdr-sim [options] Options: @@ -52,23 +61,26 @@ Options: -u User motion file (dynamic mode) -g NMEA GGA stream (dynamic mode) -l Lat,Lon,Hgt (static mode) e.g. 30.286502,120.032669,100 + -t Scenario start time YYYY/MM/DD,hh:mm:ss + -d Duration [sec] (max: 300) -o I/Q sampling data file (default: gpssim.bin) -s Sampling frequency [Hz] (default: 2600000) - -b I/Q data format [8/16] (default: 8) + -b I/Q data format [1/8/16] (default: 16) + -v Show details about simulated channels ``` The user motion can be specified in either dynamic or static mode: ``` -> gps-sdr-sim -e brdc3540.14n -u circle.csv -b 16 +> gps-sdr-sim -e brdc3540.14n -u circle.csv ``` ``` -> gps-sdr-sim -e brdc3540.14n -g triumphv3.txt -b 16 +> gps-sdr-sim -e brdc3540.14n -g triumphv3.txt ``` ``` -> gps-sdr-sim -e brdc3540.14n -l 30.286502,120.032669,100 -b 16 +> gps-sdr-sim -e brdc3540.14n -l 30.286502,120.032669,100 ``` ### Transmitting the samples diff --git a/extclk/Readme.md b/extclk/Readme.md new file mode 100644 index 0000000..88efa64 --- /dev/null +++ b/extclk/Readme.md @@ -0,0 +1,21 @@ +# HackRF External TCXO + +### Gerber Files + +| File | Layer | +|:-----------|:------------------------| +| extclk.GTL | Top layer | +| extclk.GBL | Bottom layer | +| extclk.GTS | Top solder stop mask | +| extclk.GBS | Bottom solder stop mask | +| extclk.GTO | Top silk mask | +| extclk.TXT | NC Drill | +| extclk.GML | Mechanical layer | + +### BOM (bill of material) + +| Part | Value | +|:-----|:------| +|X1 |[FOX924B-10.000](http://www.digikey.com/product-detail/en/FOX924B-10.000/631-1067-1-ND/1024772), TCXO 10MHz HCMOS 2.5ppm| +|C1 |CAP 1uF 0805| +|C2 |OPEN| diff --git a/extclk/extclk.GBL b/extclk/extclk.GBL new file mode 100644 index 0000000..c692667 --- /dev/null +++ b/extclk/extclk.GBL @@ -0,0 +1,720 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +%ADD11C,0.0594*% +%ADD12C,0.0277*% +%ADD13C,0.0079*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +D11* +X003971Y002504D03* +X003971Y003504D03* +X003971Y004504D03* +X003971Y005504D03* +X003971Y006504D03* +X003971Y007504D03* +X004971Y007504D03* +X004971Y006504D03* +X004971Y005504D03* +X004971Y004504D03* +X004971Y003504D03* +X004971Y002504D03* +D12* +X003133Y003390D03* +X003172Y005358D03* +X003133Y007366D03* +X001322Y008351D03* +X005022Y008351D03* +X001322Y002445D03* +D13* +X000724Y002473D02* +X003556Y002473D01* +X003556Y002422D02* +X003619Y002269D01* +X003736Y002152D01* +X003889Y002089D01* +X004054Y002089D01* +X004206Y002152D01* +X004323Y002269D01* +X004386Y002422D01* +X004386Y002587D01* +X004323Y002739D01* +X004206Y002856D01* +X004054Y002919D01* +X003889Y002919D01* +X003736Y002856D01* +X003619Y002739D01* +X003556Y002587D01* +X003556Y002422D01* +X003567Y002395D02* +X000724Y002395D01* +X000724Y002318D02* +X003599Y002318D01* +X003647Y002241D02* +X000724Y002241D01* +X000724Y002164D02* +X003725Y002164D01* +X003556Y002550D02* +X000724Y002550D01* +X000724Y002627D02* +X003573Y002627D01* +X003605Y002705D02* +X000724Y002705D01* +X000724Y002782D02* +X003662Y002782D01* +X003744Y002859D02* +X000724Y002859D01* +X000724Y002936D02* +X005463Y002936D01* +X005463Y002859D02* +X005198Y002859D01* +X005206Y002856D02* +X005054Y002919D01* +X004889Y002919D01* +X004736Y002856D01* +X004619Y002739D01* +X004556Y002587D01* +X004556Y002422D01* +X004619Y002269D01* +X004736Y002152D01* +X004889Y002089D01* +X005054Y002089D01* +X005206Y002152D01* +X005323Y002269D01* +X005386Y002422D01* +X005386Y002587D01* +X005323Y002739D01* +X005206Y002856D01* +X005280Y002782D02* +X005463Y002782D01* +X005463Y002705D02* +X005337Y002705D01* +X005369Y002627D02* +X005463Y002627D01* +X005463Y002550D02* +X005386Y002550D01* +X005386Y002473D02* +X005463Y002473D01* +X005463Y002395D02* +X005375Y002395D01* +X005343Y002318D02* +X005463Y002318D01* +X005463Y002241D02* +X005295Y002241D01* +X005218Y002164D02* +X005463Y002164D01* +X005463Y002086D02* +X000724Y002086D01* +X000724Y002044D02* +X000724Y008752D01* +X005463Y008752D01* +X005463Y002044D01* +X000724Y002044D01* +X000724Y003014D02* +X005463Y003014D01* +X005463Y003091D02* +X005114Y003091D01* +X005058Y003068D02* +X005218Y003134D01* +X005341Y003257D01* +X005407Y003417D01* +X005407Y003465D01* +X005011Y003465D01* +X005011Y003543D01* +X005407Y003543D01* +X005407Y003591D01* +X005341Y003751D01* +X005218Y003874D01* +X005058Y003940D01* +X005010Y003940D01* +X005010Y003544D01* +X004932Y003544D01* +X004932Y003940D01* +X004884Y003940D01* +X004724Y003874D01* +X004601Y003751D01* +X004535Y003591D01* +X004535Y003543D01* +X004932Y003543D01* +X004932Y003465D01* +X004535Y003465D01* +X004535Y003417D01* +X004601Y003257D01* +X004724Y003134D01* +X004884Y003068D01* +X004932Y003068D01* +X004932Y003465D01* +X005010Y003465D01* +X005010Y003068D01* +X005058Y003068D01* +X005010Y003091D02* +X004932Y003091D01* +X004932Y003168D02* +X005010Y003168D01* +X005010Y003246D02* +X004932Y003246D01* +X004932Y003323D02* +X005010Y003323D01* +X005010Y003400D02* +X004932Y003400D01* +X004932Y003477D02* +X004386Y003477D01* +X004386Y003422D02* +X004386Y003587D01* +X004323Y003739D01* +X004206Y003856D01* +X004054Y003919D01* +X003889Y003919D01* +X003736Y003856D01* +X003619Y003739D01* +X003556Y003587D01* +X003556Y003422D01* +X003619Y003269D01* +X003736Y003152D01* +X003889Y003089D01* +X004054Y003089D01* +X004206Y003152D01* +X004323Y003269D01* +X004386Y003422D01* +X004377Y003400D02* +X004542Y003400D01* +X004574Y003323D02* +X004345Y003323D01* +X004300Y003246D02* +X004613Y003246D01* +X004690Y003168D02* +X004222Y003168D01* +X004058Y003091D02* +X004828Y003091D01* +X004744Y002859D02* +X004198Y002859D01* +X004280Y002782D02* +X004662Y002782D01* +X004605Y002705D02* +X004337Y002705D01* +X004369Y002627D02* +X004573Y002627D01* +X004556Y002550D02* +X004386Y002550D01* +X004386Y002473D02* +X004556Y002473D01* +X004567Y002395D02* +X004375Y002395D01* +X004343Y002318D02* +X004599Y002318D01* +X004647Y002241D02* +X004295Y002241D01* +X004218Y002164D02* +X004725Y002164D01* +X005252Y003168D02* +X005463Y003168D01* +X005463Y003246D02* +X005330Y003246D01* +X005368Y003323D02* +X005463Y003323D01* +X005463Y003400D02* +X005400Y003400D01* +X005463Y003477D02* +X005011Y003477D01* +X005010Y003555D02* +X004932Y003555D01* +X004932Y003632D02* +X005010Y003632D01* +X005010Y003709D02* +X004932Y003709D01* +X004932Y003787D02* +X005010Y003787D01* +X005010Y003864D02* +X004932Y003864D01* +X004714Y003864D02* +X004187Y003864D01* +X004276Y003787D02* +X004637Y003787D01* +X004584Y003709D02* +X004335Y003709D01* +X004367Y003632D02* +X004552Y003632D01* +X004535Y003555D02* +X004386Y003555D01* +X004206Y004152D02* +X004054Y004089D01* +X003889Y004089D01* +X003736Y004152D01* +X003619Y004269D01* +X003556Y004422D01* +X003556Y004587D01* +X003619Y004739D01* +X003736Y004856D01* +X003889Y004919D01* +X004054Y004919D01* +X004206Y004856D01* +X004323Y004739D01* +X004386Y004587D01* +X004386Y004422D01* +X004323Y004269D01* +X004206Y004152D01* +X004227Y004173D02* +X004715Y004173D01* +X004736Y004152D02* +X004889Y004089D01* +X005054Y004089D01* +X005206Y004152D01* +X005323Y004269D01* +X005386Y004422D01* +X005386Y004587D01* +X005323Y004739D01* +X005206Y004856D01* +X005054Y004919D01* +X004889Y004919D01* +X004736Y004856D01* +X004619Y004739D01* +X004556Y004587D01* +X004556Y004422D01* +X004619Y004269D01* +X004736Y004152D01* +X004638Y004250D02* +X004304Y004250D01* +X004347Y004328D02* +X004595Y004328D01* +X004563Y004405D02* +X004379Y004405D01* +X004386Y004482D02* +X004556Y004482D01* +X004556Y004559D02* +X004386Y004559D01* +X004365Y004637D02* +X004577Y004637D01* +X004609Y004714D02* +X004333Y004714D01* +X004271Y004791D02* +X004671Y004791D01* +X004767Y004869D02* +X004176Y004869D01* +X004081Y005100D02* +X004861Y005100D01* +X004889Y005089D02* +X005054Y005089D01* +X005206Y005152D01* +X005323Y005269D01* +X005386Y005422D01* +X005386Y005587D01* +X005323Y005739D01* +X005206Y005856D01* +X005054Y005919D01* +X004889Y005919D01* +X004736Y005856D01* +X004619Y005739D01* +X004556Y005587D01* +X004556Y005422D01* +X004619Y005269D01* +X004736Y005152D01* +X004889Y005089D01* +X005081Y005100D02* +X005463Y005100D01* +X005463Y005023D02* +X000724Y005023D01* +X000724Y004946D02* +X005463Y004946D01* +X005463Y004869D02* +X005176Y004869D01* +X005271Y004791D02* +X005463Y004791D01* +X005463Y004714D02* +X005333Y004714D01* +X005365Y004637D02* +X005463Y004637D01* +X005463Y004559D02* +X005386Y004559D01* +X005386Y004482D02* +X005463Y004482D01* +X005463Y004405D02* +X005379Y004405D01* +X005347Y004328D02* +X005463Y004328D01* +X005463Y004250D02* +X005304Y004250D01* +X005227Y004173D02* +X005463Y004173D01* +X005463Y004096D02* +X005070Y004096D01* +X004873Y004096D02* +X004070Y004096D01* +X003873Y004096D02* +X000724Y004096D01* +X000724Y004173D02* +X003715Y004173D01* +X003638Y004250D02* +X000724Y004250D01* +X000724Y004328D02* +X003595Y004328D01* +X003563Y004405D02* +X000724Y004405D01* +X000724Y004482D02* +X003556Y004482D01* +X003556Y004559D02* +X000724Y004559D01* +X000724Y004637D02* +X003577Y004637D01* +X003609Y004714D02* +X000724Y004714D01* +X000724Y004791D02* +X003671Y004791D01* +X003767Y004869D02* +X000724Y004869D01* +X000724Y005100D02* +X003861Y005100D01* +X003889Y005089D02* +X004054Y005089D01* +X004206Y005152D01* +X004323Y005269D01* +X004386Y005422D01* +X004386Y005587D01* +X004323Y005739D01* +X004206Y005856D01* +X004054Y005919D01* +X003889Y005919D01* +X003736Y005856D01* +X003619Y005739D01* +X003556Y005587D01* +X003556Y005422D01* +X003619Y005269D01* +X003736Y005152D01* +X003889Y005089D01* +X003711Y005178D02* +X000724Y005178D01* +X000724Y005255D02* +X003633Y005255D01* +X003593Y005332D02* +X000724Y005332D01* +X000724Y005410D02* +X003561Y005410D01* +X003556Y005487D02* +X000724Y005487D01* +X000724Y005564D02* +X003556Y005564D01* +X003579Y005641D02* +X000724Y005641D01* +X000724Y005719D02* +X003611Y005719D01* +X003676Y005796D02* +X000724Y005796D01* +X000724Y005873D02* +X003778Y005873D01* +X003889Y006089D02* +X004054Y006089D01* +X004206Y006152D01* +X004323Y006269D01* +X004386Y006422D01* +X004386Y006587D01* +X004323Y006739D01* +X004206Y006856D01* +X004054Y006919D01* +X003889Y006919D01* +X003736Y006856D01* +X003619Y006739D01* +X003556Y006587D01* +X003556Y006422D01* +X003619Y006269D01* +X003736Y006152D01* +X003889Y006089D01* +X003850Y006105D02* +X000724Y006105D01* +X000724Y006028D02* +X005463Y006028D01* +X005463Y006105D02* +X005092Y006105D01* +X005054Y006089D02* +X005206Y006152D01* +X005323Y006269D01* +X005386Y006422D01* +X005386Y006587D01* +X005323Y006739D01* +X005206Y006856D01* +X005054Y006919D01* +X004889Y006919D01* +X004736Y006856D01* +X004619Y006739D01* +X004556Y006587D01* +X004556Y006422D01* +X004619Y006269D01* +X004736Y006152D01* +X004889Y006089D01* +X005054Y006089D01* +X005164Y005873D02* +X005463Y005873D01* +X005463Y005796D02* +X005266Y005796D01* +X005331Y005719D02* +X005463Y005719D01* +X005463Y005641D02* +X005363Y005641D01* +X005386Y005564D02* +X005463Y005564D01* +X005463Y005487D02* +X005386Y005487D01* +X005381Y005410D02* +X005463Y005410D01* +X005463Y005332D02* +X005349Y005332D01* +X005309Y005255D02* +X005463Y005255D01* +X005463Y005178D02* +X005232Y005178D01* +X004711Y005178D02* +X004232Y005178D01* +X004309Y005255D02* +X004633Y005255D01* +X004593Y005332D02* +X004349Y005332D01* +X004381Y005410D02* +X004561Y005410D01* +X004556Y005487D02* +X004386Y005487D01* +X004386Y005564D02* +X004556Y005564D01* +X004579Y005641D02* +X004363Y005641D01* +X004331Y005719D02* +X004611Y005719D01* +X004676Y005796D02* +X004266Y005796D01* +X004164Y005873D02* +X004778Y005873D01* +X004850Y006105D02* +X004092Y006105D01* +X004236Y006182D02* +X004706Y006182D01* +X004629Y006260D02* +X004314Y006260D01* +X004351Y006337D02* +X004591Y006337D01* +X004559Y006414D02* +X004383Y006414D01* +X004386Y006491D02* +X004556Y006491D01* +X004556Y006569D02* +X004386Y006569D01* +X004361Y006646D02* +X004581Y006646D01* +X004613Y006723D02* +X004330Y006723D01* +X004261Y006801D02* +X004681Y006801D01* +X004789Y006878D02* +X004153Y006878D01* +X004054Y007089D02* +X004206Y007152D01* +X004323Y007269D01* +X004386Y007422D01* +X004386Y007587D01* +X004323Y007739D01* +X004206Y007856D01* +X004054Y007919D01* +X003889Y007919D01* +X003736Y007856D01* +X003619Y007739D01* +X003556Y007587D01* +X003556Y007422D01* +X003619Y007269D01* +X003736Y007152D01* +X003889Y007089D01* +X004054Y007089D01* +X004104Y007110D02* +X004839Y007110D01* +X004889Y007089D02* +X005054Y007089D01* +X005206Y007152D01* +X005323Y007269D01* +X005386Y007422D01* +X005386Y007587D01* +X005323Y007739D01* +X005206Y007856D01* +X005054Y007919D01* +X004889Y007919D01* +X004736Y007856D01* +X004619Y007739D01* +X004556Y007587D01* +X004556Y007422D01* +X004619Y007269D01* +X004736Y007152D01* +X004889Y007089D01* +X004701Y007187D02* +X004241Y007187D01* +X004318Y007264D02* +X004624Y007264D01* +X004589Y007342D02* +X004353Y007342D01* +X004385Y007419D02* +X004557Y007419D01* +X004556Y007496D02* +X004386Y007496D01* +X004386Y007573D02* +X004556Y007573D01* +X004583Y007651D02* +X004360Y007651D01* +X004328Y007728D02* +X004615Y007728D01* +X004686Y007805D02* +X004257Y007805D01* +X004142Y007883D02* +X004801Y007883D01* +X005142Y007883D02* +X005463Y007883D01* +X005463Y007960D02* +X000724Y007960D01* +X000724Y008037D02* +X005463Y008037D01* +X005463Y008114D02* +X000724Y008114D01* +X000724Y008192D02* +X005463Y008192D01* +X005463Y008269D02* +X000724Y008269D01* +X000724Y008346D02* +X005463Y008346D01* +X005463Y008424D02* +X000724Y008424D01* +X000724Y008501D02* +X005463Y008501D01* +X005463Y008578D02* +X000724Y008578D01* +X000724Y008655D02* +X005463Y008655D01* +X005463Y008733D02* +X000724Y008733D01* +X000724Y007883D02* +X003801Y007883D01* +X003686Y007805D02* +X000724Y007805D01* +X000724Y007728D02* +X003615Y007728D01* +X003583Y007651D02* +X000724Y007651D01* +X000724Y007573D02* +X003556Y007573D01* +X003556Y007496D02* +X000724Y007496D01* +X000724Y007419D02* +X003557Y007419D01* +X003589Y007342D02* +X000724Y007342D01* +X000724Y007264D02* +X003624Y007264D01* +X003701Y007187D02* +X000724Y007187D01* +X000724Y007110D02* +X003839Y007110D01* +X003789Y006878D02* +X000724Y006878D01* +X000724Y006955D02* +X005463Y006955D01* +X005463Y006878D02* +X005153Y006878D01* +X005261Y006801D02* +X005463Y006801D01* +X005463Y006723D02* +X005330Y006723D01* +X005361Y006646D02* +X005463Y006646D01* +X005463Y006569D02* +X005386Y006569D01* +X005386Y006491D02* +X005463Y006491D01* +X005463Y006414D02* +X005383Y006414D01* +X005351Y006337D02* +X005463Y006337D01* +X005463Y006260D02* +X005314Y006260D01* +X005236Y006182D02* +X005463Y006182D01* +X005463Y005951D02* +X000724Y005951D01* +X000724Y006182D02* +X003706Y006182D01* +X003629Y006260D02* +X000724Y006260D01* +X000724Y006337D02* +X003591Y006337D01* +X003559Y006414D02* +X000724Y006414D01* +X000724Y006491D02* +X003556Y006491D01* +X003556Y006569D02* +X000724Y006569D01* +X000724Y006646D02* +X003581Y006646D01* +X003613Y006723D02* +X000724Y006723D01* +X000724Y006801D02* +X003681Y006801D01* +X005104Y007110D02* +X005463Y007110D01* +X005463Y007187D02* +X005241Y007187D01* +X005318Y007264D02* +X005463Y007264D01* +X005463Y007342D02* +X005353Y007342D01* +X005385Y007419D02* +X005463Y007419D01* +X005463Y007496D02* +X005386Y007496D01* +X005386Y007573D02* +X005463Y007573D01* +X005463Y007651D02* +X005360Y007651D01* +X005328Y007728D02* +X005463Y007728D01* +X005463Y007805D02* +X005257Y007805D01* +X005463Y007032D02* +X000724Y007032D01* +X000724Y004018D02* +X005463Y004018D01* +X005463Y003941D02* +X000724Y003941D01* +X000724Y003864D02* +X003755Y003864D01* +X003667Y003787D02* +X000724Y003787D01* +X000724Y003709D02* +X003607Y003709D01* +X003575Y003632D02* +X000724Y003632D01* +X000724Y003555D02* +X003556Y003555D01* +X003556Y003477D02* +X000724Y003477D01* +X000724Y003400D02* +X003565Y003400D01* +X003597Y003323D02* +X000724Y003323D01* +X000724Y003246D02* +X003643Y003246D01* +X003720Y003168D02* +X000724Y003168D01* +X000724Y003091D02* +X003884Y003091D01* +X005228Y003864D02* +X005463Y003864D01* +X005463Y003787D02* +X005306Y003787D01* +X005358Y003709D02* +X005463Y003709D01* +X005463Y003632D02* +X005390Y003632D01* +X005407Y003555D02* +X005463Y003555D01* +M02* diff --git a/extclk/extclk.GBS b/extclk/extclk.GBS new file mode 100644 index 0000000..d376d07 --- /dev/null +++ b/extclk/extclk.GBS @@ -0,0 +1,31 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +%ADD11C,0.0634*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +D11* +X003971Y002504D03* +X003971Y003504D03* +X003971Y004504D03* +X003971Y005504D03* +X003971Y006504D03* +X003971Y007504D03* +X004971Y007504D03* +X004971Y006504D03* +X004971Y005504D03* +X004971Y004504D03* +X004971Y003504D03* +X004971Y002504D03* +M02* diff --git a/extclk/extclk.GML b/extclk/extclk.GML new file mode 100644 index 0000000..87f5065 --- /dev/null +++ b/extclk/extclk.GML @@ -0,0 +1,17 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +M02* diff --git a/extclk/extclk.GTL b/extclk/extclk.GTL new file mode 100644 index 0000000..0ade230 --- /dev/null +++ b/extclk/extclk.GTL @@ -0,0 +1,1172 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +%ADD11C,0.0594*% +%ADD12R,0.0394X0.0492*% +%ADD13R,0.0591X0.0709*% +%ADD14C,0.0157*% +%ADD15C,0.0277*% +%ADD16C,0.0079*% +%ADD17C,0.0315*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +D11* +X003971Y002504D03* +X003971Y003504D03* +X003971Y004504D03* +X003971Y005504D03* +X003971Y006504D03* +X003971Y007504D03* +X004971Y007504D03* +X004971Y006504D03* +X004971Y005504D03* +X004971Y004504D03* +X004971Y003504D03* +X004971Y002504D03* +D12* +X002503Y003429D03* +X001715Y003429D03* +X001715Y007366D03* +X002503Y007366D03* +D13* +X002640Y006225D03* +X001577Y006225D03* +X001577Y004571D03* +X002640Y004571D03* +D14* +X001715Y004571D02* +X001715Y003429D01* +X001715Y002839D01* +X002050Y002504D01* +X003971Y002504D01* +X001715Y004571D02* +X001577Y004571D01* +D15* +X003133Y003390D03* +X003172Y005358D03* +X003133Y007366D03* +X001322Y008351D03* +X005022Y008351D03* +X001322Y002445D03* +D16* +X001518Y002757D02* +X001634Y002642D01* +X001968Y002307D01* +X002131Y002307D01* +X003604Y002307D01* +X003619Y002269D01* +X003736Y002152D01* +X003889Y002089D01* +X004054Y002089D01* +X004206Y002152D01* +X004323Y002269D01* +X004386Y002422D01* +X004386Y002587D01* +X004323Y002739D01* +X004206Y002856D01* +X004054Y002919D01* +X003889Y002919D01* +X003736Y002856D01* +X003619Y002739D01* +X003604Y002701D01* +X002131Y002701D01* +X001912Y002920D01* +X001912Y003065D01* +X001961Y003065D01* +X002030Y003134D01* +X002030Y003724D01* +X001961Y003793D01* +X001912Y003793D01* +X001912Y004099D01* +X001922Y004099D01* +X001991Y004168D01* +X001991Y004974D01* +X001922Y005043D01* +X001233Y005043D01* +X001164Y004974D01* +X001164Y004168D01* +X001233Y004099D01* +X001518Y004099D01* +X001518Y003793D01* +X001469Y003793D01* +X001400Y003724D01* +X001400Y003134D01* +X001469Y003065D01* +X001518Y003065D01* +X001518Y002757D01* +X001518Y002782D02* +X000724Y002782D01* +X000724Y002859D02* +X001518Y002859D01* +X001518Y002936D02* +X000724Y002936D01* +X000724Y003014D02* +X001518Y003014D01* +X001444Y003091D02* +X000724Y003091D01* +X000724Y003168D02* +X001400Y003168D01* +X001400Y003246D02* +X000724Y003246D01* +X000724Y003323D02* +X001400Y003323D01* +X001400Y003400D02* +X000724Y003400D01* +X000724Y003477D02* +X001400Y003477D01* +X001400Y003555D02* +X000724Y003555D01* +X000724Y003632D02* +X001400Y003632D01* +X001400Y003709D02* +X000724Y003709D01* +X000724Y003787D02* +X001463Y003787D01* +X001518Y003864D02* +X000724Y003864D01* +X000724Y003941D02* +X001518Y003941D01* +X001518Y004018D02* +X000724Y004018D01* +X000724Y004096D02* +X001518Y004096D01* +X001164Y004173D02* +X000724Y004173D01* +X000724Y004250D02* +X001164Y004250D01* +X001164Y004328D02* +X000724Y004328D01* +X000724Y004405D02* +X001164Y004405D01* +X001164Y004482D02* +X000724Y004482D01* +X000724Y004559D02* +X001164Y004559D01* +X001164Y004637D02* +X000724Y004637D01* +X000724Y004714D02* +X001164Y004714D01* +X001164Y004791D02* +X000724Y004791D01* +X000724Y004869D02* +X001164Y004869D01* +X001164Y004946D02* +X000724Y004946D01* +X000724Y005023D02* +X001213Y005023D01* +X000724Y005100D02* +X003861Y005100D01* +X003889Y005089D02* +X004054Y005089D01* +X004206Y005152D01* +X004323Y005269D01* +X004386Y005422D01* +X004386Y005587D01* +X004323Y005739D01* +X004206Y005856D01* +X004054Y005919D01* +X003889Y005919D01* +X003736Y005856D01* +X003619Y005739D01* +X003556Y005587D01* +X003556Y005422D01* +X003619Y005269D01* +X003736Y005152D01* +X003889Y005089D01* +X003889Y004919D02* +X003736Y004856D01* +X003619Y004739D01* +X003556Y004587D01* +X003556Y004422D01* +X003619Y004269D01* +X003736Y004152D01* +X003889Y004089D01* +X004054Y004089D01* +X004206Y004152D01* +X004323Y004269D01* +X004386Y004422D01* +X004386Y004587D01* +X004323Y004739D01* +X004206Y004856D01* +X004054Y004919D01* +X003889Y004919D01* +X003767Y004869D02* +X003054Y004869D01* +X003054Y004946D02* +X005463Y004946D01* +X005463Y005023D02* +X003005Y005023D01* +X002985Y005043D02* +X003054Y004974D01* +X003054Y004168D01* +X002985Y004099D01* +X002296Y004099D01* +X002227Y004168D01* +X002227Y004974D01* +X002296Y005043D01* +X002985Y005043D01* +X003054Y004791D02* +X003671Y004791D01* +X003609Y004714D02* +X003054Y004714D01* +X003054Y004637D02* +X003577Y004637D01* +X003556Y004559D02* +X003054Y004559D01* +X003054Y004482D02* +X003556Y004482D01* +X003563Y004405D02* +X003054Y004405D01* +X003054Y004328D02* +X003595Y004328D01* +X003638Y004250D02* +X003054Y004250D01* +X003054Y004173D02* +X003715Y004173D01* +X003873Y004096D02* +X001912Y004096D01* +X001912Y004018D02* +X005463Y004018D01* +X005463Y003941D02* +X001912Y003941D01* +X001912Y003864D02* +X003755Y003864D01* +X003736Y003856D02* +X003619Y003739D01* +X003556Y003587D01* +X003556Y003422D01* +X003619Y003269D01* +X003736Y003152D01* +X003889Y003089D01* +X004054Y003089D01* +X004206Y003152D01* +X004323Y003269D01* +X004386Y003422D01* +X004386Y003587D01* +X004323Y003739D01* +X004206Y003856D01* +X004054Y003919D01* +X003889Y003919D01* +X003736Y003856D01* +X003667Y003787D02* +X002785Y003787D01* +X002757Y003815D02* +X002839Y003733D01* +X002839Y003469D01* +X002542Y003469D01* +X002463Y003469D01* +X002463Y003815D01* +X002248Y003815D01* +X002166Y003733D01* +X002166Y003469D01* +X002463Y003469D01* +X002463Y003390D01* +X002166Y003390D01* +X002166Y003125D01* +X002248Y003044D01* +X002463Y003044D01* +X002463Y003390D01* +X002542Y003390D01* +X002542Y003469D01* +X002542Y003815D01* +X002757Y003815D01* +X002839Y003709D02* +X003607Y003709D01* +X003575Y003632D02* +X002839Y003632D01* +X002839Y003555D02* +X003556Y003555D01* +X003556Y003477D02* +X002839Y003477D01* +X002839Y003390D02* +X002542Y003390D01* +X002542Y003044D01* +X002757Y003044D01* +X002839Y003125D01* +X002839Y003390D01* +X002839Y003323D02* +X003597Y003323D01* +X003565Y003400D02* +X002542Y003400D01* +X002542Y003323D02* +X002463Y003323D01* +X002463Y003400D02* +X002030Y003400D01* +X002030Y003323D02* +X002166Y003323D01* +X002166Y003246D02* +X002030Y003246D01* +X002030Y003168D02* +X002166Y003168D01* +X002201Y003091D02* +X001987Y003091D01* +X001912Y003014D02* +X005463Y003014D01* +X005463Y003091D02* +X005114Y003091D01* +X005058Y003068D02* +X005218Y003134D01* +X005341Y003257D01* +X005407Y003417D01* +X005407Y003465D01* +X005011Y003465D01* +X005011Y003543D01* +X005407Y003543D01* +X005407Y003591D01* +X005341Y003751D01* +X005218Y003874D01* +X005058Y003940D01* +X005010Y003940D01* +X005010Y003544D01* +X004932Y003544D01* +X004932Y003940D01* +X004884Y003940D01* +X004724Y003874D01* +X004601Y003751D01* +X004535Y003591D01* +X004535Y003543D01* +X004932Y003543D01* +X004932Y003465D01* +X004535Y003465D01* +X004535Y003417D01* +X004601Y003257D01* +X004724Y003134D01* +X004884Y003068D01* +X004932Y003068D01* +X004932Y003465D01* +X005010Y003465D01* +X005010Y003068D01* +X005058Y003068D01* +X005010Y003091D02* +X004932Y003091D01* +X004932Y003168D02* +X005010Y003168D01* +X005010Y003246D02* +X004932Y003246D01* +X004932Y003323D02* +X005010Y003323D01* +X005010Y003400D02* +X004932Y003400D01* +X004932Y003477D02* +X004386Y003477D01* +X004377Y003400D02* +X004542Y003400D01* +X004574Y003323D02* +X004345Y003323D01* +X004300Y003246D02* +X004613Y003246D01* +X004690Y003168D02* +X004222Y003168D01* +X004058Y003091D02* +X004828Y003091D01* +X004889Y002919D02* +X004736Y002856D01* +X004619Y002739D01* +X004556Y002587D01* +X004556Y002422D01* +X004619Y002269D01* +X004736Y002152D01* +X004889Y002089D01* +X005054Y002089D01* +X005206Y002152D01* +X005323Y002269D01* +X005386Y002422D01* +X005386Y002587D01* +X005323Y002739D01* +X005206Y002856D01* +X005054Y002919D01* +X004889Y002919D01* +X004744Y002859D02* +X004198Y002859D01* +X004280Y002782D02* +X004662Y002782D01* +X004605Y002705D02* +X004337Y002705D01* +X004369Y002627D02* +X004573Y002627D01* +X004556Y002550D02* +X004386Y002550D01* +X004386Y002473D02* +X004556Y002473D01* +X004567Y002395D02* +X004375Y002395D01* +X004343Y002318D02* +X004599Y002318D01* +X004647Y002241D02* +X004295Y002241D01* +X004218Y002164D02* +X004725Y002164D01* +X005218Y002164D02* +X005463Y002164D01* +X005463Y002241D02* +X005295Y002241D01* +X005343Y002318D02* +X005463Y002318D01* +X005463Y002395D02* +X005375Y002395D01* +X005386Y002473D02* +X005463Y002473D01* +X005463Y002550D02* +X005386Y002550D01* +X005369Y002627D02* +X005463Y002627D01* +X005463Y002705D02* +X005337Y002705D01* +X005280Y002782D02* +X005463Y002782D01* +X005463Y002859D02* +X005198Y002859D01* +X005252Y003168D02* +X005463Y003168D01* +X005463Y003246D02* +X005330Y003246D01* +X005368Y003323D02* +X005463Y003323D01* +X005463Y003400D02* +X005400Y003400D01* +X005463Y003477D02* +X005011Y003477D01* +X005010Y003555D02* +X004932Y003555D01* +X004932Y003632D02* +X005010Y003632D01* +X005010Y003709D02* +X004932Y003709D01* +X004932Y003787D02* +X005010Y003787D01* +X005010Y003864D02* +X004932Y003864D01* +X004714Y003864D02* +X004187Y003864D01* +X004276Y003787D02* +X004637Y003787D01* +X004584Y003709D02* +X004335Y003709D01* +X004367Y003632D02* +X004552Y003632D01* +X004535Y003555D02* +X004386Y003555D01* +X004070Y004096D02* +X004873Y004096D01* +X004889Y004089D02* +X005054Y004089D01* +X005206Y004152D01* +X005323Y004269D01* +X005386Y004422D01* +X005386Y004587D01* +X005323Y004739D01* +X005206Y004856D01* +X005054Y004919D01* +X004889Y004919D01* +X004736Y004856D01* +X004619Y004739D01* +X004556Y004587D01* +X004556Y004422D01* +X004619Y004269D01* +X004736Y004152D01* +X004889Y004089D01* +X005070Y004096D02* +X005463Y004096D01* +X005463Y004173D02* +X005227Y004173D01* +X005304Y004250D02* +X005463Y004250D01* +X005463Y004328D02* +X005347Y004328D01* +X005379Y004405D02* +X005463Y004405D01* +X005463Y004482D02* +X005386Y004482D01* +X005386Y004559D02* +X005463Y004559D01* +X005463Y004637D02* +X005365Y004637D01* +X005333Y004714D02* +X005463Y004714D01* +X005463Y004791D02* +X005271Y004791D01* +X005176Y004869D02* +X005463Y004869D01* +X005463Y005100D02* +X005081Y005100D01* +X005054Y005089D02* +X005206Y005152D01* +X005323Y005269D01* +X005386Y005422D01* +X005386Y005587D01* +X005323Y005739D01* +X005206Y005856D01* +X005054Y005919D01* +X004889Y005919D01* +X004736Y005856D01* +X004619Y005739D01* +X004556Y005587D01* +X004556Y005422D01* +X004619Y005269D01* +X004736Y005152D01* +X004889Y005089D01* +X005054Y005089D01* +X004861Y005100D02* +X004081Y005100D01* +X004232Y005178D02* +X004711Y005178D01* +X004633Y005255D02* +X004309Y005255D01* +X004349Y005332D02* +X004593Y005332D01* +X004561Y005410D02* +X004381Y005410D01* +X004386Y005487D02* +X004556Y005487D01* +X004556Y005564D02* +X004386Y005564D01* +X004363Y005641D02* +X004579Y005641D01* +X004611Y005719D02* +X004331Y005719D01* +X004266Y005796D02* +X004676Y005796D01* +X004778Y005873D02* +X004164Y005873D01* +X004054Y006089D02* +X004206Y006152D01* +X004323Y006269D01* +X004386Y006422D01* +X004386Y006587D01* +X004323Y006739D01* +X004206Y006856D01* +X004054Y006919D01* +X003889Y006919D01* +X003736Y006856D01* +X003619Y006739D01* +X003556Y006587D01* +X003556Y006422D01* +X003619Y006269D01* +X003736Y006152D01* +X003889Y006089D01* +X004054Y006089D01* +X004092Y006105D02* +X004850Y006105D01* +X004889Y006089D02* +X005054Y006089D01* +X005206Y006152D01* +X005323Y006269D01* +X005386Y006422D01* +X005386Y006587D01* +X005323Y006739D01* +X005206Y006856D01* +X005054Y006919D01* +X004889Y006919D01* +X004736Y006856D01* +X004619Y006739D01* +X004556Y006587D01* +X004556Y006422D01* +X004619Y006269D01* +X004736Y006152D01* +X004889Y006089D01* +X005092Y006105D02* +X005463Y006105D01* +X005463Y006028D02* +X003075Y006028D01* +X003075Y006105D02* +X003850Y006105D01* +X003706Y006182D02* +X003075Y006182D01* +X003075Y006185D02* +X002680Y006185D01* +X002680Y006264D01* +X003075Y006264D01* +X003075Y006637D01* +X002993Y006718D01* +X002680Y006718D01* +X002680Y006264D01* +X002601Y006264D01* +X002601Y006718D01* +X002287Y006718D01* +X002206Y006637D01* +X002206Y006264D01* +X002601Y006264D01* +X002601Y006185D01* +X002680Y006185D01* +X002680Y005731D01* +X002993Y005731D01* +X003075Y005812D01* +X003075Y006185D01* +X003075Y006337D02* +X003591Y006337D01* +X003559Y006414D02* +X003075Y006414D01* +X003075Y006491D02* +X003556Y006491D01* +X003556Y006569D02* +X003075Y006569D01* +X003066Y006646D02* +X003581Y006646D01* +X003613Y006723D02* +X001991Y006723D01* +X001991Y006646D02* +X002215Y006646D01* +X002206Y006569D02* +X001991Y006569D01* +X001991Y006628D02* +X001991Y007032D01* +X002030Y007071D01* +X002030Y007661D01* +X001991Y007701D01* +X001991Y007764D01* +X002184Y007957D01* +X004160Y007957D01* +X004556Y007561D01* +X004556Y007422D01* +X004619Y007269D01* +X004736Y007152D01* +X004889Y007089D01* +X005054Y007089D01* +X005206Y007152D01* +X005323Y007269D01* +X005386Y007422D01* +X005386Y007587D01* +X005323Y007739D01* +X005206Y007856D01* +X005054Y007919D01* +X004977Y007919D01* +X004388Y008508D01* +X004160Y008508D01* +X001955Y008508D01* +X001794Y008347D01* +X001440Y007992D01* +X001440Y007764D01* +X001440Y007701D01* +X001400Y007661D01* +X001400Y007071D01* +X001440Y007032D01* +X001440Y006697D01* +X001233Y006697D01* +X001164Y006628D01* +X001164Y005821D01* +X001233Y005752D01* +X001922Y005752D01* +X001991Y005821D01* +X001991Y006628D01* +X001991Y006801D02* +X003681Y006801D01* +X003789Y006878D02* +X001991Y006878D01* +X001991Y006955D02* +X005463Y006955D01* +X005463Y006878D02* +X005153Y006878D01* +X005261Y006801D02* +X005463Y006801D01* +X005463Y006723D02* +X005330Y006723D01* +X005361Y006646D02* +X005463Y006646D01* +X005463Y006569D02* +X005386Y006569D01* +X005386Y006491D02* +X005463Y006491D01* +X005463Y006414D02* +X005383Y006414D01* +X005351Y006337D02* +X005463Y006337D01* +X005463Y006260D02* +X005314Y006260D01* +X005236Y006182D02* +X005463Y006182D01* +X005463Y005951D02* +X003075Y005951D01* +X003075Y005873D02* +X003778Y005873D01* +X003676Y005796D02* +X003059Y005796D01* +X002680Y005796D02* +X002601Y005796D01* +X002601Y005731D02* +X002601Y006185D01* +X002206Y006185D01* +X002206Y005812D01* +X002287Y005731D01* +X002601Y005731D01* +X002601Y005873D02* +X002680Y005873D01* +X002680Y005951D02* +X002601Y005951D01* +X002601Y006028D02* +X002680Y006028D01* +X002680Y006105D02* +X002601Y006105D01* +X002601Y006182D02* +X002680Y006182D01* +X002680Y006260D02* +X003629Y006260D01* +X003611Y005719D02* +X000724Y005719D01* +X000724Y005796D02* +X001189Y005796D01* +X001164Y005873D02* +X000724Y005873D01* +X000724Y005951D02* +X001164Y005951D01* +X001164Y006028D02* +X000724Y006028D01* +X000724Y006105D02* +X001164Y006105D01* +X001164Y006182D02* +X000724Y006182D01* +X000724Y006260D02* +X001164Y006260D01* +X001164Y006337D02* +X000724Y006337D01* +X000724Y006414D02* +X001164Y006414D01* +X001164Y006491D02* +X000724Y006491D01* +X000724Y006569D02* +X001164Y006569D01* +X001182Y006646D02* +X000724Y006646D01* +X000724Y006723D02* +X001440Y006723D01* +X001440Y006801D02* +X000724Y006801D01* +X000724Y006878D02* +X001440Y006878D01* +X001440Y006955D02* +X000724Y006955D01* +X000724Y007032D02* +X001439Y007032D01* +X001400Y007110D02* +X000724Y007110D01* +X000724Y007187D02* +X001400Y007187D01* +X001400Y007264D02* +X000724Y007264D01* +X000724Y007342D02* +X001400Y007342D01* +X001400Y007419D02* +X000724Y007419D01* +X000724Y007496D02* +X001400Y007496D01* +X001400Y007573D02* +X000724Y007573D01* +X000724Y007651D02* +X001400Y007651D01* +X001440Y007728D02* +X000724Y007728D01* +X000724Y007805D02* +X001440Y007805D01* +X001440Y007883D02* +X000724Y007883D01* +X000724Y007960D02* +X001440Y007960D01* +X001485Y008037D02* +X000724Y008037D01* +X000724Y008114D02* +X001562Y008114D01* +X001639Y008192D02* +X000724Y008192D01* +X000724Y008269D02* +X001716Y008269D01* +X001794Y008346D02* +X000724Y008346D01* +X000724Y008424D02* +X001871Y008424D01* +X001948Y008501D02* +X000724Y008501D01* +X000724Y008578D02* +X005463Y008578D01* +X005463Y008501D02* +X004396Y008501D01* +X004473Y008424D02* +X005463Y008424D01* +X005463Y008346D02* +X004550Y008346D01* +X004627Y008269D02* +X005463Y008269D01* +X005463Y008192D02* +X004705Y008192D01* +X004782Y008114D02* +X005463Y008114D01* +X005463Y008037D02* +X004859Y008037D01* +X004937Y007960D02* +X005463Y007960D01* +X005463Y007883D02* +X005142Y007883D01* +X005257Y007805D02* +X005463Y007805D01* +X005463Y007728D02* +X005328Y007728D01* +X005360Y007651D02* +X005463Y007651D01* +X005463Y007573D02* +X005386Y007573D01* +X005386Y007496D02* +X005463Y007496D01* +X005463Y007419D02* +X005385Y007419D01* +X005353Y007342D02* +X005463Y007342D01* +X005463Y007264D02* +X005318Y007264D01* +X005241Y007187D02* +X005463Y007187D01* +X005463Y007110D02* +X005104Y007110D01* +X004839Y007110D02* +X004104Y007110D01* +X004054Y007089D02* +X004206Y007152D01* +X004323Y007269D01* +X004386Y007422D01* +X004386Y007587D01* +X004323Y007739D01* +X004206Y007856D01* +X004054Y007919D01* +X003889Y007919D01* +X003736Y007856D01* +X003619Y007739D01* +X003556Y007587D01* +X003556Y007422D01* +X003619Y007269D01* +X003736Y007152D01* +X003889Y007089D01* +X004054Y007089D01* +X004241Y007187D02* +X004701Y007187D01* +X004624Y007264D02* +X004318Y007264D01* +X004353Y007342D02* +X004589Y007342D01* +X004557Y007419D02* +X004385Y007419D01* +X004386Y007496D02* +X004556Y007496D01* +X004544Y007573D02* +X004386Y007573D01* +X004360Y007651D02* +X004466Y007651D01* +X004389Y007728D02* +X004328Y007728D01* +X004312Y007805D02* +X004257Y007805D01* +X004234Y007883D02* +X004142Y007883D01* +X003801Y007883D02* +X002109Y007883D01* +X002032Y007805D02* +X003686Y007805D01* +X003615Y007728D02* +X002781Y007728D01* +X002757Y007752D02* +X002839Y007670D01* +X002839Y007406D01* +X002542Y007406D01* +X002463Y007406D01* +X002463Y007752D01* +X002248Y007752D01* +X002166Y007670D01* +X002166Y007406D01* +X002463Y007406D01* +X002463Y007327D01* +X002166Y007327D01* +X002166Y007062D01* +X002248Y006981D01* +X002463Y006981D01* +X002463Y007327D01* +X002542Y007327D01* +X002542Y007406D01* +X002542Y007752D01* +X002757Y007752D01* +X002839Y007651D02* +X003583Y007651D01* +X003556Y007573D02* +X002839Y007573D01* +X002839Y007496D02* +X003556Y007496D01* +X003557Y007419D02* +X002839Y007419D01* +X002839Y007327D02* +X002542Y007327D01* +X002542Y006981D01* +X002757Y006981D01* +X002839Y007062D01* +X002839Y007327D01* +X002839Y007264D02* +X003624Y007264D01* +X003589Y007342D02* +X002542Y007342D01* +X002542Y007419D02* +X002463Y007419D01* +X002463Y007496D02* +X002542Y007496D01* +X002542Y007573D02* +X002463Y007573D01* +X002463Y007651D02* +X002542Y007651D01* +X002542Y007728D02* +X002463Y007728D01* +X002224Y007728D02* +X001991Y007728D01* +X002030Y007651D02* +X002166Y007651D01* +X002166Y007573D02* +X002030Y007573D01* +X002030Y007496D02* +X002166Y007496D01* +X002166Y007419D02* +X002030Y007419D01* +X002030Y007342D02* +X002463Y007342D01* +X002463Y007264D02* +X002542Y007264D01* +X002542Y007187D02* +X002463Y007187D01* +X002463Y007110D02* +X002542Y007110D01* +X002542Y007032D02* +X002463Y007032D01* +X002196Y007032D02* +X001991Y007032D01* +X002030Y007110D02* +X002166Y007110D01* +X002166Y007187D02* +X002030Y007187D01* +X002030Y007264D02* +X002166Y007264D01* +X002601Y006646D02* +X002680Y006646D01* +X002680Y006569D02* +X002601Y006569D01* +X002601Y006491D02* +X002680Y006491D01* +X002680Y006414D02* +X002601Y006414D01* +X002601Y006337D02* +X002680Y006337D01* +X002601Y006260D02* +X001991Y006260D01* +X001991Y006337D02* +X002206Y006337D01* +X002206Y006414D02* +X001991Y006414D01* +X001991Y006491D02* +X002206Y006491D01* +X002206Y006182D02* +X001991Y006182D01* +X001991Y006105D02* +X002206Y006105D01* +X002206Y006028D02* +X001991Y006028D01* +X001991Y005951D02* +X002206Y005951D01* +X002206Y005873D02* +X001991Y005873D01* +X001965Y005796D02* +X002222Y005796D01* +X002276Y005023D02* +X001942Y005023D01* +X001991Y004946D02* +X002227Y004946D01* +X002227Y004869D02* +X001991Y004869D01* +X001991Y004791D02* +X002227Y004791D01* +X002227Y004714D02* +X001991Y004714D01* +X001991Y004637D02* +X002227Y004637D01* +X002227Y004559D02* +X001991Y004559D01* +X001991Y004482D02* +X002227Y004482D01* +X002227Y004405D02* +X001991Y004405D01* +X001991Y004328D02* +X002227Y004328D01* +X002227Y004250D02* +X001991Y004250D01* +X001991Y004173D02* +X002227Y004173D01* +X002220Y003787D02* +X001968Y003787D01* +X002030Y003709D02* +X002166Y003709D01* +X002166Y003632D02* +X002030Y003632D01* +X002030Y003555D02* +X002166Y003555D01* +X002166Y003477D02* +X002030Y003477D01* +X002463Y003477D02* +X002542Y003477D01* +X002542Y003555D02* +X002463Y003555D01* +X002463Y003632D02* +X002542Y003632D01* +X002542Y003709D02* +X002463Y003709D01* +X002463Y003787D02* +X002542Y003787D01* +X002542Y003246D02* +X002463Y003246D01* +X002463Y003168D02* +X002542Y003168D01* +X002542Y003091D02* +X002463Y003091D01* +X002128Y002705D02* +X003605Y002705D01* +X003662Y002782D02* +X002050Y002782D01* +X001973Y002859D02* +X003744Y002859D01* +X003884Y003091D02* +X002804Y003091D01* +X002839Y003168D02* +X003720Y003168D01* +X003643Y003246D02* +X002839Y003246D01* +X001957Y002318D02* +X000724Y002318D01* +X000724Y002241D02* +X003647Y002241D01* +X003725Y002164D02* +X000724Y002164D01* +X000724Y002086D02* +X005463Y002086D01* +X005463Y002044D02* +X000724Y002044D01* +X000724Y008752D01* +X005463Y008752D01* +X005463Y002044D01* +X005463Y002936D02* +X001912Y002936D01* +X001648Y002627D02* +X000724Y002627D01* +X000724Y002550D02* +X001726Y002550D01* +X001803Y002473D02* +X000724Y002473D01* +X000724Y002395D02* +X001880Y002395D01* +X001571Y002705D02* +X000724Y002705D01* +X000724Y005178D02* +X003711Y005178D01* +X003633Y005255D02* +X000724Y005255D01* +X000724Y005332D02* +X003593Y005332D01* +X003561Y005410D02* +X000724Y005410D01* +X000724Y005487D02* +X003556Y005487D01* +X003556Y005564D02* +X000724Y005564D01* +X000724Y005641D02* +X003579Y005641D01* +X004176Y004869D02* +X004767Y004869D01* +X004671Y004791D02* +X004271Y004791D01* +X004333Y004714D02* +X004609Y004714D01* +X004577Y004637D02* +X004365Y004637D01* +X004386Y004559D02* +X004556Y004559D01* +X004556Y004482D02* +X004386Y004482D01* +X004379Y004405D02* +X004563Y004405D01* +X004595Y004328D02* +X004347Y004328D01* +X004304Y004250D02* +X004638Y004250D01* +X004715Y004173D02* +X004227Y004173D01* +X005228Y003864D02* +X005463Y003864D01* +X005463Y003787D02* +X005306Y003787D01* +X005358Y003709D02* +X005463Y003709D01* +X005463Y003632D02* +X005390Y003632D01* +X005407Y003555D02* +X005463Y003555D01* +X005463Y005178D02* +X005232Y005178D01* +X005309Y005255D02* +X005463Y005255D01* +X005463Y005332D02* +X005349Y005332D01* +X005381Y005410D02* +X005463Y005410D01* +X005463Y005487D02* +X005386Y005487D01* +X005386Y005564D02* +X005463Y005564D01* +X005463Y005641D02* +X005363Y005641D01* +X005331Y005719D02* +X005463Y005719D01* +X005463Y005796D02* +X005266Y005796D01* +X005164Y005873D02* +X005463Y005873D01* +X004789Y006878D02* +X004153Y006878D01* +X004261Y006801D02* +X004681Y006801D01* +X004613Y006723D02* +X004330Y006723D01* +X004361Y006646D02* +X004581Y006646D01* +X004556Y006569D02* +X004386Y006569D01* +X004386Y006491D02* +X004556Y006491D01* +X004559Y006414D02* +X004383Y006414D01* +X004351Y006337D02* +X004591Y006337D01* +X004629Y006260D02* +X004314Y006260D01* +X004236Y006182D02* +X004706Y006182D01* +X005463Y007032D02* +X002809Y007032D01* +X002839Y007110D02* +X003839Y007110D01* +X003701Y007187D02* +X002839Y007187D01* +X000724Y008655D02* +X005463Y008655D01* +X005463Y008733D02* +X000724Y008733D01* +D17* +X001715Y007878D02* +X002070Y008232D01* +X004274Y008232D01* +X004983Y007524D01* +X004971Y007512D01* +X004971Y007504D01* +X001715Y007366D02* +X001715Y006225D01* +X001577Y006225D01* +X001715Y007366D02* +X001715Y007878D01* +M02* diff --git a/extclk/extclk.GTO b/extclk/extclk.GTO new file mode 100644 index 0000000..9ed4b55 --- /dev/null +++ b/extclk/extclk.GTO @@ -0,0 +1,109 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +%ADD11C,0.0079*% +%ADD12C,0.0080*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +D11* +X001400Y003075D02* +X002818Y003075D01* +X002818Y003784D01* +X001400Y003784D01* +X001400Y003075D01* +X002030Y004414D02* +X002188Y004414D01* +X002739Y005063D02* +X002739Y005732D01* +X002188Y006382D02* +X002030Y006382D01* +X001479Y005732D02* +X001479Y005063D01* +X001400Y007012D02* +X002818Y007012D01* +X002818Y007721D01* +X001400Y007721D01* +X001400Y007012D01* +X003096Y004591D02* +X003098Y004606D01* +X003104Y004620D01* +X003114Y004632D01* +X003126Y004641D01* +X003141Y004646D01* +X003156Y004647D01* +X003171Y004644D01* +X003184Y004637D01* +X003195Y004626D01* +X003203Y004613D01* +X003207Y004599D01* +X003207Y004583D01* +X003203Y004569D01* +X003195Y004556D01* +X003184Y004545D01* +X003171Y004538D01* +X003156Y004535D01* +X003141Y004536D01* +X003126Y004541D01* +X003114Y004550D01* +X003104Y004562D01* +X003098Y004576D01* +X003096Y004591D01* +X003471Y007004D02* +X004471Y007004D01* +X004471Y008004D01* +X005471Y008004D01* +X005471Y002004D01* +X003471Y002004D01* +X003471Y007004D01* +X003471Y008004D01* +X004471Y008004D01* +D12* +X001163Y007663D02* +X001163Y007454D01* +X000954Y007663D01* +X000902Y007663D01* +X000850Y007611D01* +X000850Y007506D01* +X000902Y007454D01* +X000902Y007301D02* +X000850Y007248D01* +X000850Y007144D01* +X000902Y007091D01* +X001111Y007091D01* +X001163Y007144D01* +X001163Y007248D01* +X001111Y007301D01* +X001163Y005754D02* +X001163Y005544D01* +X001163Y005649D02* +X000850Y005649D01* +X000954Y005544D01* +X000850Y005391D02* +X001163Y005182D01* +X001163Y005391D02* +X000850Y005182D01* +X001163Y003726D02* +X001163Y003517D01* +X001163Y003621D02* +X000850Y003621D01* +X000954Y003517D01* +X000902Y003364D02* +X000850Y003311D01* +X000850Y003207D01* +X000902Y003154D01* +X001111Y003154D01* +X001163Y003207D01* +X001163Y003311D01* +X001111Y003364D01* +M02* diff --git a/extclk/extclk.GTS b/extclk/extclk.GTS new file mode 100644 index 0000000..be08225 --- /dev/null +++ b/extclk/extclk.GTS @@ -0,0 +1,43 @@ +G75* +G70* +%OFA0B0*% +%FSLAX24Y24*% +%IPPOS*% +%LPD*% +%AMOC8* +5,1,8,0,0,1.08239X$1,22.5* +% +%ADD10C,0.0000*% +%ADD11C,0.0634*% +%ADD12R,0.0434X0.0532*% +%ADD13R,0.0631X0.0749*% +D10* +X000534Y001854D02* +X000534Y008941D01* +X005652Y008941D01* +X005652Y001854D01* +X000534Y001854D01* +D11* +X003971Y002504D03* +X003971Y003504D03* +X003971Y004504D03* +X003971Y005504D03* +X003971Y006504D03* +X003971Y007504D03* +X004971Y007504D03* +X004971Y006504D03* +X004971Y005504D03* +X004971Y004504D03* +X004971Y003504D03* +X004971Y002504D03* +D12* +X002503Y003429D03* +X001715Y003429D03* +X001715Y007366D03* +X002503Y007366D03* +D13* +X002640Y006225D03* +X001577Y006225D03* +X001577Y004571D03* +X002640Y004571D03* +M02* diff --git a/extclk/extclk.TXT b/extclk/extclk.TXT new file mode 100644 index 0000000..3fc99ad --- /dev/null +++ b/extclk/extclk.TXT @@ -0,0 +1,27 @@ +% +M48 +M72 +T01C0.0157 +T02C0.0394 +% +T01 +X1322Y2445 +X3133Y3390 +X3172Y5358 +X3133Y7366 +X1322Y8351 +X5022Y8351 +T02 +X4971Y7504 +X4971Y6504 +X4971Y5504 +X4971Y4504 +X4971Y3504 +X4971Y2504 +X3971Y2504 +X3971Y3504 +X3971Y4504 +X3971Y5504 +X3971Y6504 +X3971Y7504 +M30 diff --git a/extclk/hackrf_gpssim.jpg b/extclk/hackrf_gpssim.jpg new file mode 100644 index 0000000..3037e37 Binary files /dev/null and b/extclk/hackrf_gpssim.jpg differ diff --git a/extclk/hackrf_tcxo.jpg b/extclk/hackrf_tcxo.jpg new file mode 100644 index 0000000..02db28e Binary files /dev/null and b/extclk/hackrf_tcxo.jpg differ diff --git a/gpssim.c b/gpssim.c index fa87eff..2d72e41 100644 --- a/gpssim.c +++ b/gpssim.c @@ -11,77 +11,8 @@ #else #include #endif +#include "gpssim.h" -#ifndef bool -typedef int bool; -#define true 1 -#define false 0 -#endif - -/*! \brief Maximum length of a line in a text file (RINEX, motion) */ -#define MAX_CHAR (100) - -/*! \brief Maximum number of satellites in RINEX file */ -#define MAX_SAT (32) -/*! \brief Maximum number of channels we simulate */ -#define MAX_CHAN (16) - -/*! \brief Maximum number of user motion waypoints */ -#define USER_MOTION_SIZE (3000) // max 300 sec at 10Hz - -/*! \brief Number of subframes */ -#define N_SBF (51) // 6 seconds per subframe, 6 sec * 51 = 306 sec (max) - -/*! \brief Number of words per subframe */ -#define N_DWRD_SBF (10) // 10 word per subframe - -/*! \brief Number of words */ -#define N_DWRD (N_SBF*N_DWRD_SBF) // 10 word per subframe - -/*! \brief C/A code sequence length */ -#define CA_SEQ_LEN (1023) - -#define SECONDS_IN_WEEK 604800.0 -#define SECONDS_IN_HALF_WEEK 302400.0 -#define SECONDS_IN_DAY 86400.0 -#define SECONDS_IN_HOUR 3600.0 -#define SECONDS_IN_MINUTE 60.0 - -#define POW2_M5 0.03125 -#define POW2_M19 1.907348632812500e-6 -#define POW2_M29 1.862645149230957e-9 -#define POW2_M31 4.656612873077393e-10 -#define POW2_M33 1.164153218269348e-10 -#define POW2_M43 1.136868377216160e-13 -#define POW2_M55 2.775557561562891e-17 - -// Conventional values employed in GPS ephemeris model (ICD-GPS-200) -#define GM_EARTH 3.986005e14 -#define OMEGA_EARTH 7.2921151467e-5 -#define PI 3.1415926535898 - -#define WGS84_RADIUS 6378137.0 -#define WGS84_ECCENTRICITY 0.0818191908426 - -#define R2D 57.2957795131 - -#define SPEED_OF_LIGHT 2.99792458e8 -#define LAMBDA_L1 0.190293672798365 - -/*! \brief GPS L1 Carrier frequency */ -#define CARR_FREQ (1575.42e6) -/*! \brief C/A code frequency */ -#define CODE_FREQ (1.023e6) -#define CARR_TO_CODE (1.0/1540.0) - -// Sampling data format -#define SC08 (8) -#define SC16 (16) - -#define ADC_GAIN (250) // for bladeRF txvga1 = -25dB with 50dB external attenuation - -#define _SINE_LUT -#ifdef _SINE_LUT int sinTable512[] = { 2, 5, 8, 11, 14, 17, 20, 23, 26, 29, 32, 35, 38, 41, 44, 47, 50, 53, 56, 59, 62, 65, 68, 71, 74, 77, 80, 83, 86, 89, 91, 94, @@ -151,90 +82,49 @@ int cosTable512[] = { 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 241, 242, 243, 244, 244, 245, 245, 246, 247, 247, 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 250 }; -#endif -/*! \file gpssim.c - * \brief GPS Satellite Simulator +// Receiver antenna attenuation in dB for boresight angle = 0:5:180 [deg] +double ant_pat_db[37] = { + 0.00, 0.00, 0.22, 0.44, 0.67, 1.11, 1.56, 2.00, 2.44, 2.89, 3.56, 4.22, + 4.89, 5.56, 6.22, 6.89, 7.56, 8.22, 8.89, 9.78, 10.67, 11.56, 12.44, 13.33, + 14.44, 15.56, 16.67, 17.78, 18.89, 20.00, 21.33, 22.67, 24.00, 25.56, 27.33, 29.33, + 31.56 +}; + +int allocatedSat[MAX_SAT]; + +/*! \brief Subtract two vectors of double + * \param[out] y Result of subtraction + * \param[in] x1 Minuend of subtracion + * \param[in] x2 Subtrahend of subtracion */ - -/*! \brief Structure representing GPS time */ -typedef struct +void subVect(double *y, const double *x1, const double *x2) { - int week; /*!< GPS week number (since January 1980) */ - double sec; /*!< second inside the GPS \a week */ -} gpstime_t; + y[0] = x1[0]-x2[0]; + y[1] = x1[1]-x2[1]; + y[2] = x1[2]-x2[2]; -/*! \brief Structure repreenting UTC time */ -typedef struct + return; +} + +/*! \brief Compute Norm of Vector + * \param[in] x Input vector + * \returns Length (Norm) of the input vector + */ +double normVect(const double *x) { - int y; /*!< Calendar year */ - int m; /*!< Calendar month */ - int d; /*!< Calendar day */ - int hh; /*!< Calendar hour */ - int mm; /*!< Calendar minutes */ - double sec; /*!< Calendar seconds */ -} datetime_t; + return(sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])); +} -/*! \brief Structure representing ephemeris of a single satellite */ -typedef struct +/*! \brief Compute dot-product of two vectors + * \param[in] x1 First multiplicand + * \param[in] x2 Second multiplicand + * \returns Dot-product of both multiplicands + */ +double dotProd(const double *x1, const double *x2) { - int vflg; /*!< Valid Flag */ - gpstime_t toc; /*!< Time of Clock */ - gpstime_t toe; /*!< Time of Ephemeris */ - int iodc; /*!< Issue of Data, Clock */ - int iode; /*!< Isuse of Data, Ephemeris */ - double deltan; /*!< Delta-N (radians/sec) */ - double cuc; /*!< Cuc (radians) */ - double cus; /*!< Cus (radians) */ - double cic; /*!< Correction to inclination cos (radians) */ - double cis; /*!< Correction to inclination sin (radians) */ - double crc; /*!< Correction to radius cos (meters) */ - double crs; /*!< Correction to radius sin (meters) */ - double ecc; /*!< e Eccentricity */ - double sqrta; /*!< sqrt(A) (sqrt(m)) */ - double m0; /*!< Mean anamoly (radians) */ - double omg0; /*!< Longitude of the ascending node (radians) */ - double inc0; /*!< Inclination (radians) */ - double aop; - double omgdot; /*!< Omega dot (radians/s) */ - double idot; /*!< IDOT (radians/s) */ - double af0; /*!< Clock offset (seconds) */ - double af1; /*!< rate (sec/sec) */ - double af2; /*!< acceleration (sec/sec^2) */ - double tgd; /*!< Group delay L2 bias */ - - // Working variables follow - double n; /*!< Mean motion (Average angular velocity) */ - double sq1e2; /*!< sqrt(1-e^2) */ - double A; /*!< Semi-major axis */ - double omgkdot; /*!< OmegaDot-OmegaEdot */ -} ephem_t; - -typedef struct -{ - gpstime_t g; - double range; - double rate; -} range_t; - -/*! \brief Structure representing a Channel */ -typedef struct -{ - int prn; /*< PRN Number */ - int ca[CA_SEQ_LEN]; /*< C/A Sequence */ - double f_carr; /*< Carrier frequency */ - double f_code; /*< Code frequency */ - double carr_phase; /*< Carrier phase */ - double code_phase; /*< Code phase */ - gpstime_t g0; /*!< GPS time at start */ - unsigned long dwrd[N_DWRD]; /*!< Data words of sub-frame */ - int iword; /*!< initial word */ - int ibit; /*!< initial bit */ - int icode; /*!< initial code */ - int dataBit; /*!< current data bit */ - int codeCA; /*!< current C/A code */ - short *iq_buff; /*< buffer of I/Q samples */ -} channel_t; + return(x1[0]*x2[0]+x1[1]*x2[1]+x1[2]*x2[2]); +} /* !\brief generate the C/A code sequence for a given Satellite Vehicle PRN * \param[in] prn PRN nuber of the Satellite Vehicle @@ -326,6 +216,16 @@ void xyz2llh(const double *xyz, double *llh) eps = 1.0e-3; e2 = e*e; + if (normVect(xyz)-SECONDS_IN_HOUR) && (dt<=SECONDS_IN_HOUR)) + // Check current time of clock + dt = subGpsTime(g, g0); + + if (dt>SECONDS_IN_HOUR) { - strncpy(tmp, str, 2); - tmp[2] = 0; - sv = atoi(tmp)-1; + g0 = g; + ieph++; // a new set of ephemerides - if (eph[sv].vflg==0) - { - eph[sv].toc = g; - - strncpy(tmp, str+22, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); // tmp[15]='E'; - eph[sv].af0 = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].af1 = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].af2 = atof(tmp); - - // BROADCAST ORBIT - 1 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+3, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].iode = (int)atof(tmp); - - strncpy(tmp, str+22, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].crs = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].deltan = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].m0 = atof(tmp); - - // BROADCAST ORBIT - 2 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+3, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].cuc = atof(tmp); - - strncpy(tmp, str+22, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].ecc = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].cus = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].sqrta = atof(tmp); - - // BROADCAST ORBIT - 3 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+3, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].toe.sec = atof(tmp); - - strncpy(tmp, str+22, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].cic = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].omg0 = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].cis = atof(tmp); - - // BROADCAST ORBIT - 4 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+3, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].inc0 = atof(tmp); - - strncpy(tmp, str+22, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].crc = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].aop = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].omgdot = atof(tmp); - - // BROADCAST ORBIT - 5 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+3, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].idot = atof(tmp); - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].toe.week = (int)atof(tmp); - - // BROADCAST ORBIT - 6 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - strncpy(tmp, str+41, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].tgd = atof(tmp); - - strncpy(tmp, str+60, 19); - tmp[19] = 0; - replaceExpDesignator(tmp, 19); - eph[sv].iodc = (int)atof(tmp); - - // BROADCAST ORBIT - 7 - if (NULL==fgets(str, MAX_CHAR, fp)) - break; - - eph[sv].vflg = 1; - - nsat++; - } + if (ieph>=EPHEM_ARRAY_SIZE) + break; } - else + + // Date and time + eph[ieph][sv].t = t; + + // PRN + strncpy(tmp, str, 2); + tmp[2] = 0; + sv = atoi(tmp)-1; + + // SV CLK + eph[ieph][sv].toc = g; + + strncpy(tmp, str+22, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); // tmp[15]='E'; + eph[ieph][sv].af0 = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].af1 = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].af2 = atof(tmp); + + // BROADCAST ORBIT - 1 + if (NULL==fgets(str, MAX_CHAR, fp)) break; + strncpy(tmp, str+3, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].iode = (int)atof(tmp); + + strncpy(tmp, str+22, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].crs = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].deltan = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].m0 = atof(tmp); + + // BROADCAST ORBIT - 2 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + strncpy(tmp, str+3, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].cuc = atof(tmp); + + strncpy(tmp, str+22, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].ecc = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].cus = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].sqrta = atof(tmp); + + // BROADCAST ORBIT - 3 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + strncpy(tmp, str+3, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].toe.sec = atof(tmp); + + strncpy(tmp, str+22, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].cic = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].omg0 = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].cis = atof(tmp); + + // BROADCAST ORBIT - 4 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + strncpy(tmp, str+3, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].inc0 = atof(tmp); + + strncpy(tmp, str+22, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].crc = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].aop = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].omgdot = atof(tmp); + + // BROADCAST ORBIT - 5 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + strncpy(tmp, str+3, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].idot = atof(tmp); + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].toe.week = (int)atof(tmp); + + // BROADCAST ORBIT - 6 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + strncpy(tmp, str+41, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].tgd = atof(tmp); + + strncpy(tmp, str+60, 19); + tmp[19] = 0; + replaceExpDesignator(tmp, 19); + eph[ieph][sv].iodc = (int)atof(tmp); + + // BROADCAST ORBIT - 7 + if (NULL==fgets(str, MAX_CHAR, fp)) + break; + + // Set valid flag + eph[ieph][sv].vflg = 1; + // Update the working variables - eph[sv].A = eph[sv].sqrta * eph[sv].sqrta; - eph[sv].n = sqrt(GM_EARTH/(eph[sv].A*eph[sv].A*eph[sv].A)) + eph[sv].deltan; - eph[sv].sq1e2 = sqrt(1.0 - eph[sv].ecc*eph[sv].ecc); - eph[sv].omgkdot = eph[sv].omgdot - OMEGA_EARTH; + eph[ieph][sv].A = eph[ieph][sv].sqrta * eph[ieph][sv].sqrta; + eph[ieph][sv].n = sqrt(GM_EARTH/(eph[ieph][sv].A*eph[ieph][sv].A*eph[ieph][sv].A)) + eph[ieph][sv].deltan; + eph[ieph][sv].sq1e2 = sqrt(1.0 - eph[ieph][sv].ecc*eph[ieph][sv].ecc); + eph[ieph][sv].omgkdot = eph[ieph][sv].omgdot - OMEGA_EARTH; } fclose(fp); + + if (g0.week>=0) + ieph += 1; // Number of sets of ephemerides - return(nsat); -} - -/*! \brief Subtract two vectors of double - * \param[out] y Result of subtraction - * \param[in] x1 Minuend of subtracion - * \param[in] x2 Subtrahend of subtracion - */ -void subVect(double *y, const double *x1, const double *x2) -{ - y[0] = x1[0]-x2[0]; - y[1] = x1[1]-x2[1]; - y[2] = x1[2]-x2[2]; - - return; -} - -/*! \brief Compute Norm of Vector - * \param[in] x Input vector - * \returns Length (Norm) of the input vector - */ -double normVect(const double *x) -{ - return(sqrt(x[0]*x[0]+x[1]*x[1]+x[2]*x[2])); -} - -/*! \brief Compute dot-product of two vectors - * \param[in] x1 First multiplicand - * \param[in] x2 Second multiplicand - * \returns Dot-product of both multiplicands - */ -double dotProd(const double *x1, const double *x2) -{ - return(x1[0]*x2[0]+x1[1]*x2[1]+x1[2]*x2[2]); + return(ieph); } /*! \brief Compute range between a satellite and the receiver @@ -1099,6 +989,10 @@ void computeRange(range_t *rho, ephem_t eph, gpstime_t g, double xyz[]) double tau; double range,rate; double xrot,yrot; + + double llh[3],neu[3]; + double tmat[3][3]; + // SV position at time of the pseudorange observation. satpos(eph, g, pos, vel, clk); @@ -1121,6 +1015,7 @@ void computeRange(range_t *rho, ephem_t eph, gpstime_t g, double xyz[]) // New observer to satellite vector and satellite range. subVect(los, pos, xyz); range = normVect(los); + rho->d = range; // Pseudorange. rho->range = range - SPEED_OF_LIGHT*clk[0]; @@ -1131,33 +1026,38 @@ void computeRange(range_t *rho, ephem_t eph, gpstime_t g, double xyz[]) // Pseudorange rate. rho->rate = rate; // - SPEED_OF_LIGHT*clk[1]; - // Time of application + // Time of application. rho->g = g; + // Azimuth and elevation angles. + xyz2llh(xyz, llh); + ltcmat(llh, tmat); + ecef2neu(los, tmat, neu); + neu2azel(rho->azel, neu); + return; } /*! \brief Compute the code phase for a given channel (satellite) * \param chan Channel on which we operate (is updated) - * \param[in] rho0 Range at start of interval * \param[in] rho1 Current range, after \a dt has expired * \param[in dt delta-t (time difference) in seconds */ -void computeCodePhase(channel_t *chan, range_t rho0, range_t rho1, double dt) +void computeCodePhase(channel_t *chan, range_t rho1, double dt) { double ms; int ims; double rhorate; // Pseudorange rate. - rhorate = (rho1.range - rho0.range)/dt; + rhorate = (rho1.range - chan->rho0.range)/dt; // Carrier and code frequency. chan->f_carr = -rhorate/LAMBDA_L1; chan->f_code = CODE_FREQ + chan->f_carr*CARR_TO_CODE; // Initial code phase and data bit counters. - ms = (((rho0.g.sec-chan->g0.sec)+6.0) - rho0.range/SPEED_OF_LIGHT)*1000.0; + ms = (((chan->rho0.g.sec-chan->g0.sec)+6.0) - chan->rho0.range/SPEED_OF_LIGHT)*1000.0; ims = (int)ms; chan->code_phase = (ms-(double)ims)*CA_SEQ_LEN; // in chip @@ -1173,6 +1073,9 @@ void computeCodePhase(channel_t *chan, range_t rho0, range_t rho1, double dt) chan->codeCA = chan->ca[(int)chan->code_phase]*2-1; chan->dataBit = (int)((chan->dwrd[chan->iword]>>(29-chan->ibit)) & 0x1UL)*2-1; + // Save current pseudorange + chan->rho0 = rho1; + return; } @@ -1290,6 +1193,181 @@ int readNmeaGGA(double xyz[USER_MOTION_SIZE][3], const char *filename) return (numd); } +int generateNavMsg(gpstime_t g, channel_t *chan, int init) +{ + int iwrd,isbf; + gpstime_t g0; + unsigned long tow; + unsigned sbfwrd; + unsigned long prevwrd; + int nib; + + g0.week = g.week; + g0.sec = (double)(((unsigned long)(g.sec+0.5))/30UL) * 30.0; // Align with the full frame length = 30 sec + chan->g0 = g0; // Data bit reference time + + tow = ((unsigned long)g0.sec)/6UL; + + if (init==1) // Initialize subframe 5 + { + prevwrd = 0UL; + + for (iwrd=0; iwrdsbf[4][iwrd]; + + // Add TOW-count message into HOW + if (iwrd==1) + sbfwrd |= ((tow&0x1FFFFUL)<<13); + + // Compute checksum + sbfwrd |= (prevwrd<<30) & 0xC0000000UL; // 2 LSBs of the previous transmitted word + nib = ((iwrd==1)||(iwrd==9))?1:0; // Non-information bearing bits for word 2 and 10 + chan->dwrd[iwrd] = computeChecksum(sbfwrd, nib); + + prevwrd = chan->dwrd[iwrd]; + } + } + else // Save subframe 5 + { + for (iwrd=0; iwrddwrd[iwrd] = chan->dwrd[N_DWRD_SBF*N_SBF+iwrd]; + + prevwrd = chan->dwrd[iwrd]; + } + /* + // Sanity check + if (((chan->dwrd[1])&(0x1FFFFUL<<13)) != ((tow&0x1FFFFUL)<<13)) + { + printf("\nWARNING: Invalid TOW in subframe 5.\n"); + return(0); + } + */ + } + + for (isbf=0; isbfsbf[isbf][iwrd]; + + // Add TOW-count message into HOW + if (iwrd==1) + sbfwrd |= ((tow&0x1FFFFUL)<<13); + + // Compute checksum + sbfwrd |= (prevwrd<<30) & 0xC0000000UL; // 2 LSBs of the previous transmitted word + nib = ((iwrd==1)||(iwrd==9))?1:0; // Non-information bearing bits for word 2 and 10 + chan->dwrd[(isbf+1)*N_DWRD_SBF+iwrd] = computeChecksum(sbfwrd, nib); + + prevwrd = chan->dwrd[(isbf+1)*N_DWRD_SBF+iwrd]; + } + } + + return(1); +} + +int checkSatVisibility(ephem_t eph, gpstime_t g, double *xyz, double elvMask, double *azel) +{ + double llh[3],neu[3]; + double pos[3],vel[3],clk[3],los[3]; + double tmat[3][3]; + + if (eph.vflg != 1) + return (-1); // Invalid + + xyz2llh(xyz,llh); + ltcmat(llh, tmat); + + satpos(eph, g, pos, vel, clk); + subVect(los, pos, xyz); + ecef2neu(los, tmat, neu); + neu2azel(azel, neu); + + if (azel[1]*R2D > elvMask) + return (1); // Visible + // else + return (0); // Invisible +} + +int allocateChannel(channel_t *chan, ephem_t *eph, gpstime_t grx, double *xyz, double elvMask) +{ + int nsat=0; + int i,sv; + double azel[2]; + + range_t rho; + double ref[3]={0.0}; + double r_ref,r_xyz; + double phase_ini; + + for (sv=0; sv=0) // Not visible but allocated + { + // Clear channel + chan[allocatedSat[sv]].prn = 0; + + // Clear satellite allocation flag + allocatedSat[sv] = -1; + } + } + + return(nsat); +} + void usage(void) { printf("Usage: gps-sdr-sim [options]\n" @@ -1298,9 +1376,13 @@ void usage(void) " -u User motion file (dynamic mode)\n" " -g NMEA GGA stream (dynamic mode)\n" " -l Lat,Lon,Hgt (static mode) e.g. 30.286502,120.032669,100\n" + " -t Scenario start time YYYY/MM/DD,hh:mm:ss\n" + " -d Duration [sec] (max: %.0f)\n" " -o I/Q sampling data file (default: gpssim.bin)\n" " -s Sampling frequency [Hz] (default: 2600000)\n" - " -b I/Q data format [8/16] (default: 8)\n"); + " -b I/Q data format [1/8/16] (default: 16)\n" + " -v Show details about simulated channels\n", + ((double)USER_MOTION_SIZE)/10.0); return; } @@ -1312,40 +1394,22 @@ int main(int argc, char *argv[]) FILE *fp; int sv; - int neph; - ephem_t eph[MAX_SAT]; + int neph,ieph; + ephem_t eph[EPHEM_ARRAY_SIZE][MAX_SAT]; gpstime_t g0; double llh[3]; - double pos[3],vel[3],clk[2]; - double tmat[3][3]; - double los[3]; - double neu[3]; - double azel[2]; int i; - int nsat; channel_t chan[MAX_CHAN]; - double elvmask = 0.0/R2D; + double elvmask = 0.0; // in degree - int isbf,iwrd; - unsigned long tow; - unsigned long sbf[5][N_DWRD_SBF]; - unsigned long sbfwrd; - unsigned long prevwrd; - int nib; - -#ifdef _SINE_LUT int ip,qp; int iTable; -#else - double ip,qp; -#endif - void *iq_buff = NULL; + short *iq_buff = NULL; + signed char *iq8_buff = NULL; gpstime_t grx; - range_t rho0[MAX_SAT]; - double delt; int isamp; @@ -1354,8 +1418,8 @@ int main(int argc, char *argv[]) char umfile[MAX_CHAR]; double xyz[USER_MOTION_SIZE][3]; - bool staticLocationMode = false; - bool nmeaGGA = false; + int staticLocationMode = FALSE; + int nmeaGGA = FALSE; char navfile[MAX_CHAR]; char outfile[MAX_CHAR]; @@ -1366,6 +1430,21 @@ int main(int argc, char *argv[]) int result; + int gain[MAX_CHAN]; + double path_loss; + double ant_gain; + double ant_pat[37]; + int ibs; // boresight angle index + + datetime_t t0,tmin,tmax; + gpstime_t gmin,gmax; + double dt; + int igrx; + + double duration; + int iduration; + int verb; + //////////////////////////////////////////////////////////// // Read options //////////////////////////////////////////////////////////// @@ -1375,7 +1454,10 @@ int main(int argc, char *argv[]) umfile[0] = 0; strcpy(outfile, "gpssim.bin"); samp_freq = 2.6e6; - data_format = SC08; + data_format = SC16; + g0.week = -1; // Invalid start time + iduration = USER_MOTION_SIZE; + verb = 0; if (argc<3) { @@ -1383,7 +1465,7 @@ int main(int argc, char *argv[]) exit(1); } - while ((result=getopt(argc,argv,"e:u:g:l:o:s:b:"))!=-1) + while ((result=getopt(argc,argv,"e:u:g:l:o:s:b:t:d:v"))!=-1) { switch (result) { @@ -1392,16 +1474,16 @@ int main(int argc, char *argv[]) break; case 'u': strcpy(umfile, optarg); - nmeaGGA = false; + nmeaGGA = FALSE; break; case 'g': strcpy(umfile, optarg); - nmeaGGA = true; + nmeaGGA = TRUE; break; case 'l': // Static geodetic coordinates input mode // Added by scateu@gmail.com - staticLocationMode = true; + staticLocationMode = TRUE; sscanf(optarg,"%lf,%lf,%lf",&llh[0],&llh[1],&llh[2]); llh[0] = llh[0] / R2D; // convert to RAD llh[1] = llh[1] / R2D; // convert to RAD @@ -1413,18 +1495,41 @@ int main(int argc, char *argv[]) samp_freq = atof(optarg); if (samp_freq<1.0e6) { - printf("Invalid sampling frequency.\n"); + printf("ERROR: Invalid sampling frequency.\n"); exit(1); } break; case 'b': data_format = atoi(optarg); - if (data_format!=SC08 && data_format!=SC16) + if (data_format!=SC01 && data_format!=SC08 && data_format!=SC16) { - printf("Invalid data format.\n"); + printf("ERROR: Invalid I/Q data format.\n"); exit(1); } break; + case 't': + sscanf(optarg, "%d/%d/%d,%d:%d:%lf", &t0.y, &t0.m, &t0.d, &t0.hh, &t0.mm, &t0.sec); + if (t0.y<=1980 || t0.m<1 || t0.m>12 || t0.d<1 || t0.d>31 || + t0.hh<0 || t0.hh>23 || t0.mm<0 || t0.mm>59 || t0.sec<0.0 || t0.sec>=60.0) + { + printf("ERROR: Invalid date and time.\n"); + exit(1); + } + t0.sec = floor(t0.sec); + date2gps(&t0, &g0); + break; + case 'd': + duration = atof(optarg); + if (duration<0.0 || duration>((double)USER_MOTION_SIZE)/10.0) + { + printf("ERROR: Invalid duration.\n"); + exit(1); + } + iduration = (int)(duration*10.0+0.5); + break; + case 'v': + verb = 1; + break; case ':': case '?': usage(); @@ -1436,13 +1541,13 @@ int main(int argc, char *argv[]) if (navfile[0]==0) { - printf("GPS ephemeris file is not specified.\n"); + printf("ERROR: GPS ephemeris file is not specified.\n"); exit(1); } if (umfile[0]==0 && !staticLocationMode) { - printf("User motion file / NMEA GGA stream is not specified.\n"); + printf("ERROR: User motion file / NMEA GGA stream is not specified.\n"); printf("You may use -l to specify the static location directly.\n"); exit(1); } @@ -1461,26 +1566,25 @@ int main(int argc, char *argv[]) if (!staticLocationMode) { // Read user motion file - if (nmeaGGA==true) + if (nmeaGGA==TRUE) numd = readNmeaGGA(xyz, umfile); else numd = readUserMotion(xyz, umfile); if (numd==-1) { - printf("Failed to open user motion / NMEA GGA file.\n"); + printf("ERROR: Failed to open user motion / NMEA GGA file.\n"); exit(1); } else if (numd==0) { - printf("Failed to read user motion / NMEA GGA data.\n"); + printf("ERROR: Failed to read user motion / NMEA GGA data.\n"); exit(1); } - printf("Track points = %d\n", numd); - - // Initial location in Geodetic coordinate system - xyz2llh(xyz[0], llh); + // Set simulation duration + if (numd>iduration) + numd = iduration; } else { @@ -1489,7 +1593,7 @@ int main(int argc, char *argv[]) printf("Using static location mode.\n"); llh2xyz(llh,xyz[0]); // Convert llh to xyz - numd = USER_MOTION_SIZE; + numd = iduration; for (iumd=1; iumd0) + for (sv=0; svelvmask) - { - chan[nsat].prn = sv+1; - nsat++; - - printf("%02d %6.1f %5.1f\n", sv+1, azel[0]*R2D, azel[1]*R2D); - } + gmax = eph[neph-1][sv].toc; + tmax = eph[neph-1][sv].t; + break; } } - printf("Number of channels = %d\n", nsat); + if (g0.week>=0) + { + if (subGpsTime(g0, gmin)<0.0 || subGpsTime(gmax, g0)<0.0) + { + printf("ERROR: Invalid start time.\n"); + printf("tmin = %4d/%02d/%02d,%02d:%02d:%02.0f (%d:%.0f)\n", + tmin.y, tmin.m, tmin.d, tmin.hh, tmin.mm, tmin.sec, + gmin.week, gmin.sec); + printf("tmax = %4d/%02d/%02d,%02d:%02d:%02.0f (%d:%.0f)\n", + tmax.y, tmax.m, tmax.d, tmax.hh, tmax.mm, tmax.sec, + gmax.week, gmax.sec); + exit(1); + } + } + else + { + g0 = gmin; + t0 = tmin; + } + + printf("Start time = %4d/%02d/%02d,%02d:%02d:%02.0f (%d:%.0f)\n", + t0.y, t0.m, t0.d, t0.hh, t0.mm, t0.sec, g0.week, g0.sec); + printf("Duration = %.1f [sec]\n", ((double)numd)/10.0); + + // Select the current set of ephemerides + ieph = -1; + + for (i=0; i=-SECONDS_IN_HOUR && dt=0) // ieph has been set + break; + } + + if (ieph == -1) + { + printf("ERROR: No current set of ephemerides has been found.\n"); + exit(1); + } //////////////////////////////////////////////////////////// // Baseband signal buffer and output file //////////////////////////////////////////////////////////// // Allocate I/Q buffer - if (data_format==SC08) - iq_buff = (signed char *)calloc(2*iq_buff_size, 1); - else - iq_buff = (short *)calloc(2*iq_buff_size, 2); + iq_buff = calloc(2*iq_buff_size, 2); if (iq_buff==NULL) { - printf("Faild to allocate IQ buffer.\n"); + printf("ERROR: Faild to allocate 16-bit I/Q buffer.\n"); exit(1); } + if (data_format==SC08) + { + iq8_buff = calloc(2*iq_buff_size, 1); + if (iq8_buff==NULL) + { + printf("ERROR: Faild to allocate 8-bit I/Q buffer.\n"); + exit(1); + } + } + else if (data_format==SC01) + { + iq8_buff = calloc(iq_buff_size/4, 1); // byte = {I0, Q0, I1, Q1, I2, Q2, I3, Q3} + if (iq8_buff==NULL) + { + printf("ERROR: Faild to allocate compressed 1-bit I/Q buffer.\n"); + exit(1); + } + } + // Open output file if (NULL==(fp=fopen(outfile,"wb"))) { - printf("Failed to open output file.\n"); + printf("ERROR: Failed to open output file.\n"); exit(1); } @@ -1591,84 +1733,33 @@ int main(int argc, char *argv[]) // Initialize channels //////////////////////////////////////////////////////////// + // Clear all channels + for (i=0; i0) + printf("%02d %6.1f %5.1f %11.1f\n", chan[i].prn, + chan[i].azel[0]*R2D, chan[i].azel[1]*R2D, chan[i].rho0.d); } //////////////////////////////////////////////////////////// - // Generate subframes and data bits + // Receiver antenna gain pattern //////////////////////////////////////////////////////////// - for (i=0; i Configuration Properties -> C/C++ -> Language -> Open MP Support -> Yes (/openmp) - for (i=0; i0) { -#ifdef _SINE_LUT - iTable = (int)floor(chan[i].carr_phase*512.0); + // Refresh code phase and data bit counters + int sv = chan[i].prn-1; + range_t rho; - ip = chan[i].dataBit * chan[i].codeCA * cosTable512[iTable]; - qp = chan[i].dataBit * chan[i].codeCA * sinTable512[iTable]; + // Current pseudorange + computeRange(&rho, eph[ieph][sv], grx, xyz[iumd]); + chan[i].azel[0] = rho.azel[0]; + chan[i].azel[1] = rho.azel[1]; - // Store I/Q samples into buffer - chan[i].iq_buff[isamp*2] = (short)ip; - chan[i].iq_buff[isamp*2+1] = (short)qp; -#else - ip = chan[i].dataBit * chan[i].codeCA * cos(2.0*PI*chan[i].carr_phase); - qp = chan[i].dataBit * chan[i].codeCA * sin(2.0*PI*chan[i].carr_phase); + // Update code phase and data bit counters + computeCodePhase(&chan[i], rho, 0.1); + chan[i].carr_phasestep = (int)(512 * 65536.0 * chan[i].f_carr * delt); - // Store I/Q samples into buffer - chan[i].iq_buff[isamp*2] = (short)(ADC_GAIN*ip); - chan[i].iq_buff[isamp*2+1] = (short)(ADC_GAIN*qp); -#endif - // Update code phase - chan[i].code_phase += chan[i].f_code * delt; + // Path loss + path_loss = 20200000.0/rho.d; - if (chan[i].code_phase>=CA_SEQ_LEN) - { - chan[i].code_phase -= CA_SEQ_LEN; + // Receiver antenna gain + ibs = (int)((90.0-rho.azel[1]*R2D)/5.0); // covert elevation to boresight + ant_gain = ant_pat[ibs]; - chan[i].icode++; - - if (chan[i].icode>=20) // 20 C/A codes = 1 navigation data bit - { - chan[i].icode = 0; - chan[i].ibit++; - - if (chan[i].ibit>=30) // 30 navigation data bits = 1 word - { - chan[i].ibit = 0; - chan[i].iword++; - } - - // Set new navigation data bit - chan[i].dataBit = (int)((chan[i].dwrd[chan[i].iword]>>(29-chan[i].ibit)) & 0x1UL)*2-1; - } - } - - // Set currnt code chip - chan[i].codeCA = chan[i].ca[(int)chan[i].code_phase]*2-1; - - // Update carrier phase - chan[i].carr_phase += chan[i].f_carr * delt; - - if (chan[i].carr_phase>=1.0) - chan[i].carr_phase -= 1.0; - else if (chan[i].carr_phase<0.0) - chan[i].carr_phase += 1.0; + // Signal gain + gain[i] = (int)(path_loss*ant_gain*100.0); // scaled by 100 } + } + + for (isamp=0; isamp0) + { + iTable = (chan[i].carr_phase >> 16) & 511; + + ip = chan[i].dataBit * chan[i].codeCA * cosTable512[iTable] * gain[i]; + qp = chan[i].dataBit * chan[i].codeCA * sinTable512[iTable] * gain[i]; + + i_acc += (ip + 50)/100; + q_acc += (qp + 50)/100; + + // Update code phase + chan[i].code_phase += chan[i].f_code * delt; + + if (chan[i].code_phase>=CA_SEQ_LEN) + { + chan[i].code_phase -= CA_SEQ_LEN; + + chan[i].icode++; + + if (chan[i].icode>=20) // 20 C/A codes = 1 navigation data bit + { + chan[i].icode = 0; + chan[i].ibit++; + + if (chan[i].ibit>=30) // 30 navigation data bits = 1 word + { + chan[i].ibit = 0; + chan[i].iword++; + /* + if (chan[i].iword>=N_DWRD) + printf("\nWARNING: Subframe word buffer overflow.\n"); + */ + } + + // Set new navigation data bit + chan[i].dataBit = (int)((chan[i].dwrd[chan[i].iword]>>(29-chan[i].ibit)) & 0x1UL)*2-1; + } + } + + // Set currnt code chip + chan[i].codeCA = chan[i].ca[(int)chan[i].code_phase]*2-1; + + // Update carrier phase + chan[i].carr_phase += chan[i].carr_phasestep; + } + } + + // Store I/Q samples into buffer + iq_buff[isamp*2] = (short)i_acc; + iq_buff[isamp*2+1] = (short)q_acc; + } // End of omp parallel for - if (data_format==SC08) + if (data_format==SC01) { for (isamp=0; isamp<2*iq_buff_size; isamp++) { - signed char sample = 0; - for (i=0; i>4); // 12-bit bladeRF -> 8-bit HackRF - ((signed char*)iq_buff)[isamp] = sample; + if (isamp%8==0) + iq8_buff[isamp/8] = 0x00; + + iq8_buff[isamp/8] |= (iq_buff[isamp]>0?0x01:0x00)<<(7-isamp%8); } - fwrite(iq_buff, 1, 2*iq_buff_size, fp); + + fwrite(iq8_buff, 1, iq_buff_size/4, fp); + } + else if (data_format==SC08) + { + for (isamp=0; isamp<2*iq_buff_size; isamp++) + iq8_buff[isamp] = iq_buff[isamp]>>4; // 12-bit bladeRF -> 8-bit HackRF + + fwrite(iq8_buff, 1, 2*iq_buff_size, fp); } - else + else // data_format==SC16 { + /* for (isamp=0; isamp<2*iq_buff_size; isamp++) - { - short sample = 0; - for (i=0; i0?1000:-1000; // Emulated 1-bit I/Q + */ fwrite(iq_buff, 2, 2*iq_buff_size, fp); } + // + // Update navigation message and channel allocation every 30 seconds + // + + igrx = (int)(grx.sec*10.0+0.5); + + if (igrx%300==0) // Every 30 seconds + { + // Update navigation message + for (i=0; i0) + generateNavMsg(grx, &chan[i], 0); + + // Update channel allocation + allocateChannel(chan, eph[ieph], grx, xyz[iumd], elvmask); + + // Show ditails about simulated channels + if (verb) + { + printf("\n"); + for (i=0; i0) + printf("%02d %6.1f %5.1f %11.1f\n", chan[i].prn, + chan[i].azel[0]*R2D, chan[i].azel[1]*R2D, chan[i].rho0.d); + } + } + } + // Update receiver time grx.sec += 0.1; // Update time counter - printf("\rTime = %4.1f", grx.sec-g0.sec); + printf("\rTime into run = %4.1f", grx.sec-g0.sec); fflush(stdout); } @@ -1808,14 +1932,12 @@ int main(int argc, char *argv[]) // Free I/Q buffer free(iq_buff); - for (i=0; i #include +#include #include +#ifdef _WIN32 +#include "getopt.h" +#else +#include +#endif #define TX_FREQUENCY 1575420000 #define TX_SAMPLERATE 2600000 @@ -15,6 +21,18 @@ #define NUM_TRANSFERS 16 #define TIMEOUT_MS 1000 +#define AMPLITUDE (1000) // Default amplitude for 12-bit I/Q + +void usage(void) +{ + fprintf(stderr, "Usage: bladeplayer [options]\n" + " -f I/Q sampling data file (required)\n" + " -b I/Q data format [1/16] (default: 16)\n" + " -g TX VGA1 gain (default: %d)\n", + TX_VGA1); + + return; +} int main(int argc, char *argv[]) { int status; @@ -26,16 +44,71 @@ int main(int argc, char *argv[]) enum state {INIT, READ_FILE, PAD_TRAILING, DONE}; enum state state = INIT; - if (argc!=2) { - fprintf(stderr, "Usage: bladeplayer \n"); + int compressed = 0; + uint8_t *read_buffer; + size_t samples_read; + int16_t lut[256][8]; + int16_t amp = AMPLITUDE; + int i,k; + + int gain = TX_VGA1; + int result; + int data_format; + char txfile[128]; + + // Empty TX file name + txfile[0] = 0; + + if (argc<3) { + usage(); exit(1); } + while ((result=getopt(argc,argv,"g:b:f:"))!=-1) + { + switch (result) + { + case 'g': + gain = atoi(optarg); + if (gain>-4 || gain<-35) + { + printf("ERROR: Invalid TX VGA1 gain.\n"); + exit(1); + } + break; + case 'b': + data_format = atoi(optarg); + if (data_format!=1 && data_format!=16) + { + printf("ERROR: Invalid I/Q data format.\n"); + exit(1); + } + else if (data_format==1) + compressed = 1; + break; + case 'f': + strcpy(txfile, optarg); + break; + case ':': + case '?': + usage(); + exit(1); + default: + break; + } + } + // Open TX file. - fp = fopen(argv[1], "rb"); + if (txfile[0]==0) + { + printf("ERROR: I/Q sampling data file is not specified.\n"); + exit(1); + } + + fp = fopen(txfile, "rb"); if (fp==NULL) { - fprintf(stderr, "Failed to open TX file: %s\n", argv[1]); + fprintf(stderr, "ERROR: Failed to open TX file: %s\n", argv[1]); exit(1); } @@ -75,13 +148,13 @@ int main(int argc, char *argv[]) printf("TX bandwidth: %u Hz\n", TX_BANDWIDTH); } - status = bladerf_set_txvga1(dev, TX_VGA1); + status = bladerf_set_txvga1(dev, gain); if (status != 0) { fprintf(stderr, "Failed to set TX VGA1 gain: %s\n", bladerf_strerror(status)); goto out; } else { - printf("TX VGA1 gain: %d dB\n", TX_VGA1); + printf("TX VGA1 gain: %d dB\n", gain); } status = bladerf_set_txvga2(dev, TX_VGA2); @@ -97,13 +170,27 @@ int main(int argc, char *argv[]) printf("Running...\n"); // Allocate a buffer to hold each block of samples to transmit. - tx_buffer = (int16_t*)malloc(SAMPLES_PER_BUFFER* 2 * sizeof(int16_t)); + tx_buffer = (int16_t*)malloc(SAMPLES_PER_BUFFER * 2 * sizeof(int16_t)); if (tx_buffer == NULL) { fprintf(stderr, "Failed to allocate TX buffer.\n"); goto out; } + // if compressed + read_buffer = (uint8_t*)malloc(SAMPLES_PER_BUFFER / 4); + + if (read_buffer == NULL) { + fprintf(stderr, "Failed to allocate read buffer.\n"); + goto out; + } + + for (i=0; i<256; i++) + { + for (k=0; k<8; k++) + lut[i][k] = ((i>>(7-k))&0x1)?amp:-amp; + } + // Configure the TX module for use with the synchronous interface. status = bladerf_sync_config(dev, BLADERF_MODULE_TX, @@ -131,6 +218,9 @@ int main(int argc, char *argv[]) int16_t *tx_buffer_current = tx_buffer; unsigned int buffer_samples_remaining = SAMPLES_PER_BUFFER; + // if compressed + unsigned int read_samples_remaining = SAMPLES_PER_BUFFER / 4; + // Keep adding to the buffer until it is full or a failure occurs while (buffer_samples_remaining > 0 && status == 0 && state != DONE) { size_t samples_populated = 0; @@ -139,11 +229,35 @@ int main(int argc, char *argv[]) case INIT: case READ_FILE: // Read from the input file - samples_populated = fread(tx_buffer_current, - 2 * sizeof(int16_t), - buffer_samples_remaining, - fp); - + if (compressed) + { + int16_t *write_buffer_current = tx_buffer; + + samples_read = fread(read_buffer, + sizeof(uint8_t), + read_samples_remaining, + fp); + + samples_populated = samples_read * 4; + buffer_samples_remaining = read_samples_remaining * 4; + + // Expand compressed data into TX buffer + for (i=0; i