Pictured above is the front-end, first mixer and IF amplifier of an experimental GPS receiver.
The leftmost SMA is connected to a commercial antenna with integral LNA and SAW filter.
A synthesized first local oscillator drives the bottom SMA.
Pin headers to the right are power input and IF output.
The latter is connected to a Xilinx FPGA which not only performs DSP,
but also hosts a fractional-N frequency synthesizer.
More on this later.
I was motivated to design this receiver after reading the work [1]
of Matjaž Vidmar, S53MV, who developed a GPS receiver from scratch, using mainly discrete components, over 20 years ago.
His use of DSP following a hard-limiting IF and 1-bit ADC interested me.
The receiver described here works on the same principle.
Its 1-bit ADC is the 6-pin IC near the pin headers, an LVDS-output comparator.
Hidden under noise but not obliterated in the bi-level quantised mush that emerges are signals from every satellite in view.
All GPS satellites transmit on the same frequency, 1575.42 MHz, using direct sequence spread spectrum (DSSS).
The L1 carrier is spread over a 2 MHz bandwidth and its strength at the Earth’s surface is -130 dBm.
Thermal noise power in the same bandwidth is -111 dBm, so a GPS signal at the receiving antenna is ~ 20 dB below the noise floor.
That any of the signals present, superimposed one on another and buried in noise,
are recoverable after bi-level quantisation seems counter-intuitive!
I wrote a simulation to convince myself.
GPS relies on the correlation properties of pseudo-random sequences called Gold Codes to separate signals from noise and each other.
Every satellite transmits a unique sequence.
All uncorrelated signals are noise, including those of other satellites and hard-limiter quantisation errors.
Mixing with the same code in the correct phase de-spreads the wanted signal and further spreads everything else.
Narrow-band filtering then removes wideband noise without affecting the (once again narrow) wanted signal.
Hard-limiting (1-bit ADC) degrades SNR by less than 3 dB, a price worth paying to avoid hardware AGC.
May 2013 Update
This is now a truly portable, battery-powered, 12-channel GPS receiver with turnkey software,
which acquires and tracks satellites, and continuously recalculates its position, without user-intervention.
The complete system (below, left) comprises: 16×2 LCD display, Raspberry Pi Model “A” computer, two custom printed-circuit boards, commercial patch antenna and Li-Ion battery.
Total system current consumption is 0.4A for a battery life of 5 hours.
The Raspberry Pi is powered through the ribbon cable linking its GPIO header to the “Frac7” FPGA board and requires no other connections.
Currently, the Pi is running Raspbian Linux.
A smaller distro would shorten time to first fix.
After booting from SD-Card, the GPS application software starts automatically.
On exit, it provides a means to properly shutdown the Pi before powering-off.
Pi software development was done “head-less” via SSH and FTP over a USB Wi-Fi dongle.
Source code and documentation can be found towards the bottom of this page.
Both custom PCBs are simple 2-layer PTH boards with continuous ground planes on the bottom.
Going clockwise around the Xilinx Spartan 3 on the “Frac7” FPGA board:
from 12 o’clock to 3 o’clock are the loop filter, VCO, power splitter and prescaler of the microwave frequency synthesizer;
bottom right are the joystick and JTAG connector; and, at 6 o’clock, a pin header for the Raspberry Pi ribbon cable.
Far left is the LCD connector.
Near left is a temperature-compensated voltage-controlled crystal oscillator (TCVCXO) providing a stable reference frequency, vital for GPS reception.
The TCVCXO is good; but not quite up to GPS standard when operating un-boxed in windy locations.
Blowing on it displaces the 10.000000 MHz crystal oscillator by around 1 part in 10 million or 1 Hz,
which is magnified 150 times by the synthesizer PLL.
This is enough to momentarily unlock the satellite tracking loops, if done suddenly.
The device is also slightly sensitive to infra-red e.g. from halogen bulbs and TV remotes!
When first posted in 2011, this was a four-channel receiver, meaning it could only track four satellites simultaneously.
At least four are required to solve for user position and receiver clock bias; but greater accuracy is possible with more.
In that original version, four identical instances of the “tracker” module filled the FPGA.
But most of the flops were only clocked once per millisecond.
Now, a custom “soft-core” CPU inside the FPGA serializes the processing
and only 50% of the FPGA fabric is required for an 8-channel receiver or 67% for 12-channels.
Number of channels is a parameter in the source and could go higher.
Positional accuracy is best when the antenna can see 360° of sky and receive signals from all directions.
Generally, the more satellites in view, the better.
Two or more satellites on the same bearing can lead to what is termed “bad geometry.”
The best fix so far was ±1 metres at a very open location using 12 satellites;
but accuracy is typically ±5 metres in poorer locations with fewer satellites.
September 2014 Update
The source code for this project has been re-released under the GNU General Public License (GPL).
Architecture
Processing is split between FPGA and Pi by complexity and urgency.
The Pi handles math-intensive heavy-lifting at its own pace.
The FPGA synthesizes the first local oscillator, services high-priority events in real-time and tracks satellites autonomously.
The Pi controls the FPGA via an SPI interface.
Conveniently, the same SPI is used to load the FPGA configuration bitstream and binary executable code for the embedded CPU.
The FPGA can also be controlled via a JTAG cable from a Windows PC and auto-detects which interface is in use.
L1 frequencies are down-converted to a 1st IF of 22.6 MHz by mixing with a 1552.82 MHz local oscillator on the “GPS3” front-end board.
All subsequent IF and baseband signal processing is done digitally in the FPGA.
Two proportional-integral (PI) controllers per satellite, track carrier and code phase.
NAV data transmitted by the satellites is collected in FPGA memory.
This is uploaded to the Pi, which checks parity and extracts ephemerides from the bit stream.
When all required orbital parameters are collected, a snapshot is taken of certain internal FPGA counters,
from which time of transmission is computed to ± 15ns precision.
Much of the 1552.82 MHz synthesizer is implemented in the FPGA.
One might expect jitter problems, co-hosting a phase detector with other logic, but it works.
Synthesizer output spectral-purity is excellent, even though the FPGA core is toggling away furiously and not all on harmonically-related frequencies.
This approach was taken because a board similar to “Frac7” already existed from an earlier synthesizer project.
Adding a front-end was the shortest route to a prototype receiver.
But that first version was not portable: it had inconvenient power requirements and no on-board frequency standard.
Front-end
Signal processing up to and including the hard-limiter:
The LMH7220 comparator has a maximum input offset voltage of 9.5mV.
Amplified thermal noise must comfortably exceed this to keep it toggling.
Weak GPS signals only influence the comparator near zero crossings!
They are “sampled” by the noise!
To estimate noise level at the comparator input we tabulate gains, insertion losses and noise figures:
LNA | SAW | Coax | RF | Mixer | IF | Overall system noise figure | |
Gain | +28 | -1.5 | -3.9 | +20 | -6 | ||
NF | 0.8 | 1.5 | 3.9 | 2 | 6 | 7 | 0.8 dB |
In-band noise at the mixer output is -174+0.8+28-1.5-3.9+20-6+10*log10(2.5e6) = -73 dBm or 52µV RMS.
The mixer is resistively terminated in 50-ohms and the stages thereafter work at higher impedance.
The discrete IF strip has an overall voltage gain of 1000 so the comparator input level is 52mV RMS.
The LMH7220 adds 59 dB of gain making a total of 119 dB for the whole IF.
Deploying so much gain at one frequency was a risk.
To minimise it, balanced circuitry over a solid ground plane was used and screened twisted-pair carries the output to the FPGA.
The motivation was simplicity, avoiding a second conversion.
In practice, the circuit is stable, so the gamble paid-off.
Active decoupler Q1 supplies 5V for the remote LNA.
MMIC amplifier U2 provides 20 dB gain (not at IF!) and ensures low overall system noise figure, even if long antenna cables are used.
L1 and L2 are hand-wound microwave chokes with very high self-resonant frequency, mounted perpendicular to one another and clear of the ground plane.
Wind 14 turns, air-cored, 1mm inside diameter from 7cm lengths of 32swg enamelled copper wire.
Checked with the tracking generator on a Marconi 2383 SA, these were good to 4 GHz.
The Mini-Circuits MBA-15L DBM was chosen for its low 6 dB conversion loss at 1.5 GHz and low 4 dBm LO drive requirement.
R9 terminates the IF port.
Three fully-differential IF amplifier stages follow the mixer.
Low-Q parallel tuned circuits strung between collectors set the -3 dB bandwidth around 2.5 MHz and prevent build-up of DC offsets.
L4, L5 and L6 are screened Toko 7mm coils.
The BFS17 was chosen for its high (but not too high) 1 GHz fT.
Ie is 2mA for lowest noise and reasonable βre.
The 22.6 MHz 1st IF is digitally down-converted to 2.6 MHz by under-sampling at 10 MHz in the FPGA.
2.6 MHz lies close to the centre of the 5 MHz Nyquist bandwidth.
It is best to avoid the exact centre, for reasons that will be explained later.
Several other first IF frequencies are possible:
27.5 MHz, which produces spectrum inversion at the 2nd IF, has also been tried successfully.
There is a trade-off between image problems at lower and available BFS17 gain at higher frequencies.
Search
Signal detection entails resolving three unknowns: what satellites are in view, their Doppler shifts and code phases.
A sequential search of this three-dimensional space from a so-called “cold start” could take many minutes.
A “warm start” using almanac data to predict positions and velocities still requires a code search.
All 1023 code phases must be tested to find the maximum correlation peak.
Calculating 1023 correlation integrals in the time-domain is very expensive and redundant.
This GPS receiver uses an FFT-based algorithm that tests all code phases in parallel.
From cold, it takes 2.5 seconds on a 1.7 GHz Pentium to measure signal strength, Doppler shift and code phase of every visible satellite.
The Raspberry Pi is somewhat slower.
With over-bar denoting conjugation, the cross-correlation function y(Τ) of complex signal s(t) and code c(t) shifted by offset Τ is:
The Correlation Theorem states that the Fourier transform of a correlation integral is equal to the product of the complex conjugate of the Fourier transform of the first function and the Fourier transform of the second function:
FFT(y) = CONJUGATE(FFT(s)) * FFT(c)
Correlation is performed at baseband.
The 1.023 Mbps C/A code is 1023 chips or 1ms long.
Forward FFT length must be a multiple of this.
Sampling at 10 MHz for 4 ms results in an FFT bin size of 250 Hz.
41 Doppler shifts must be tested by rotating the frequency domain data, one bin at a time, up to ±20 bins = ±5 KHz.
Rotation can be applied to either function.
The 22.6 MHz 1st IF from the 1-bit ADC is under-sampled by a 10 MHz clock in the FPGA, digitally down-converting it to a 2nd IF of 2.6 MHz.
In software, the 2nd IF is down-converted to complex baseband (IQ) using quadrature local oscillators.
For bi-level signals, the mixers are simple XOR gates.
Although not shown above, the samples are temporarily buffered in FPGA memory.
The Pi is not able to accept them at 10 Mbps.
1.023 Mbps and 2.6 MHz are generated by numerically-controlled-oscillator (NCO) phase accumulators.
These frequencies are quite large compared to the sampling rate, and are not exact sub-harmonics of it.
Consequently, the NCOs have fractional spurs.
The number of samples per code chip dithers between 9 and 10.
Fortunately, DSSS receivers are tolerant of narrow-band interferers, external or self-generated.
Complex baseband is transformed to the frequency domain by a forward FFT which need only be computed once.
An FFT of each satellite’s C/A code is pre-computed.
Processing time is dominated by the inner-most loop which performs shifting, conjugation, complex multiplication and one inverse-FFT per satellite-Doppler test.
The Raspberry Pi’s Videocore GPU could be leveraged to speed things up.
At 10 MHz sampling rate, code phase is resolved to the nearest 100ns.
Typical CCF output is illustrated below:
Calculating peak to average power over this data gives a good estimate of SNR and is used to find the strongest signals.
The following were received at 20:14 GMT on 4 March 2011 in Cambridge, UK with the antenna on an outside North-facing window ledge:
PRN | NAVSTAR | Doppler (Hz) | Code Phase | SNR | |
9 | 33 | 1500 | 2.4 | 95.3 | |
17 | 57 | 500 | 364.5 | 98.4 | |
22 | 53 | 1000 | 844.7 | 54.1 | |
27 | 27 | 0 | 770.0 | 53.8 | |
28 | 48 | -3000 | 103.9 | 99.1 |
From northern la