DB and 400G and minor changes
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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))];
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user