In a previous post I discussed my BER simulations with the LilacSat-1 receiver in gr-satellites. I found out that the "Feed Forward AGC" block was not performing well and causing a considerable loss in performance. David Rowe remarked that an AGC should not be necessary in a PSK modem, since PSK is not sensitive to amplitude. While this is true, several of the GNU Radio blocks that I'm using in my BPSK receiver are indeed sensitive to amplitude, so an AGC must be used with them. Here I look at these blocks and I explain the new AGC that I'm now using in gr-satellites.
The basic BPSK receiver that I'm using in GNU Radio is show below. An FLL Band-Edge block is used first for coarse frequency correction, a low pass filter takes out some of the noise off the sides of the signal, the Polyphase Clock Sync performs clock recovery and RRC filtering, and the Costas loop acts as a PLL to lock to the phase of the carrier.
It turns out that all the three blocks in this chain (besides the low pass filter) have feedback loops with discriminators that assume a signal of amplitude 1. Let us analyse this in detail, starting by the Costas loop, which is probably the best known and simplest algorithm amongst the three used here.
Recall that a Costas loop works by using a phase detector to measure the phase of the signal and then using this measure as an error input in a feedback loop to try to drive the phase to zero. The phase detector of a BPSK Costas loop should be insensitive to phase changes of 180º, meaning that it should output zero both for a phase of 0º and a phase of 180º. Otherwise we just get a regular PLL, which is sensitive to phase changes. Mathematically, the optimal phase detector for a BPSK Costas loop is . Note that this is just the phase of the point when is in the first or fourth quadrant and the phase of when is in the second or third quadrant. This is just what we wanted.
Often, to simplify computations a different phase detector is used. This phase detector should approximate well at least when the phase of is near 0º and near 180º. The detector used in the Costas loop GNU Radio block is just . This works as follows. If , then , where is the phase of . Now, for near we have just as we wanted, and also similarly for near . However, this only works if , which means that the amplitude of the signal is 1. To make this detector insensitive to amplitude we would have to use instead.
The algorithm used in the Polyphase clock sync is best read in the documentation. We see that there are two polyphase filterbanks: one contains matched filters at different phases and the other one contains their derivatives. The error is computed as
where is the output of the -th matched filter and is the output of its corresponding derivative filter. We see that this is sensitive to the amplitude of the input signal. If the input signal is multiplied by , then gets multiplied by .
Similarly, the FLL Band Edge block also includes an algorithm whose error discriminator depends on the amplitude of the input signal.
It would be interesting to modify the discriminators in these 3 blocks to make a BPSK receiver which is insensitive to amplitude. For now, I have just tried to include a better AGC in gr-satellites. Besides the Feed Foward AGC, GNU Radio includes 3 AGC blocks. The simplest is the AGC block. It has a reference value , and at each step it transforms the input into the output , and updates the gain as . The problem with this algorithm is that if the input level is very low, then grows almost linearly as , and so it takes a lot to ramp up to the appropriate level if the rate is set to a value that provides good performance in the steady state.
The AGC2 algorithm is similar but it uses different rates for attack and decay. There is also an AGC3 algorithm which presumably solves this problem by doing a linear average of the signal amplitude the first time and then using an IIR filter to update the gain. However, I haven't managed to make it work properly.
In the end, I haven't used any of the AGC, AGC2 or AGC3 blocks for gr-satellites. The AGC that I'm using is rather simple. It computes the average RMS level of the signal using the GNU Radio RMS block and then divides the signal by this RMS. This is inspired by Blockstream satellite, which uses the same kind of AGC. I'm calling this block the "RMS AGC".
The RMS block computes and averages the RMS power using a single-pole IIR filter as
where is the input signal, is the averaged power and is the RMS. I have found that a value of works well for gr-satellites, since it gives a time constant of samples. Since gr-satellites uses a sampling rate of 48kHz, this is 2ms. For 9k6 and 1k2 modems it provides an averaging over several symbols, while still being short enough to ramp up to a stable value during the preamble of the packet.
I have run the BER simulations again, now using an RMS AGC block and an input signal amplitude of 0.1, to force the AGC do some work. It seems that the BPSK receiver works best at a signal amplitude of 0.5, which is weird, because all the blocks are designed for an amplitude of 1, as we have seen above. For this reason, I'm using a reference level of 0.5 in the RMS AGC. For comparison, I also include the BER simulation obtained in the previous post with no AGC and a signal amplitude of 0.5. It seems that the performance of the Viterbi decoder is slightly better with the RMS AGC.
Thanks to David Rowe VK5DGR for all his advice regarding modems.