New MPI mitigation schemes // Duobinary // Start of FTN schemes

This commit is contained in:
Silas Oettinghaus
2024-09-06 08:10:04 +02:00
parent bb228ae2bd
commit 03bfd70470
30 changed files with 1598 additions and 560 deletions

View File

@@ -0,0 +1,245 @@
classdef Duobinary
%Duobinary Coding
% should work
properties(Access=public)
end
methods (Access=public)
function obj = Duobinary()
%NAME Construct an instance of this class
% Detailed explanation goes here
arguments
end
% %
% fn = fieldnames(options);
% for n = 1:numel(fn)
% try
% obj.(fn{n}) = options.(fn{n});
% end
% end
% do more stuff
end
function signalclass = precode(~,signalclass)
data = signalclass.signal;
u = unique(data);
M = numel(u);
%make unipolar
if M == 4
data = data .* sqrt(5);
elseif M == 6
data = data .* sqrt(10);
elseif M == 8
data = data .* sqrt(21);
elseif M == 16
data = data .* sqrt(85);
warning('Check if PAM16 implementation, mapping and scaling is correct!')
end
data = round(data);
b = min(data);
data = data - b;
data = data ./ 2;
assert(isequal((0:M-1)',unique(data)),'Check Duobinary Precoding'); %seems the signal is not unipolar
% Pre coding
bk = zeros(numel(data),1);
for k = 1:numel(data)-1
bk(k+1) =mod(data(k)-bk(k),M);
end
%make bipolar
bk = bk .* 2;
bk = bk + b;
if M == 4
bk = bk ./ sqrt(5);
elseif M == 6
bk = bk ./ sqrt(10);
elseif M == 8
bk = bk ./ sqrt(21);
end
signalclass.signal = bk;
assert(isequal(unique(signalclass.signal),u),'Check Duobinary Precoding'); %seems the signal is not the same as before
end
function signalclass = encode(~,signalclass)
data = signalclass.signal;
u = unique(data);
M = numel(u);
%make unipolar
if M == 4
data = data .* sqrt(5);
elseif M == 6
data = data .* sqrt(10);
elseif M == 8
data = data .* sqrt(21);
elseif M == 16
data = data .* sqrt(85);
warning('Check if PAM16 implementation, mapping and scaling is correct!')
end
data = round(data);
b = min(data);
data = data - b;
data = data ./ 2;
assert(isequal((0:M-1)',unique(data)),'Check Duobinary Precoding'); %seems the signal is not unipolar
% duobinary coding (1+D)
coeff = [1,1];
data = conv(data,coeff,"same");
%make bipolar
data = (data-round(mean(data),1));
if M == 4
data = data ./ sqrt(2.5); % 7-level constellation weighted with probability after DB code i.e. mean([-3 3 -2 -2 2 2 -1 -1 -1 1 1 1 0 0 0 0].^2) = 2.5 --> sqrt(2.5) == rms(constellation)
elseif M == 6
data = data ./ sqrt(5.8);
elseif M == 8
data = data ./ sqrt(10.5); % 15-level constellation weighted with probability after DB code i.e.
end
signalclass.signal = data;
% Code to evaluate the s in sqrt(s):
% M=6;
% c = (0:(2*M)-2) - ((2*M)-2)/2;
% s = 0;
% for i = 0:(2*M)-2
% p(i+1) = M-abs(i-(M-1));
% s = s+p(i+1)*c(i+1).^2;
% end
% s = s/M^2;
end
function signalclass = decode(~,signalclass)
data = signalclass.signal;
u = unique(data);
I = numel(u); %number of duobinary coded const. points
M = (I+1)/2; %PAM-M order
%make unipolar
if I == 7
data = data .* sqrt(2.5);
elseif I == 11
%todo
data = data .* sqrt(5.8);
warning('Check if PAM16 implementation, mapping and scaling is correct!')
elseif I == 15
data = data .* sqrt(10.5);
elseif I == 16
warning('Check if PAM16 implementation, mapping and scaling is correct!')
end
data = round(data);
b = min(data);
data = data - b;
data = round(data);
data = mod(data,M);
%make bipolar
data = data .* 2;
data = data - round(mean(data));
if M == 4
data = data ./ sqrt(5);
elseif M == 6
data = data ./ sqrt(10);
elseif M == 8
data = data ./ sqrt(21);
end
signalclass.signal = data;
end
function signalclass = feedbackdetector(~,signalclass)
data = signalclass.signal;
u = unique(data);
I = numel(u); %number of duobinary coded const. points
M = (I+1)/2; %PAM-M order
%make unipolar
if I == 7
data = data .* sqrt(2.5);
elseif I == 11
%todo
data = data .* sqrt(5.8);
warning('Check if PAM16 implementation, mapping and scaling is correct!')
elseif I == 15
data = data .* sqrt(10.5);
elseif I == 16
warning('Check if PAM16 implementation, mapping and scaling is correct!')
end
data = round(data);
b = min(data);
data = data - b;
data = round(data);
data_out = zeros(length(data),1);
const = 0:M-1;
%%FALSCH!
for k = 1:length(data)-1
d_ = data(k+1) - data_out(k);
[~,b] = min(abs(d_-[0:M-1]));
data_out(k+1) = const(b);
end
%make bipolar
data_out = data_out .* 2;
data_out = data_out - round(mean(data_out));
if M == 4
data_out = data_out ./ sqrt(5);
elseif M == 6
data_out = data_out ./ sqrt(10);
elseif M == 8
data_out = data_out ./ sqrt(21);
end
signalclass.signal = data_out;
end
end
methods (Access=private)
% Cant be seen from outside! So put all your functions here that can/
% shall not be called from outside
end
end

View File

@@ -0,0 +1,269 @@
classdef MRDS_coding
%MRDS implementation according to:
% Optical Multi-Path Interference Mitigation for PAM4-IMDD Systems Using Balanced Coding
% Journal of Lightwave Technology; 2024
properties(Access=public)
blocklength
delta
end
methods (Access=public)
function obj = MRDS_coding(options)
%NAME Construct an instance of this class
% Detailed explanation goes here
arguments
options.blocklength = 8;
end
%
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
end
function process(~)
error("MRDS_coding has no process function. Use .encode(signal) and .dc_remove(signal) and .decode(signal)");
end
function signalclass_out = encode(obj,signalclass_in)
data_in = signalclass_in.signal';
if mean(unique(data_in)) < 0.01 % --> check for bipolar
data_in = int32(data_in.*sqrt(5));
data_in = double(data_in);
else % unipolar
data_in = int32(data_in.*sqrt(5)*2-3); % make bipolar [-3, -1, 1, 3]
data_in = double(data_in);
end
data_out = obj.mrds_encoding(data_in, obj.blocklength);
data_out = data_out./sqrt(5); % normalized to Power=1
signalclass_in.signal = data_out';
% append to logbook
lbdesc = ['MRDS Coded'];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function signalclass_out = decode(obj,signalclass_in)
data_in = signalclass_in.signal';
if mean(unique(data_in)) < 0.01 % --> check for bipolar
data_in = int32(data_in.*sqrt(5));
data_in = double(data_in);
else % unipolar
data_in = int32(data_in.*sqrt(5)*2-3); % make bipolar [-3, -1, 1, 3]
data_in = double(data_in);
end
data_oh = obj.oh_decider(data_in, obj.blocklength); % decider for overhead
data_out = obj.mrds_decoding(data_oh, obj.blocklength);
data_out = data_out./sqrt(5); % normalized to Power=1
signalclass_in.signal = data_out';
% append to logbook
lbdesc = ['MRDS Coded'];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function signalclass_out = dc_remove(obj,signalclass_in,options)
arguments
obj
signalclass_in
options.oversampling_factor = 1;
end
signalclass_in.signal = obj.dcr(signalclass_in.signal, obj.blocklength, options.oversampling_factor);
% append to logbook
lbdesc = ['MRDS DC Removed'];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
end
methods (Access=private)
% Cant be seen from outside! So put all your functions here that can/
% shall not be called from outside
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function 1 - encoding
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [data_out] = mrds_encoding(~,data_in, blocklength)
% data_in: bipolar PAM4 sequence with levels [-3, -1, 1, 3]
% with length power of two
% blocklength: power of two <= length of data_in
oh_length = log2(blocklength);
data_out = zeros(1,length(data_in)+length(data_in)/blocklength*oh_length);
l = 0;
for j = 1:blocklength:length(data_in)
data = data_in(j:j+blocklength-1);
z_N = zeros(1,blocklength); % RDS
z_rds = 0;
for i = 1:blocklength
z_rds = z_rds + data(i);
z_N(i) = z_rds;
end
z = z_rds/2; % find inversion point k
k = find(z_N == z);
[~, index] = min(abs(blocklength/2 - k));
k = k(index);
if isempty(k) == 1
k = blocklength;
end
if k == blocklength
overhead = ones(1,oh_length)*3;
else
overhead = (decimalToBinaryVector(k-1,log2(blocklength))-0.5)*6; % calculate OH
data(k+1:end) = data(k+1:end)*(-1); % invert
end
data_oh = [data overhead];
data_out(l*(blocklength+oh_length)+1:(l+1)*(blocklength+oh_length)) = data_oh;
l = l+1;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function 2 - decoding
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [data_out] = mrds_decoding(~,data_in, blocklength)
oh_length = log2(blocklength);
data_out = zeros(1,length(data_in)-length(data_in)/(blocklength+oh_length)*oh_length);
l = 1;
for j = 1:(blocklength+oh_length):length(data_in)
data = data_in(j:j+blocklength+oh_length-1);
overhead = data(blocklength+1:end)/6+0.5;
k = binaryVectorToDecimal(overhead)+1;
if k == blocklength
data = data(1:blocklength);
else
data = data(1:blocklength);
data(k+1:end) = data(k+1:end)*(-1); % invert
end
data_out(l:l+blocklength-1) = data;
l = l+blocklength;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function 3 - decider for overhead values
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [data_out] = oh_decider(~,data_in, blocklength)
oh_length = log2(blocklength);
threshold = 0;
data_out = data_in;
for j = 1:length(data_in)/(blocklength+oh_length)
for k = 1:oh_length
if data_in(j*blocklength+(j-1)*oh_length+k) >= threshold
data_out(j*blocklength+(j-1)*oh_length+k) = 3;
else
data_out(j*blocklength+(j-1)*oh_length+k) = -3;
end
end
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Function 4 - matched DC removal (DCR)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [data_out] = dcr(~,data_in, blocklength, oversampling_factor)
oh_length = log2(blocklength);
winlength = blocklength+oh_length;
if oversampling_factor > 1
winlength = winlength*oversampling_factor;
end
for j = 1:winlength:length(data_in)
try
data = data_in(j:j+winlength-1);
rmean = mean(data);
data_out(j:j+winlength-1) = data - rmean;
catch
if j+winlength > length(data_in)
data = data_in(j:length(data_in));
else
error('indice problem.')
end
rmean = mean(data);
data_out(j:length(data_in)) = data - rmean;
end
end
data_out = data_out';
end
end
end