[ Edit: the CMA code seems to work after all, the problem is likely elsewhere (timing recovery), see added text at the end. ]

Yesterday I implemented some CMA code for polarization demultiplexing which does not seem to work, 2 possible outcomes:

  1. I made an error in the code and are completely blind to see what it is (spent hours looking into this...).
  2. I have a misunderstanding of what the algorithm can do and what it cannot do.

The input of the CMA code is 2 noisy sequences of QPSK symbols, and I added some mutal crosscoupling to mimic the polarization issue. Below: input left, output right. The effect is close to nothing.

input and output


%     Digital Coherent Optical Receivers: Algorithms and Subsystems
%     Seb J. Savory

% Convergence parameter.

mu = 1e-3;

% Filters. N must be odd.

N            = 5;
hxx          = zeros(N, 1);
hyy          = zeros(N, 1);
hxy          = zeros(N, 1);
hyx          = zeros(N, 1);                
hxx((N+1)/2) = 1;
hyy((N+1)/2) = 1;

% Offset indices for each input sample as input for the filter.

input_offset_indices = ((-N+1):0)';

% Loop.

xi      = zeros(N, 1);
yi      = zeros(N, 1);
i_start = N;
i_end   = numel(parms.x);
for i = i_start:i_end

    % Get the input vectors for the filters.

    xi(:) = parms.x(i + input_offset_indices);
    yi(:) = parms.y(i + input_offset_indices);

    % Filter output. Eq. 16, Savory.

    xo(i) = hxx' * xi + hxy' * yi;
    yo(i) = hyy' * yi + hyx' * xi;

    % Calculate errors. Above Eq. 37, Savory.

    eps_x = 1 - abs(xo(i))^2;
    eps_y = 1 - abs(yo(i))^2;

    % Update filters. Eq. 39, Savory.

    hxx = hxx + eps_x * mu * xi * conj(xo(i));
    hxy = hxy + eps_x * mu * yi * conj(xo(i));            
    hyy = hyy + eps_y * mu * yi * conj(yo(i));
    hyx = hyx + eps_y * mu * xi * conj(yo(i));

My implementation seems to be the same as the (real-valued) answer here:

MATLAB : Proper estimation of weights and how to calculate MSE for QPSK signal for Constant Modulus Algorithm

Small part from the article with relevant information I used:


Anyone sees an error in the code or has some clarification? Highly appreciated!

Edit, addition: The problem seems to be elsewhere:

  1. If I change the simulation such that the receiver timing recovery (TR) essentially has nothing to do (by aligning Tx and Rx oversampling ratios at forehand...), the CMA code then works nicely although the TR introduces quite some noise. The CMA is then also resilient against frequency offsets (expected, modulus of the signal does not change with rotations).
  2. If the Tx oversampling ratio is a bit different from the Rx and the TR has to make some corrections, I see the same constellation at the TR_output=CMA_input as in case 1 above, but now CMA fails to do anything even without any frequency offset.

So the question seems to shift to what happens in the TR that makes the CMA fail...

  • $\begingroup$ My first debug attempt would be removing the noise and setting N=1. (I assume the cross-coupling you simulate is memoryless). $\endgroup$
    – Vito
    Commented Dec 18, 2022 at 6:54
  • $\begingroup$ @Vito I changed some things which gives me some more insight in the problem, see the added text in the original post. $\endgroup$ Commented Dec 18, 2022 at 8:19
  • $\begingroup$ In the end are you getting constant vectors for hxx, hxy, hyx and hyy? $\endgroup$
    – Bob
    Commented Dec 18, 2022 at 12:33
  • $\begingroup$ @Bob Yes, the filters converge and the CMA seems to work. Please see the addition at the end of my orignal post: the problem seems to be elsewhere. $\endgroup$ Commented Dec 18, 2022 at 14:33
  • $\begingroup$ So why you post the code for the CMA? What I was wondering is why you make N copies of each sample to compute the filter... In my understanding that might give you the correct result but it does N times more arithmetic operations than necessary. $\endgroup$
    – Bob
    Commented Dec 18, 2022 at 15:58

1 Answer 1


The adaption of the CMA equalizer somehow conflicts with the convergence of the timing recovery loop. (Note that the equalizer intrinsically performs some fractional interpolation.)

You may find this reference useful.

Another potential solution could be to switch on the equalizer only after you are reasonably certain that the timing recovery has been achieved. That might or might not work depending on your several factors in your scenario (e.g. which algorithm you use for timing recovery, your loop bandwidth, whether the streams transmitted on the two polarizations are synchronous or not).

  • 1
    $\begingroup$ Resetting the CMA equalizer after timing recovery locks (I take Tlock=5/Loop_bandwidth for that to be on the safe side...) seems to work in my simulation. I will also look into the combined timing recovery / CMA in the paper you mentioned. Thanks for your input. $\endgroup$ Commented Dec 20, 2022 at 10:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.