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