DB and 400G and minor changes

This commit is contained in:
Silas Oettinghaus
2024-10-07 08:22:28 +02:00
parent 179a7f9682
commit da3be973e2
20 changed files with 578 additions and 142 deletions

View File

@@ -192,6 +192,19 @@ classdef Signal
end
%% Add signals from one signal to another, the first object will sustain
function Difference = minus(X,y)
if isa(y,'Signal')
Difference = X;
Difference.signal = X.signal - y.signal;
elseif isnumeric(y)
Difference = X;
Difference.signal = X.signal - y;
end
end
function Product = times(X,y)
if isa(y,'Signal')
@@ -271,14 +284,22 @@ classdef Signal
N = 2^(nextpow2(length(obj.signal))-8);
[p_lin,w] = pwelch(obj.signal,hanning(N),N/2,N,obj.fs,"centered","power","mean");
p_dbm = 10*log10(p_lin)+30; %dB to dBm in case of "power"
normalize = 1;
if normalize
p_lin = p_lin./ max(p_lin);
p_dbm = 10*log10(p_lin); %dB to dBm in case of "power"
ylab = "normalized to 0 dB";
else
p_dbm = 10*log10(p_lin)+30; %dB to dBm in case of "power"
ylab = "Power (dBm)";
end
figure(options.fignum); % If figure does not exist, create new figure
hold on
plot(w.*1e-9,p_dbm,'DisplayName',options.displayname,'LineWidth',1);
xlabel("Frequency in GHz");
%ylabel("Power/frequency (dB/Hz)");
ylabel("Power (dBm)");
ylabel(ylab);
xlim([-obj.fs/2 obj.fs/2].*1e-9)
edgetick = 2^(nextpow2(obj.fs*1e-9));
% xticks([-edgetick:16:edgetick]);
@@ -362,7 +383,7 @@ classdef Signal
end
%%
%% Normalize
function obj = normalize(obj,options)
arguments
@@ -381,7 +402,7 @@ classdef Signal
end
%%
%% Delay
function [obj] = delay(obj,delay,options)
arguments
@@ -402,7 +423,7 @@ classdef Signal
end
%%
%% Synchronize with reference
function [obj,D,cuts] = tsynch(obj,options)
% time sync and cut
arguments
@@ -446,6 +467,10 @@ classdef Signal
end
function obj = filter(obj,a,b)
obj.signal = filter(a,b,obj.signal);
end
function er = extinctionratio(obj,fsym,M)
histpoints = 1024; %% verticale resolution
histpoints = floor(histpoints/2)*2+1; %% to have the eye digram centered around one point make the vertical resolution uneven

View File

@@ -184,12 +184,12 @@ classdef ChannelFreqResp < handle
% it could be helpful to clip at linear 1 (=to keep comp from attenuating the signal)
% iH(abs(iH)<1) = 1.*exp(1j*angle(iH(abs(iH)<1)));
if 0
figure(7);hold on;plot(fnew,20*log10(abs(iH)))
end
% iH(1) is DC ---> iH(end) is High Freq.
% iH(1) is DC ---> iH(end) is High Freq.
H_inv = [iH(1) iH fliplr(conj(iH)) conj(iH(1))];
H_inv = [iH(1) iH iH(end) fliplr(conj(iH)) conj(iH(1))];

View File

@@ -10,6 +10,7 @@ classdef PAMsource
randkey
db_precode
db_encode
mrds_code
mrds_blocklength
@@ -36,6 +37,7 @@ classdef PAMsource
options.randkey = 0;
options.db_precode = 0;
options.db_encode = 0;
options.mrds_code = 0;
options.mrds_blocklength = 512;
@@ -95,10 +97,16 @@ classdef PAMsource
symbols = PAMmapper(obj.M,0).map(bits);
symbols.fs = obj.fsym;
%%%%%% Duobinary %%%%%%%%%%%
if obj.db_precode
symbols = Duobinary().precode(symbols);
end
if obj.db_encode
symbols = Duobinary().encode(symbols);
end
% figure(12);hold on;histogram(symbols.signal,'Normalization','probability');
if obj.mrds_code
symbols = MRDS_coding("blocklength",obj.mrds_blocklength).encode(symbols);

View File

@@ -47,10 +47,14 @@ classdef Duobinary
% 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 = 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;
@@ -107,9 +111,16 @@ classdef Duobinary
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 = conv(data,coeff,"same");
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));

View File

@@ -51,7 +51,7 @@ classdef FFE < handle
end
function [X] = process(obj, X, D)
function [X,Noi] = process(obj, X, D)
% actual processing of the signal (steps 1. - 3.)
% 1 normalize RMS
@@ -65,10 +65,10 @@ classdef FFE < handle
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
% Decision Directed Mode
N = X.length;
n = X.length;
training = 0;
showviz = 0;
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,N,training,showviz);
[signal,decision]=obj.equalize(X.signal, D.signal,obj.mu_dd,obj.epochs_dd,n,training,showviz);
% Output Signal
if obj.decide
@@ -76,9 +76,13 @@ classdef FFE < handle
else
X.signal = signal;
end
X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym
lbdesc = [num2str(obj.order),' tap FFE'];
X = X.logbookentry(lbdesc); % append to logbook
Noi = X;
Noi = X - D;
end

View File

@@ -54,10 +54,12 @@ classdef MLSE
obj.DIR(1:DIR_nonzero(1)-1) = [];
end
if length(obj.DIR) == 1
if isscalar(obj.DIR)
obj.DIR = [0 obj.DIR];
end
obj.DIR = flip(obj.DIR);
% RMS normalization of input data
data_in = data_in ./ rms(data_in);
@@ -95,10 +97,65 @@ classdef MLSE
% i.e. match the rms values of data_in to noise_free_received
if isreal(data_in)
if obj.M == round(obj.M)
data_in = data_in * rms(noise_free_received,'all','omitnan');
data_in = data_in * rms(noise_free_received(noise_free_received ~= inf),'all','omitnan');
end
end
%
% %% Optimized
% % Preallocate and initialize variables
% data_out = NaN(size(data_in)); % output vector
% sum_path_metrics_res = zeros(length(states), length(data_in));
% path_idx = zeros(length(states), length(data_in));
%
% % Precompute repmat size
% num_states = length(states);
% num_signals = numel(noise_free_received);
%
% % First trellis path (initialize)
% sum_path_metrics = zeros(num_states, num_states);
% path_metrics = (abs(data_in(1) - noise_free_received)).^2; % Use broadcasting instead of repmat
% sum_path_metrics = sum_path_metrics + path_metrics; % Compute initial path metrics
%
% [sum_path_metrics_res(:,1), path_idx(:,1)] = min(sum_path_metrics, [], 2); % Best path for first step
%
% % Preallocate path_metrics and sum_path_metrics to avoid reallocating in each loop
% path_metrics = zeros(num_states, num_signals);
%
% % Loop over remaining trellis paths
% for n = 2:length(data_in)
% % Avoid reallocation of sum_path_metrics, reuse the same matrix and update
% previous_sum_path_metrics = sum_path_metrics_res(:,n-1).'; % Transpose once for broadcasting
% sum_path_metrics = repmat(previous_sum_path_metrics, num_states, 1); % Avoid dynamic resizing
%
% % Calculate path metrics using broadcasting
% path_metrics = (abs(data_in(n) - noise_free_received)).^2; % Avoid repmat
%
% % Update sum path metrics
% sum_path_metrics = sum_path_metrics + path_metrics;
%
% % Find the best path for each state and store results
% [sum_path_metrics_res(:,n), path_idx(:,n)] = min(sum_path_metrics, [], 2);
% end
%
% %% Traceback
% ideal_path = NaN(1, length(data_in)+1); % Preallocate ideal path
% [~, ideal_path(length(data_in)+1)] = min(sum_path_metrics_res(:,length(data_in))); % Start from final state
%
% % Trace back through trellis
% for h = length(data_in):-1:1
% ideal_path(h) = path_idx(ideal_path(h+1),h); % Follow the best path back
% end
%
% % Extract the output indices
% idx_out = ideal_path(2:end);
% OLD
% initilaize the output vector
data_out = NaN(size(data_in));
@@ -132,12 +189,17 @@ classdef MLSE
ideal_path(h) = path_idx(ideal_path(h+1),h);
end
idx_out = ideal_path(1:length(data_in));
idx_out = ideal_path(2:length(data_in)+1);
if obj.duobinary_output
%use duobinary encoder, output is already scaled inside this
%one
data_out = Duobinary().encode(first_sym(idx_out));
else
%
data_out(1:length(data_in)) = first_sym(idx_out);