classdef Duobinary %Duobinary Coding % should work properties(Access=public) end methods (Access=public) function obj = Duobinary() %NAME Construct an instance of this class end function signal = precode(~,signal) if isa(signal,'Signal') data = signal.signal; else data = signal; end 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 for k = 2:numel(data) bk(k) = mod(data(k)-bk(k-1),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 assert(isequal(unique(bk),u),'Check Duobinary Precoding'); %seems the signal is not the same as before if isa(signal,'Signal') signal.signal = bk; else signal = bk; end end function signal = encode(~,signal) arguments ~ signal end if isa(signal,'Signal') data = signal.signal; else data = signal; end data = data./rms(data); 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"); coeff = [1,1]; data = filter(coeff, 1, data); %data = data ./ rms(data); % data = ifft(fft(real(data)).*fft(fliplr(coeff'),length(data))) + 1i*ifft(fft(imag(data)).*fft(fliplr(coeff'),length(data))); %make bipolar data = (data-round(mean(data),1)); [unique_points, ~, idx] = unique(data); counts = accumarray(idx, 1); total_samples = numel(data); probabilities = counts / total_samples; mean_power = sum((unique_points .^ 2) .* probabilities); scaling_factor = sqrt(mean_power); 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. else errormsg("Error in: Duobinary encode > scale unipolar to bipolar > The data is not PAM4, PAM6 or PAM 8? ") end if isa(signal,'Signal') signal.signal = data; else signal = data; end % 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 data = data .* sqrt(5.8); elseif I == 15 data = data .* sqrt(10.5); 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); else errormsg("Error in: Duobinary decode > scale unipolar to bipolar > The data is not PAM4, PAM6 or PAM 8? ") 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