IQ correction and mirror frequencies - df8oe/UHSDR GitHub Wiki
Text and figures © DD4WH, under GNU GPLv3
1. Understanding where the mirror frequencies are
Sometimes understanding where the rejected mirror frequencies are located can be slightly confusing. I want to try to shed light on how and where to find the mirror frequencies which are normally strongly rejected (up to 65dB) by the automatic or manual IQ amplitude and phase correction.
First, in order to see the mirror frequencies, you have to switch off Auto IQ correction in the menu and you have to strongly adjust the manual IQ amplitude and phase correction to wrong values (very high or very low values). For being able to do this, go to the 80m band. After setting these values to wrong values, you can choose any band to do further experiments.
Second, look for a strong carrier signal on the band of interest (with no signals around this strong signal +-30kHz) or (better) inject a strong signal with a signal generator.
Third, switch demod mode to SAM (this is a trick, so that the carrier is being caught by the SAM PLL as soon it is in the filter passband: in this case the small frequency display very accurately displays your carrier frequency or the mirror frequency depending on whatever you have in the passband)
F(rx) = receive frequency = frequency of the desired signal --> this is the strong signal visible in the spectrum display / waterfall
F(lo) = local oscillator frequency (if you set the display to magnify 1x, then this is the central frequency in the display)
IF = intermediate frequency = Xlate frequency (you can set this to -6kHz, +6kHz, -12kHz or +12kHz; in this example I use -12kHz)
F(mi) = mirror frequency (this is the frequency where we can find the undesired mirror of the signal that we inject/listen too)
You can calculate the mirror frequency by:
F(mi) = F(rx) - 2 * IF
Attention! Use the right sign of IF.
I will give you an example:
IF = -12k [ie. if you set magnify to 1x, the reception passband is to the right of the centre of the spectrum/waterfall display]
F(rx) = 3774k
then you can calculate the mirror frequency as F(mi) = 3774k - 2 * (-12k) = 3798kHz
SOMETHING IMPORTANT:
It can be very confusing, if you tune exactly to the signal = F(rx)
If you do that, you can see the mirror in the spectrum/waterfall display (as a large peak almost as big as the real signal), BUT:
now it seems it is located at
F(rx) + 2* IF = 3774k + 2 * (-12k) = 3750k (in our example)
BUT this signal is moving mirrorwise around the local oscillator frequency, when you retune and try to tune to the mirror! It is moving in the opposite direction of all other "real" signals. Use a low tune step (e.g. 10Hz) in order to experience this.
It is only when you tune to the real mirror frequency
F(mi) = 3774k - 2 * (-12) = 3798kHz
that you are able to catch the mirror and have it in your passband and demodulate it or measure its frequency.
REMEMBER: all of this can only be seen, when your IQ-correction is not working correctly or has been purposely set to weird values or your audio codec in your TRX temporarily shows the "twinpeak" issue (see below). In normal operation either keep Auto-IQ-correction ON or adjust IQ amplitude and IQ phase correction values so that the mirror signal is minimized (should be possible to achieve 60-65dB of attenuation depending on the hardware you use)
Have fun with experimenting!
Figure where the three signals can be seen: Signal = F(rx), CF = F(lo), Image = F(mirror)
2. Understanding I & Q phase and amplitude correction [also treats the "twinpeaks" syndrome]
Remember:
1.) the amplitudes of I and Q have to be equal 2.) the phase shift between I and Q has to be exactly 90 degrees
No hardware in this world can do that in an exact way, so this is where the software helps to achieve this.
The automatic I & Q correction uses the algorithm by Moseley & Slump (2006):
http://doc.utwente.nl/66726/1/moseley.pdf
If you really want to understand the algorithm, make sure you read that article and take your time to at least understand the general principle (probably you do not need to understand all the formula, but you have to understand ALL the figures and the general principle).
The aim is to compensate the phase and amplitude differences in the I & Q path by applying a
g = gain (amplitude) correction factor
p = phase correction factor [cos (p) for the I path and sin(p) for the Q path]
The amplitude of I and Q can be calibrated by simply adjusting gains in I & Q [or simpler just I].
Phase calibration is just as simple: A small amount of the I signal can be mixed into the Q channel and vice versa. This is equivalent to a slight phase shift of the signals (because the amplitude of a wave of different phase added to another wave determines the phase of the resulting wave).
How does the algorithm calculate the correction factors g and p ?
The algorithm takes a block of I and Q input samples [N = no of samples] and calculates three estimators:
teta1 = sum of [Q * sign (+1 or -1) of I] / N
teta2 = sum of [I * sign (+1 or -1) of I] / N
teta3 = sum of [Q * sign (+1 or -1) of Q] / N
The results for the three estimators are then lowpass-filtered with an exponential averager (1st order lowpass filter) to smooth their response:
eg. teta3 = 0.003 * teta3_new + 0.997 * teta3_old
After this lowpass, the three tetas are used to caculate the compensator coefficients c1 and c2:
c1 = teta1 / teta2
c2 = sqrt ( (teta3 * teta3 - teta1 * teta1) / (teta2 * teta2) )
Twinpeaks
"Twinpeaks" occur in the spectrum display and indicate that the mirror frequency and the RX frequency are accidentally of equal amplitude. This is caused by a wrong hardware conception in many brands of audio codecs and it occurs arbitrarily without the possibility of predicting when [and without the possibility to buy another codec IC, because ALL ICs of the same codec brand have this failure].
I & Q are sampled separately and synchroneously by two ADCs, they sample in this time order:
ADC1: I[1], I[2], I[3] . . .
ADC2: Q[1], Q[2], Q[3] . . .
If there is an accidental shift of only one sample at the startup of the hardware codec [this hardware bug ONLY occurs at the startup, NEVER during operation], the order of the samples is:
ADC1: none, I[1], I[2], I[3] . . .
ADC2: Q[1], Q[2], Q[3], Q[4] . . .
This leads to an erroneous phase difference between I and Q, which is no longer 90 degrees, thus the mirror rejection cannot work any more.
How can we detect this arbitrarily occuring hardware bug?
-
look at the spectrum display!!! This is the fastest and most reliable way OR
-
Just use the output of the I & Q correction algorithm explained above and calculate the phase shift error between I and Q (the deviation of the phase difference between I and Q from the desired 90 degrees):
phase error = arcsin (teta1 / teta3)
If this phase error is larger than one or two degrees, you have a severe hardware problem OR the codec needs to be restarted!
Now we have to smooth this in order to give a reliable indication of the occurence / non-occurence of the twinpeak syndrome. If we have detected it, we just restart the codec and hope that the phase error is gone!
However, if you have no antenna connected, or if you disabled "auto-IQ correction" in the menu, or if your TRX has problems with its power supply, or if you have mods that influence the quick startup, then the detection routine does not work reliably and gives an indication of "failed" --> meaning the detection of twinpeaks . . .
In our experience, this is in 99% of the cases NOT a real twinpeak issue, but an indication of something else.
So, if you see "failed" in the menu, do the following:
-
read the Mosely & Slump (2006) paper
-
try to understand what I & Q are, how they work to suppress the mirror frequencies
-
try to understand how the manual IQ correction works
-
try to understand how the automatic IQ correction work
-
make sure you have the automatic IQ correction activated
-
try to understand what a "twinpeak" is
-
be really sure that you have no twinpeak --> refer to the first part of this page for this purpose
--> Well done!
If you are interested in how we implemented this, the C code for this automatic IQ correction can be found in audio_driver.c in the UHSDR firmware github.