Compensating I/Q imbalance in radio receivers

Previously …

In the previous article, how to measure of I/Q imbalance was discussed. In this article we will show how to do actual compensation.

Compensation of I/Q imbalance

When the imbalance parameters $/phi$ (in radians) and $g$ are known, the compensator coefficients $c_1$ and $c_2$ are simply:

$$ c_1 = g \cdot \sin(\phi) $$ $$ c_2 = g \cdot \cos(\phi) $$

These coefficients need only be calculated once, as long as the imbalance parameters do not change.

The compensator itself, which is applied to every incoming I/Q sample, is quite simple: $$ I_c = c_2 \cdot I $$ $$ Q_c = Q + c_1 \cdot I $$ where $I_c$ and $Q_c$ are the compensated I and Q signals.

Directly obtaining $c_1$ and $c_2$

When the imbalance parameters $/phi$ (in radians) and $g$ are not known, which is almost always the case, calculating $c_1$ and $c_2$ isn’t possible and some other technique must be found. Luckily the smoothed accumulator values saccu1, saccu2 and saccu3 from the previous article can be used to estimate $c_1$ and $c_2$.

The equations needed are:

$$ c_1 = -\dfrac{\text{saccu}_1}{\text{saccu}_2} $$ $$ c_2 = \sqrt{\dfrac{\text{saccu}_3}{\text{saccu}_2}} $$

Code

The following should be added to the calc_iq_imbalance() routine from the previous article:

    // protection for division by zero
    if (saccu_2 > 0.0)
    {
        c1 = -saccu1/saccu_2
        c2 = fsqrt(saccu3/saccu_2)
    }

Note: the code to calculate g and phi estimates in calc_iq_imbalance() are no longer needed, except for reporting purposes.

The following compensator needs to be added after the I/Q estimation code:

    Ic = c2*I
    Qc = Q + c1*I

Initialise c1 to 0 and c2 to 1 at the start of the program.

References

The method implemented is described more throughly in A Low-complexity Feed-forward I/Q Imbalance Compensation Algorithm