[ 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:
- I made an error in the code and are completely blind to see what it is (spent hours looking into this...).
- 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.
% Digital Coherent Optical Receivers: Algorithms and Subsystems % Seb J. Savory % IEEE JOURNAL OF SELECTED TOPICS IN QUANTUM ELECTRONICS, VOL. 16, NO. 5, SEPTEMBER/OCTOBER 2010 % 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)); end
My implementation seems to be the same as the (real-valued) answer here:
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:
- 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).
- 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...