106 lines
4.0 KiB
Matlab
106 lines
4.0 KiB
Matlab
classdef ML_MLSE_DUOBINARY_test < IMDDTestCase
|
|
methods (Test, TestTags = {'unit', 'fast', 'dsp', 'ml_mlse', 'duobinary'})
|
|
function constructorStoresDuobinaryConfiguration(testCase)
|
|
eq = ML_MLSE_DUOBINARY();
|
|
|
|
testCase.verifyEqual(class(eq), 'ML_MLSE_DUOBINARY');
|
|
testCase.verifyEqual(eq.sps, 2);
|
|
testCase.verifyEqual(eq.order, 15);
|
|
testCase.verifyEqual(eq.ber, []);
|
|
testCase.verifyEqual(eq.ber_dd, []);
|
|
end
|
|
|
|
function processReturnsPrecodeDomainAndFiniteDiagnostics(testCase)
|
|
[~, ~, txPrecoded, txEncoded] = makePam4Fixture(512);
|
|
|
|
eq = ML_MLSE_DUOBINARY( ...
|
|
"sps", 1, ...
|
|
"order", 1, ...
|
|
"len_tr", length(txEncoded), ...
|
|
"epochs_tr", 1, ...
|
|
"epochs_dd", 1, ...
|
|
"mu_tr", 0.01, ...
|
|
"mu_dd", 0.01, ...
|
|
"adaptive_mu", false, ...
|
|
"L", 1);
|
|
|
|
[detected, detectedViterbi] = eq.process(txEncoded, txPrecoded);
|
|
|
|
testCase.verifyEqual(length(detected), length(txEncoded));
|
|
testCase.verifyEqual(length(detectedViterbi), length(txEncoded));
|
|
testCase.verifyTrue(all(ismembertol(detected.signal, unique(txPrecoded.signal), 1e-12)));
|
|
testCase.verifySize(eq.ber, [1 1]);
|
|
testCase.verifySize(eq.ber_dd, [1 1]);
|
|
testCase.verifyTrue(isfinite(eq.ber(1)));
|
|
testCase.verifyTrue(isfinite(eq.ber_dd(1)));
|
|
|
|
end
|
|
|
|
function encodeDecodeInvertsPrecodingAwayFromInitialState(testCase)
|
|
[~, txSymbols, txPrecoded, ~] = makePam4Fixture(512);
|
|
|
|
encoded = Duobinary().encode(txPrecoded, "M", 4);
|
|
decoded = Duobinary().decode(encoded, "M", 4);
|
|
|
|
testCase.verifyEqual(decoded.signal(11:end-10), ...
|
|
txSymbols.signal(11:end-10), "AbsTol", 1e-12);
|
|
end
|
|
|
|
function intermediateTrainingEpochsKeepWeightsWithoutTracebackBer(testCase)
|
|
[~, ~, txPrecoded, txEncoded] = makePam4Fixture(512);
|
|
|
|
eq = ML_MLSE_DUOBINARY( ...
|
|
"sps", 1, ...
|
|
"order", 1, ...
|
|
"len_tr", length(txEncoded), ...
|
|
"epochs_tr", 2, ...
|
|
"epochs_dd", 1, ...
|
|
"mu_tr", 0.01, ...
|
|
"mu_dd", 0.01, ...
|
|
"adaptive_mu", false, ...
|
|
"L", 1);
|
|
|
|
eq.process(txEncoded, txPrecoded);
|
|
|
|
testCase.verifyTrue(isnan(eq.ber(1)));
|
|
testCase.verifyTrue(isfinite(eq.ber(2)));
|
|
testCase.verifyTrue(all(isfinite(eq.ce)));
|
|
end
|
|
|
|
function resultWrapperReportsBothPrecodedAndOriginalBer(testCase)
|
|
[txBits, ~, txPrecoded, txEncoded] = makePam4Fixture(32000);
|
|
|
|
eq = ML_MLSE_DUOBINARY( ...
|
|
"sps", 1, ...
|
|
"order", 1, ...
|
|
"len_tr", length(txEncoded), ...
|
|
"epochs_tr", 1, ...
|
|
"epochs_dd", 1, ...
|
|
"mu_tr", 0.01, ...
|
|
"mu_dd", 0.01, ...
|
|
"adaptive_mu", false, ...
|
|
"L", 1);
|
|
|
|
results = ml_mlse(eq, 4, txEncoded, txPrecoded, txBits, ...
|
|
"precode_mode", db_mode.db_precoded);
|
|
|
|
testCase.verifyTrue(isfinite(results.metrics.BER));
|
|
testCase.verifyTrue(isfinite(results.metrics.BER_precoded));
|
|
testCase.verifyGreaterThanOrEqual(results.metrics.numBits, 0);
|
|
testCase.verifyGreaterThanOrEqual(results.metrics.numBitErr, 0);
|
|
testCase.verifyGreaterThanOrEqual(results.metrics.numBitErr_precoded, 0);
|
|
end
|
|
end
|
|
end
|
|
|
|
function [txBits, txSymbols, txPrecoded, txEncoded] = makePam4Fixture(nSymbols)
|
|
pattern = [0 0; 0 1; 1 1; 1 0];
|
|
bits = repmat(pattern, ceil(nSymbols / size(pattern, 1)), 1);
|
|
bits = bits(1:nSymbols, :);
|
|
|
|
txBits = Informationsignal(bits);
|
|
txSymbols = PAMmapper(4, 0).map(txBits);
|
|
txPrecoded = Duobinary().precode(txSymbols);
|
|
txEncoded = Duobinary().encode(txPrecoded, "M", 4);
|
|
end
|