301 lines
8.2 KiB
Matlab
301 lines
8.2 KiB
Matlab
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 == 2
|
|
data = data;
|
|
elseif 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 == 2
|
|
bk = bk;
|
|
elseif 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,options)
|
|
|
|
arguments
|
|
~
|
|
signal
|
|
options.M = [];
|
|
end
|
|
|
|
if isa(signal,'Signal')
|
|
data = signal.signal;
|
|
else
|
|
data = signal;
|
|
end
|
|
|
|
data = data./rms(data);
|
|
|
|
if isempty(options.M)
|
|
u = unique(data);
|
|
options.M = numel(u);
|
|
end
|
|
|
|
%make unipolar
|
|
if options.M == 2
|
|
data = data;
|
|
elseif options.M == 4
|
|
data = data .* sqrt(5);
|
|
elseif options.M == 6
|
|
data = data .* sqrt(10);
|
|
elseif options.M == 8
|
|
data = data .* sqrt(21);
|
|
elseif options.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:options.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 options.M == 2
|
|
data = data ./ sqrt(0.5);
|
|
elseif options.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 options.M == 6
|
|
data = data ./ sqrt(5.8);
|
|
elseif options.M == 8
|
|
data = data ./ sqrt(10.5); % 15-level constellation weighted with probability after DB code i.e.
|
|
else
|
|
error("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,options)
|
|
|
|
arguments
|
|
~
|
|
signalclass
|
|
options.M = [];
|
|
end
|
|
|
|
data = signalclass.signal;
|
|
u = unique(data);
|
|
I = numel(u); %number of duobinary coded const. points
|
|
if isempty(options.M)
|
|
M = (I+1)/2; %PAM-M order
|
|
else
|
|
M = options.M; %PAM-M order
|
|
end
|
|
|
|
%make unipolar
|
|
if I == 3
|
|
data = data .* 0.5;
|
|
elseif I == 7 || I == 6
|
|
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 == 2
|
|
data = data;
|
|
elseif 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
|