New MPI mitigation schemes // Duobinary // Start of FTN schemes
This commit is contained in:
245
Classes/04_DSP/Coding/Duobinary.m
Normal file
245
Classes/04_DSP/Coding/Duobinary.m
Normal 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
|
||||
269
Classes/04_DSP/Coding/MRDS_coding.m
Normal file
269
Classes/04_DSP/Coding/MRDS_coding.m
Normal 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
|
||||
Reference in New Issue
Block a user