85 lines
3.1 KiB
Matlab
85 lines
3.1 KiB
Matlab
classdef MLSE_test < IMDDTestCase
|
|
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'mlse'})
|
|
function constructorStoresConfiguration(testCase)
|
|
mlse = MLSE( ...
|
|
"M", 4, ...
|
|
"DIR", [1 0.35], ...
|
|
"trellis_states", [-3 -1 1 3], ...
|
|
"duobinary_output", false, ...
|
|
"trellis_state_mode", 2, ...
|
|
"trellis_exclusion", 0, ...
|
|
"scale_mode", 0, ...
|
|
"debug", 0);
|
|
|
|
testCase.verifyEqual(mlse.M, 4);
|
|
testCase.verifyEqual(mlse.DIR, [1 0.35]);
|
|
testCase.verifyEqual(mlse.trellis_states, [-3 -1 1 3]);
|
|
testCase.verifyFalse(mlse.duobinary_output);
|
|
testCase.verifyEqual(mlse.trellis_state_mode, 2);
|
|
testCase.verifyEqual(mlse.trellis_exclusion, 0);
|
|
testCase.verifyEqual(mlse.scale_mode, 0);
|
|
testCase.verifyEqual(mlse.debug, 0);
|
|
end
|
|
|
|
function processRecoversKnownPAM4Sequence(testCase)
|
|
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
|
|
|
|
txSignal = Informationsignal(txSymbols, "fs", 1);
|
|
rxSignal = Signal(rxSymbols, "fs", 1);
|
|
|
|
hdSignal = mlse.process(rxSignal, txSignal);
|
|
rxBits = PAMmapper(4, 0).demap(hdSignal);
|
|
|
|
testCase.verifyClass(hdSignal, "Signal");
|
|
testCase.verifyEqual(hdSignal.fs, rxSignal.fs);
|
|
testCase.verifyEqual(rxBits.signal, txBits, ...
|
|
"MLSE should recover the transmitted PAM-4 bits on the deterministic fixture.");
|
|
end
|
|
|
|
function processReturnsExpectedShapesAndFiniteMetric(testCase)
|
|
[txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture();
|
|
|
|
[viterbiSymbols, llr, gmi] = mlse.process_(rxSymbols, txSymbols);
|
|
rxBits = PAMmapper(4, 0).demap(viterbiSymbols(:));
|
|
expectedSymbols = txSymbols(:) ./ rms(txSymbols(:));
|
|
|
|
testCase.verifyEqual(numel(viterbiSymbols), numel(rxSymbols));
|
|
testCase.verifyEqual(size(llr), [numel(rxSymbols), 2]);
|
|
testCase.verifyTrue(isfinite(gmi));
|
|
testCase.verifyEqual(viterbiSymbols(:), expectedSymbols, "AbsTol", 1e-12);
|
|
testCase.verifyEqual(rxBits, txBits, ...
|
|
"Lower-level MLSE output should decode the same deterministic fixture.");
|
|
end
|
|
end
|
|
end
|
|
|
|
function [txBits, txSymbols, rxSymbols, mlse] = makePam4Fixture()
|
|
txBits = [ ...
|
|
0 0; ...
|
|
0 1; ...
|
|
1 1; ...
|
|
1 0; ...
|
|
0 1; ...
|
|
1 0; ...
|
|
0 0; ...
|
|
1 1];
|
|
|
|
mapper = PAMmapper(4, 0);
|
|
txSignal = Informationsignal(txBits);
|
|
txSymbols = mapper.map(txSignal).signal;
|
|
|
|
channel = [1 0.35];
|
|
rxSymbols = filter(channel, 1, txSymbols);
|
|
rxSymbols = rxSymbols + 0.01 * [0; 1; -1; 2; -2; 1; -1; 0];
|
|
|
|
mlse = MLSE( ...
|
|
"M", 4, ...
|
|
"DIR", channel, ...
|
|
"trellis_states", mapper.levels, ...
|
|
"duobinary_output", false, ...
|
|
"trellis_state_mode", 2, ...
|
|
"trellis_exclusion", 0, ...
|
|
"scale_mode", 0, ...
|
|
"debug", 0);
|
|
end
|