DB and 400G and minor changes
This commit is contained in:
@@ -192,6 +192,19 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
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)
|
function Product = times(X,y)
|
||||||
|
|
||||||
if isa(y,'Signal')
|
if isa(y,'Signal')
|
||||||
@@ -271,14 +284,22 @@ classdef Signal
|
|||||||
N = 2^(nextpow2(length(obj.signal))-8);
|
N = 2^(nextpow2(length(obj.signal))-8);
|
||||||
|
|
||||||
[p_lin,w] = pwelch(obj.signal,hanning(N),N/2,N,obj.fs,"centered","power","mean");
|
[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
|
figure(options.fignum); % If figure does not exist, create new figure
|
||||||
hold on
|
hold on
|
||||||
plot(w.*1e-9,p_dbm,'DisplayName',options.displayname,'LineWidth',1);
|
plot(w.*1e-9,p_dbm,'DisplayName',options.displayname,'LineWidth',1);
|
||||||
xlabel("Frequency in GHz");
|
xlabel("Frequency in GHz");
|
||||||
%ylabel("Power/frequency (dB/Hz)");
|
%ylabel("Power/frequency (dB/Hz)");
|
||||||
ylabel("Power (dBm)");
|
ylabel(ylab);
|
||||||
xlim([-obj.fs/2 obj.fs/2].*1e-9)
|
xlim([-obj.fs/2 obj.fs/2].*1e-9)
|
||||||
edgetick = 2^(nextpow2(obj.fs*1e-9));
|
edgetick = 2^(nextpow2(obj.fs*1e-9));
|
||||||
% xticks([-edgetick:16:edgetick]);
|
% xticks([-edgetick:16:edgetick]);
|
||||||
@@ -362,7 +383,7 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%%
|
%% Normalize
|
||||||
function obj = normalize(obj,options)
|
function obj = normalize(obj,options)
|
||||||
|
|
||||||
arguments
|
arguments
|
||||||
@@ -381,7 +402,7 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%%
|
%% Delay
|
||||||
function [obj] = delay(obj,delay,options)
|
function [obj] = delay(obj,delay,options)
|
||||||
|
|
||||||
arguments
|
arguments
|
||||||
@@ -402,7 +423,7 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%%
|
%% Synchronize with reference
|
||||||
function [obj,D,cuts] = tsynch(obj,options)
|
function [obj,D,cuts] = tsynch(obj,options)
|
||||||
% time sync and cut
|
% time sync and cut
|
||||||
arguments
|
arguments
|
||||||
@@ -446,6 +467,10 @@ classdef Signal
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function obj = filter(obj,a,b)
|
||||||
|
obj.signal = filter(a,b,obj.signal);
|
||||||
|
end
|
||||||
|
|
||||||
function er = extinctionratio(obj,fsym,M)
|
function er = extinctionratio(obj,fsym,M)
|
||||||
histpoints = 1024; %% verticale resolution
|
histpoints = 1024; %% verticale resolution
|
||||||
histpoints = floor(histpoints/2)*2+1; %% to have the eye digram centered around one point make the vertical resolution uneven
|
histpoints = floor(histpoints/2)*2+1; %% to have the eye digram centered around one point make the vertical resolution uneven
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ classdef PAMsource
|
|||||||
randkey
|
randkey
|
||||||
|
|
||||||
db_precode
|
db_precode
|
||||||
|
db_encode
|
||||||
|
|
||||||
mrds_code
|
mrds_code
|
||||||
mrds_blocklength
|
mrds_blocklength
|
||||||
@@ -36,6 +37,7 @@ classdef PAMsource
|
|||||||
options.randkey = 0;
|
options.randkey = 0;
|
||||||
|
|
||||||
options.db_precode = 0;
|
options.db_precode = 0;
|
||||||
|
options.db_encode = 0;
|
||||||
|
|
||||||
options.mrds_code = 0;
|
options.mrds_code = 0;
|
||||||
options.mrds_blocklength = 512;
|
options.mrds_blocklength = 512;
|
||||||
@@ -95,11 +97,17 @@ classdef PAMsource
|
|||||||
symbols = PAMmapper(obj.M,0).map(bits);
|
symbols = PAMmapper(obj.M,0).map(bits);
|
||||||
symbols.fs = obj.fsym;
|
symbols.fs = obj.fsym;
|
||||||
|
|
||||||
|
%%%%%% Duobinary %%%%%%%%%%%
|
||||||
if obj.db_precode
|
if obj.db_precode
|
||||||
symbols = Duobinary().precode(symbols);
|
symbols = Duobinary().precode(symbols);
|
||||||
|
end
|
||||||
|
|
||||||
|
if obj.db_encode
|
||||||
symbols = Duobinary().encode(symbols);
|
symbols = Duobinary().encode(symbols);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
% figure(12);hold on;histogram(symbols.signal,'Normalization','probability');
|
||||||
|
|
||||||
if obj.mrds_code
|
if obj.mrds_code
|
||||||
symbols = MRDS_coding("blocklength",obj.mrds_blocklength).encode(symbols);
|
symbols = MRDS_coding("blocklength",obj.mrds_blocklength).encode(symbols);
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,8 +47,12 @@ classdef Duobinary
|
|||||||
% Pre coding
|
% Pre coding
|
||||||
bk = zeros(numel(data),1);
|
bk = zeros(numel(data),1);
|
||||||
|
|
||||||
for k = 1:numel(data)-1
|
% for k = 1:numel(data)-1
|
||||||
bk(k+1) =mod(data(k)-bk(k),M);
|
% 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
|
end
|
||||||
|
|
||||||
%make bipolar
|
%make bipolar
|
||||||
@@ -107,9 +111,16 @@ classdef Duobinary
|
|||||||
assert(isequal((0:M-1)',unique(data)),'Check Duobinary Precoding'); %seems the signal is not unipolar
|
assert(isequal((0:M-1)',unique(data)),'Check Duobinary Precoding'); %seems the signal is not unipolar
|
||||||
|
|
||||||
% duobinary coding (1+D)
|
% duobinary coding (1+D)
|
||||||
|
% coeff = [1,1];
|
||||||
|
%
|
||||||
|
% data = conv(data,coeff,"same");
|
||||||
|
|
||||||
coeff = [1,1];
|
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
|
%make bipolar
|
||||||
data = (data-round(mean(data),1));
|
data = (data-round(mean(data),1));
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ classdef FFE < handle
|
|||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function [X] = process(obj, X, D)
|
function [X,Noi] = process(obj, X, D)
|
||||||
|
|
||||||
% actual processing of the signal (steps 1. - 3.)
|
% actual processing of the signal (steps 1. - 3.)
|
||||||
% 1 normalize RMS
|
% 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);
|
obj.equalize(X.signal, D.signal,obj.mu_tr,obj.epochs_tr,obj.len_tr,training,showviz);
|
||||||
|
|
||||||
% Decision Directed Mode
|
% Decision Directed Mode
|
||||||
N = X.length;
|
n = X.length;
|
||||||
training = 0;
|
training = 0;
|
||||||
showviz = 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
|
% Output Signal
|
||||||
if obj.decide
|
if obj.decide
|
||||||
@@ -76,10 +76,14 @@ classdef FFE < handle
|
|||||||
else
|
else
|
||||||
X.signal = signal;
|
X.signal = signal;
|
||||||
end
|
end
|
||||||
|
|
||||||
X.fs = D.fs; %change sampling frequency of outgoing signal from fdac e.g. 2 sps to symbol spaced = fsym
|
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'];
|
lbdesc = [num2str(obj.order),' tap FFE'];
|
||||||
X = X.logbookentry(lbdesc); % append to logbook
|
X = X.logbookentry(lbdesc); % append to logbook
|
||||||
|
|
||||||
|
Noi = X;
|
||||||
|
Noi = X - D;
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -54,10 +54,12 @@ classdef MLSE
|
|||||||
obj.DIR(1:DIR_nonzero(1)-1) = [];
|
obj.DIR(1:DIR_nonzero(1)-1) = [];
|
||||||
end
|
end
|
||||||
|
|
||||||
if length(obj.DIR) == 1
|
if isscalar(obj.DIR)
|
||||||
obj.DIR = [0 obj.DIR];
|
obj.DIR = [0 obj.DIR];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
obj.DIR = flip(obj.DIR);
|
||||||
|
|
||||||
% RMS normalization of input data
|
% RMS normalization of input data
|
||||||
data_in = data_in ./ rms(data_in);
|
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
|
% i.e. match the rms values of data_in to noise_free_received
|
||||||
if isreal(data_in)
|
if isreal(data_in)
|
||||||
if obj.M == round(obj.M)
|
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
|
||||||
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
|
% initilaize the output vector
|
||||||
data_out = NaN(size(data_in));
|
data_out = NaN(size(data_in));
|
||||||
|
|
||||||
@@ -132,12 +189,17 @@ classdef MLSE
|
|||||||
ideal_path(h) = path_idx(ideal_path(h+1),h);
|
ideal_path(h) = path_idx(ideal_path(h+1),h);
|
||||||
end
|
end
|
||||||
|
|
||||||
idx_out = ideal_path(1:length(data_in));
|
idx_out = ideal_path(2:length(data_in)+1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if obj.duobinary_output
|
if obj.duobinary_output
|
||||||
%use duobinary encoder, output is already scaled inside this
|
%use duobinary encoder, output is already scaled inside this
|
||||||
%one
|
%one
|
||||||
data_out = Duobinary().encode(first_sym(idx_out));
|
data_out = Duobinary().encode(first_sym(idx_out));
|
||||||
|
|
||||||
else
|
else
|
||||||
%
|
%
|
||||||
data_out(1:length(data_in)) = first_sym(idx_out);
|
data_out(1:length(data_in)) = first_sym(idx_out);
|
||||||
|
|||||||
@@ -1,61 +1,68 @@
|
|||||||
classdef PAMmapper_test < matlab.unittest.TestCase
|
classdef PAMmapper_test < matlab.unittest.TestCase
|
||||||
|
|
||||||
properties
|
properties
|
||||||
Digi_Mod
|
|
||||||
Tx_bits
|
Tx_bits
|
||||||
Rx_bits
|
PAMmapper
|
||||||
% M = 8; % Modulation order
|
end
|
||||||
fsym = 112e9; % Symbol rate
|
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
% Define method-level parameters for PRBS and bit pattern
|
||||||
|
useprbs = struct('false', 0, 'true', 1); % variations: {0, 1}
|
||||||
|
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
|
||||||
|
O = struct('O10', 10, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
|
||||||
end
|
end
|
||||||
|
|
||||||
properties (TestParameter)
|
properties (TestParameter)
|
||||||
M = {4,6,8};
|
% Define test-level parameters for M and O
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
methods (TestMethodSetup)
|
methods (TestMethodSetup)
|
||||||
function setupModulation(testCase)
|
|
||||||
% Setup PRBS and bit pattern for the test case
|
function setupModulation(testCase, useprbs, M, O)
|
||||||
O = 10; % Order of PRBS
|
% Setup PRBS and bit pattern for the test case using parameters
|
||||||
|
|
||||||
|
% Setup PRBS parameters
|
||||||
N = 2^(O-1); % Length of PRBS
|
N = 2^(O-1); % Length of PRBS
|
||||||
useprbs = 1; % Flag to use PRBS
|
|
||||||
randkey = 1; % Random key for random stream
|
randkey = 1; % Random key for random stream
|
||||||
|
|
||||||
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
|
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
|
||||||
bitpattern = [];
|
bitpattern = [];
|
||||||
if useprbs
|
if useprbs
|
||||||
for i = 1:log2(testCase.M)
|
for i = 1:log2(M)
|
||||||
[bitpattern(:, i), seed] = prbs(O, N, seed);
|
[bitpattern(:, i), seed] = prbs(O, N, seed);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
s = RandStream('twister', 'Seed', randkey);
|
s = RandStream('twister', 'Seed', randkey);
|
||||||
for i = 1:log2(testCase.M)
|
for i = 1:log2(M)
|
||||||
bitpattern(:, i) = randi(s, [0 1], N, 1);
|
bitpattern(:, i) = randi(s, [0 1], N, 1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if testCase.M == 6
|
if M == 6
|
||||||
bitpattern = reshape(bitpattern, [], 1);
|
bitpattern = reshape(bitpattern, [], 1);
|
||||||
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
|
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
|
||||||
end
|
end
|
||||||
|
|
||||||
testCase.Tx_bits = Informationsignal(bitpattern);
|
testCase.Tx_bits = Informationsignal(bitpattern);
|
||||||
testCase.Digi_Mod = PAMmapper(testCase.M, 0);
|
testCase.PAMmapper = PAMmapper(M, 0);
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
methods (Test)
|
methods (Test, ParameterCombination = 'sequential')
|
||||||
function testBackToBackMapping(testCase)
|
% Test with sequential combination of parameters
|
||||||
|
function testBackToBackMapping(testCase, M, useprbs, O)
|
||||||
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
|
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
|
||||||
|
|
||||||
% Map bits to symbols
|
% Map bits to symbols
|
||||||
Symbols = testCase.Digi_Mod.map(testCase.Tx_bits);
|
Symbols = testCase.PAMmapper.map(testCase.Tx_bits);
|
||||||
|
|
||||||
% Demap symbols back to bits
|
% Demap symbols back to bits
|
||||||
testCase.Rx_bits = testCase.Digi_Mod.demap(Symbols);
|
Rx_bits = testCase.PAMmapper.demap(Symbols);
|
||||||
|
|
||||||
% Validate BER is zero
|
% Validate BER is zero
|
||||||
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, testCase.Rx_bits.signal, ...
|
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, Rx_bits.signal, ...
|
||||||
"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
|
"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
|
||||||
|
|
||||||
% Assert that BER is zero
|
% Assert that BER is zero
|
||||||
|
|||||||
@@ -1,11 +1,108 @@
|
|||||||
classdef Duobinary_test < matlab.unittest.TestCase
|
classdef Duobinary_test < matlab.unittest.TestCase
|
||||||
% Test class for Duobinary
|
|
||||||
|
properties
|
||||||
|
%genereal properties of the test
|
||||||
|
ber
|
||||||
|
errors
|
||||||
|
errorIndice
|
||||||
|
numbits
|
||||||
|
numsymbols
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
% Define method-level parameters for PRBS and bit pattern
|
||||||
|
% i.e.: useprbs = {0,1};
|
||||||
|
useprbs = struct('true', 1,'false', 0); % variations: {0, 1}
|
||||||
|
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
|
||||||
|
O = struct('O10', 10,'O11', 11,'O12', 12,'O13', 13, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (TestParameter)
|
||||||
|
% Define test-level parameters for M and O
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (TestMethodSetup, ParameterCombination = 'pairwise')
|
||||||
|
|
||||||
|
function setupTest(testCase, useprbs, M, O)
|
||||||
|
|
||||||
|
randkey = 1;
|
||||||
|
datarate = 448e9;
|
||||||
|
fsym = round(datarate / log2(M)) ;
|
||||||
|
|
||||||
|
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||||
|
N = 2^O; %length of prbs
|
||||||
|
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||||
|
bitpattern=[];
|
||||||
|
|
||||||
|
if useprbs
|
||||||
|
for i = 1:log2(M)
|
||||||
|
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s = RandStream('twister','Seed',randkey);
|
||||||
|
for i = 1:log2(M)
|
||||||
|
bitpattern(:,i) = randi(s,[0 1], N, 1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if M == 6
|
||||||
|
bitpattern = reshape(bitpattern,[],1);
|
||||||
|
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||||
|
end
|
||||||
|
|
||||||
|
testCase.numbits = length(bitpattern);
|
||||||
|
|
||||||
|
Tx_bits = Informationsignal(bitpattern);
|
||||||
|
|
||||||
|
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
|
||||||
|
Symbols_tx.fs = fsym;
|
||||||
|
|
||||||
|
testCase.numsymbols = length(Symbols_tx);
|
||||||
|
|
||||||
|
Symbols_tx = PAMmapper(M,0).map(Tx_bits);
|
||||||
|
|
||||||
|
Symbols_tx.fs = fsym;
|
||||||
|
|
||||||
|
Symbols = Duobinary().precode(Symbols_tx);
|
||||||
|
|
||||||
|
Symbols = Duobinary().encode(Symbols);
|
||||||
|
|
||||||
|
Symbols = Duobinary().decode(Symbols);
|
||||||
|
|
||||||
|
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||||
|
|
||||||
|
[bits,testCase.errors,testCase.ber,testCase.errorIndice] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
methods (Test)
|
methods (Test)
|
||||||
function testExample(testCase)
|
% Test with sequential combination of parameters
|
||||||
% Example test case for Duobinary
|
|
||||||
% Add your test code here
|
function checkBerZero(testCase, useprbs, M, O)
|
||||||
testCase.verifyTrue(true);
|
% Assert that BER is zero
|
||||||
|
testCase.verifyEqual(testCase.ber, 0, ['Numer of Errors is not zero, found ',num2str(testCase.errors), ' errors at position ', num2str(testCase.errorIndice),' out of ', num2str(2^O)]);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function checkBerCloseToZero(testCase, useprbs, M, O)
|
||||||
|
|
||||||
|
testCase.verifyLessThan(testCase.errors, 5, ['Found more than 5 errors. Found ',num2str(testCase.errors),' errors.']);
|
||||||
|
|
||||||
|
% if ~isempty(testCase.errorIndice)
|
||||||
|
% testCase.verifyEqual(testCase.errorIndice, 2^O , ['Error is NOT at the End but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
|
||||||
|
% testCase.verifyEqual(testCase.errorIndice,1, ['Error is NOT at the Beginning but at: ', num2str(testCase.errorIndice),' of ', num2str(2^O)]);
|
||||||
|
% end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function checkSystemFailure(testCase, useprbs, M, O)
|
||||||
|
testCase.verifyLessThan(testCase.ber, 0.1, ['BER is higher than 10%. Soemthing is completely wrong! (BER is ',num2str(testCase.ber),')']);
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
50
Tests/Testclass_template.m
Normal file
50
Tests/Testclass_template.m
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
classdef Testclass_template < matlab.unittest.TestCase
|
||||||
|
|
||||||
|
properties
|
||||||
|
%genereal properties of the test
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
% Define method-level parameters for PRBS and bit pattern
|
||||||
|
% i.e.: useprbs = {0,1};
|
||||||
|
useprbs = {0,1};
|
||||||
|
M = {2,4,6};
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (TestParameter)
|
||||||
|
% Define test-level parameters for M and O
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (TestMethodSetup)
|
||||||
|
|
||||||
|
function setupTest(testCase, useprbs, M)
|
||||||
|
% Setup everything that is somehow reguired for the test,
|
||||||
|
% include the MethodSetupParameters here as arguments
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test)
|
||||||
|
% Test with sequential combination of parameters
|
||||||
|
function myTest(testCase, M, useprbs)
|
||||||
|
% Write the actual test,
|
||||||
|
% include the MethodSetupParameters here as arguments
|
||||||
|
|
||||||
|
% Assert that BER is zero
|
||||||
|
testCase.verifyEqual(M, M, 'error message');
|
||||||
|
testCase.verifyEqual(useprbs, useprbs, 'error message');
|
||||||
|
end
|
||||||
|
|
||||||
|
% Test with sequential combination of parameters
|
||||||
|
function anotherTest(testCase, M)
|
||||||
|
% Write the actual test,
|
||||||
|
% include the MethodSetupParameters here as arguments
|
||||||
|
|
||||||
|
% Assert that BER is zero
|
||||||
|
testCase.verifyEqual(M, M, 'error message');
|
||||||
|
testCase.verifyClass(M,'double');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
0
projects/400G_FTN_setups/duobinary_example.m
Normal file
0
projects/400G_FTN_setups/duobinary_example.m
Normal file
Binary file not shown.
@@ -16,6 +16,7 @@ for i = 1:log2(M)
|
|||||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
if M == 6
|
if M == 6
|
||||||
bitpattern = reshape(bitpattern,[],1);
|
bitpattern = reshape(bitpattern,[],1);
|
||||||
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
|
||||||
|
|||||||
Binary file not shown.
@@ -2,11 +2,17 @@
|
|||||||
%% Parameter to simulate and save
|
%% Parameter to simulate and save
|
||||||
params = struct;
|
params = struct;
|
||||||
|
|
||||||
params.M = [4];
|
params.M = [8];
|
||||||
params.datarate = [300];
|
params.datarate = [448];
|
||||||
params.rop = [0];
|
params.rop = [-12:0];
|
||||||
|
|
||||||
|
precomp_mode = 0; %0=do nothing ; 1= measure; 2=precomp active
|
||||||
|
postfilter = 0; % noise whiten. approach -> Postfilter + MLSE
|
||||||
|
|
||||||
|
db_precode = 1;
|
||||||
|
db_encode = 1;
|
||||||
|
db_channelapproach = 0;
|
||||||
|
|
||||||
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
|
|
||||||
|
|
||||||
if ismac
|
if ismac
|
||||||
precomp_path = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/standard_system";
|
precomp_path = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/standard_system";
|
||||||
@@ -24,7 +30,7 @@ wh = DataStorage(params);
|
|||||||
wh.addStorage("ber_ffe");
|
wh.addStorage("ber_ffe");
|
||||||
|
|
||||||
%% Init Params
|
%% Init Params
|
||||||
link_length = 0; %meter
|
link_length = 1000; %meter
|
||||||
pn_key = 2;
|
pn_key = 2;
|
||||||
laser_linewidth = 0;
|
laser_linewidth = 0;
|
||||||
|
|
||||||
@@ -34,7 +40,6 @@ cnt=0;
|
|||||||
disp(['Start Simulation of ',num2str(endcnt),' loops...'])
|
disp(['Start Simulation of ',num2str(endcnt),' loops...'])
|
||||||
tic
|
tic
|
||||||
|
|
||||||
|
|
||||||
for M = wh.parameter.M.values
|
for M = wh.parameter.M.values
|
||||||
for datarate = wh.parameter.datarate.values
|
for datarate = wh.parameter.datarate.values
|
||||||
|
|
||||||
@@ -50,32 +55,34 @@ for M = wh.parameter.M.values
|
|||||||
|
|
||||||
%%%%% Symbol Generation %%%%%%
|
%%%%% Symbol Generation %%%%%%
|
||||||
[Digi_sig,Symbols,Bits] = PAMsource("fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
[Digi_sig,Symbols,Bits] = PAMsource("fsym",fsym,"M",M,"order",18,"useprbs",0,...
|
||||||
"fs_out",M8199.fdac,"applyclipping",1,"clipfactor",1.7,...
|
"fs_out",M8199.fdac,"applyclipping",1,"clipfactor",1.5,...
|
||||||
"applypulseform",0,"pulseformer",Pform,"randkey",pn_key,...
|
"applypulseform",0,"pulseformer",Pform,"randkey",pn_key,...
|
||||||
"db_precode",0,...
|
"db_precode",db_precode,"db_encode",db_encode,...
|
||||||
"mrds_code",usemrds,"mrds_blocklength",512).process();
|
"mrds_code",usemrds,"mrds_blocklength",512).process();
|
||||||
|
|
||||||
Digi_sig.eye(fsym,M);
|
% Digi_sig.eye(fsym,M);
|
||||||
Digi_sig.spectrum("fignum",11,"displayname",'before precomp');
|
Digi_sig.spectrum("fignum",123434,"displayname",'Digital Tx Signal');
|
||||||
|
|
||||||
if precomp_mode == 1
|
if precomp_mode == 1
|
||||||
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
|
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
|
||||||
Digi_sig = freqresp.buildOFDM();
|
Digi_sig = freqresp.buildOFDM();
|
||||||
elseif precomp_mode == 2
|
elseif precomp_mode == 2
|
||||||
Digi_sig = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs).precomp(Digi_sig,'maxampdb',3,'loadPath',precomp_path,'fileName',precomp_fn);
|
Digi_sig = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs).precomp(Digi_sig,'maxampdb',1,'loadPath',precomp_path,'fileName',precomp_fn);
|
||||||
Digi_sig.spectrum("fignum",11,"displayname",'after precomp');
|
Digi_sig.spectrum("fignum",11,"displayname",'after precomp');
|
||||||
end
|
end
|
||||||
|
|
||||||
%%%%% AWG %%%%%%
|
%%%%% AWG %%%%%%
|
||||||
El_sig = M8199.process(Digi_sig);
|
El_sig = M8199.process(Digi_sig);
|
||||||
|
|
||||||
|
% El_sig.spectrum("displayname",'el','fignum',123434);
|
||||||
|
|
||||||
% El_sig.signal = awgn(El_sig.signal,-3,'measured',pn_key);
|
% El_sig.signal = awgn(El_sig.signal,-3,'measured',pn_key);
|
||||||
|
|
||||||
%%%%% Lowpass el. components %%%%%%
|
%%%%% Lowpass el. components %%%%%%
|
||||||
El_sig = Filter('filtdegree',2,"f_cutoff",60e9,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
El_sig = Filter('filtdegree',2,"f_cutoff",60e9,"fs",fdac*kover,"filterType",filtertypes.butterworth,"active",true).process(El_sig);
|
||||||
|
|
||||||
%%%%% Electrical Driver Amplifier %%%%%%
|
%%%%% Electrical Driver Amplifier %%%%%%
|
||||||
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",9).process(El_sig);
|
El_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","gain","amplification_db",3).process(El_sig);
|
||||||
% El_sig = El_sig.setPower(6,"dBm");
|
% El_sig = El_sig.setPower(6,"dBm");
|
||||||
|
|
||||||
fprintf('Driver output power: %s dBm\n', num2str(El_sig.power));
|
fprintf('Driver output power: %s dBm\n', num2str(El_sig.power));
|
||||||
@@ -90,9 +97,8 @@ for M = wh.parameter.M.values
|
|||||||
|
|
||||||
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",1290,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",pn_key).process(El_sig);
|
[Opt_sig] = EML("mode",eml_mode.im_cosinus,"power",3,"fsimu",El_sig.fs,"lambda",1290,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",pn_key).process(El_sig);
|
||||||
|
|
||||||
|
% Opt_sig.eye(fsym,7);
|
||||||
% Opt_sig.eye(fsym,M);
|
%
|
||||||
% %
|
|
||||||
% figure(10)
|
% figure(10)
|
||||||
% hold on
|
% hold on
|
||||||
% scatter(El_sig.signal(1:100000)+vbias,(abs(Opt_sig.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF')
|
% scatter(El_sig.signal(1:100000)+vbias,(abs(Opt_sig.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF')
|
||||||
@@ -104,6 +110,8 @@ for M = wh.parameter.M.values
|
|||||||
Optfilter = Filter('filtdegree',6,"f_cutoff",fsym.*0.7,"fs",fdac*kover,"filterType",filtertypes.gaussian,"active",true);
|
Optfilter = Filter('filtdegree',6,"f_cutoff",fsym.*0.7,"fs",fdac*kover,"filterType",filtertypes.gaussian,"active",true);
|
||||||
Opt_sig = Optfilter.process(Opt_sig);
|
Opt_sig = Optfilter.process(Opt_sig);
|
||||||
|
|
||||||
|
% Opt_sig.spectrum("fignum",122,"displayname",['Tx SPectrum; PAM ',num2str(M)]);
|
||||||
|
|
||||||
Opt_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",0).process(Opt_sig);
|
Opt_sig = Amplifier("amp_mode","ideal_no_noise","gain_mode","output_power","amplification_db",0).process(Opt_sig);
|
||||||
|
|
||||||
i_ = wh.parameter.rop.length;
|
i_ = wh.parameter.rop.length;
|
||||||
@@ -143,19 +151,54 @@ for M = wh.parameter.M.values
|
|||||||
freqresp.plot();
|
freqresp.plot();
|
||||||
end
|
end
|
||||||
|
|
||||||
|
Scpe_sig.spectrum("displayname",'After Scope','fignum',123434);
|
||||||
|
|
||||||
%%%%%% Sample to 2x fsym %%%%%%
|
%%%%%% Sample to 2x fsym %%%%%%
|
||||||
Scpe_sig = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym);
|
Scpe_sig = Scpe_sig.resample("fs_in",fadc,"fs_out",2*fsym);
|
||||||
|
|
||||||
|
|
||||||
%%%%%% Sync Rx signal with reference %%%%%%
|
%%%%%% Sync Rx signal with reference %%%%%%
|
||||||
[Scpe_sig,D,cuts] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym);
|
[Scpe_sig,D,cuts] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym);
|
||||||
|
|
||||||
|
|
||||||
%%%%% EQUALIZE %%%%%%
|
%%%%% EQUALIZE %%%%%%
|
||||||
%
|
Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0);
|
||||||
Eq = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",1);
|
|
||||||
%Eq = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,7,7],"sps",2,"decide",1);
|
%Eq = VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,7,7],"sps",2,"decide",1);
|
||||||
[EQ_sig] = Eq.process(Scpe_sig,Symbols);
|
|
||||||
|
if db_channelapproach
|
||||||
|
% ref symbols and transm. sequence are precoded
|
||||||
|
[EQ_sig, Noi] = Eq.process(Scpe_sig,Duobinary().encode(Symbols));
|
||||||
|
else
|
||||||
|
[EQ_sig, Noi] = Eq.process(Scpe_sig,Symbols);
|
||||||
|
end
|
||||||
|
|
||||||
|
if db_encode || db_channelapproach
|
||||||
|
EQ_sig = MLSE("DIR",[1,1],"duobinary_output",1,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
|
||||||
|
EQ_sig = Duobinary().decode(EQ_sig);
|
||||||
|
end
|
||||||
|
|
||||||
|
if postfilter
|
||||||
|
% Noi.spectrum("displayname",'Noise Spectrum','fignum',1234);
|
||||||
|
% EQ_sig.spectrum("displayname","Signal Spectrum","fignum",1234);
|
||||||
|
|
||||||
|
nc = 2;
|
||||||
|
burg_coeff = arburg(Noi.signal,nc);
|
||||||
|
|
||||||
|
EQ_sig = EQ_sig.filter(burg_coeff,1);
|
||||||
|
|
||||||
|
% EQ_sig.spectrum("displayname","Signal Spectrum after Postfilter","fignum",1234);
|
||||||
|
tic
|
||||||
|
EQ_sig = MLSE("DIR",burg_coeff,"duobinary_output",0,"M",M,"trellis_states",PAMmapper(M,0).levels).process(EQ_sig);
|
||||||
|
toc
|
||||||
|
% EQ_sig.spectrum("displayname","Signal Spectrum after MLSE","fignum",1234);
|
||||||
|
|
||||||
|
if 0
|
||||||
|
[h,w] = freqz(1,burg_coeff,length(Noi),"whole",Noi.fs);
|
||||||
|
h = h/max(abs(h));
|
||||||
|
hold on
|
||||||
|
w_ = (w - Noi.fs/2);
|
||||||
|
plot(w_.*1e-9,20*log10(fftshift(h)),'DisplayName',['', num2str(nc), ' coefficients for burg alg.']);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
|
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
|
||||||
[~,errors_bm,ber_ffe(i),errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
[~,errors_bm,ber_ffe(i),errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
|
||||||
disp(['BER: ',sprintf('%.1E',ber_ffe(i)),' - - ROP: ',num2str(patten(i)),'dBm - - PAM-',num2str(M),' - - ',num2str(fsym*1e-9),' GBd']);
|
disp(['BER: ',sprintf('%.1E',ber_ffe(i)),' - - ROP: ',num2str(patten(i)),'dBm - - PAM-',num2str(M),' - - ',num2str(fsym*1e-9),' GBd']);
|
||||||
@@ -170,19 +213,21 @@ for M = wh.parameter.M.values
|
|||||||
end
|
end
|
||||||
|
|
||||||
toc
|
toc
|
||||||
disp(['Simulated: ',num2str(cnt/endcnt*100),' %']);
|
|
||||||
% wh.save('C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\MPI_August\auswertung\')
|
% wh.save('C:\Users\Silas\Documents\MATLAB\imdd_simulation\projects\MPI_August\auswertung\')
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
disp('Simulation Done!')
|
||||||
|
|
||||||
|
|
||||||
cols = linspecer(8);
|
cols = linspecer(8);
|
||||||
|
|
||||||
%cnt = cnt+1;
|
%cnt = cnt+1;
|
||||||
ber_ffe = wh.getStoValue('ber_ffe',M,datarate,wh.parameter.rop.values);
|
ber_ffe = wh.getStoValue('ber_ffe',M,datarate,wh.parameter.rop.values);
|
||||||
|
|
||||||
|
|
||||||
% Create the initial plot
|
% Create the initial plot
|
||||||
|
|
||||||
figure(44);
|
figure(44);
|
||||||
|
|||||||
@@ -2,6 +2,9 @@ M = wh.parameter.M.values(1);
|
|||||||
datarates = wh.parameter.datarate.values;
|
datarates = wh.parameter.datarate.values;
|
||||||
rop = wh.parameter.rop.values;
|
rop = wh.parameter.rop.values;
|
||||||
|
|
||||||
|
clear("sens_ffe")
|
||||||
|
|
||||||
|
col = flip(cbrewer2("RdYlGn",numel(datarates)));
|
||||||
|
|
||||||
cnt = 1;
|
cnt = 1;
|
||||||
for dr = datarates
|
for dr = datarates
|
||||||
@@ -10,9 +13,9 @@ for dr = datarates
|
|||||||
|
|
||||||
sens_ffe(cnt) = getIntersection(ber_ffe,rop);
|
sens_ffe(cnt) = getIntersection(ber_ffe,rop);
|
||||||
|
|
||||||
figure(112)
|
figure(116)
|
||||||
hold on
|
hold on
|
||||||
plot(rop,ber_ffe,"LineWidth",0.5,"LineStyle","-","Marker",".","MarkerSize",15,"DisplayName",['FFE only; ',num2str(dr), ' Gbps']);
|
plot(rop,ber_ffe,"LineWidth",0.5,"LineStyle","-","Marker",".","MarkerSize",15,"DisplayName",['Postfilter + MLSE; ',num2str(dr), ' Gbps'],'Color',col(cnt,:));
|
||||||
yline(3.8e-3,'DisplayName','HD-FEC','LineStyle','--','HandleVisibility','off');
|
yline(3.8e-3,'DisplayName','HD-FEC','LineStyle','--','HandleVisibility','off');
|
||||||
xlabel('Received Optical Power (dBm)');
|
xlabel('Received Optical Power (dBm)');
|
||||||
ylabel('Bit Error Rate (BER)');
|
ylabel('Bit Error Rate (BER)');
|
||||||
@@ -28,7 +31,7 @@ for dr = datarates
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
figure(223);
|
figure(22);
|
||||||
hold on; % Retain the plot so new points can be added without complete redraw
|
hold on; % Retain the plot so new points can be added without complete redraw
|
||||||
plot(datarates,sens_ffe,"LineWidth",1,"LineStyle","-","Marker",".","MarkerSize",10,"DisplayName",['Linewidth: ',num2str(laser_linewidth.*1e-6),' MHz']);
|
plot(datarates,sens_ffe,"LineWidth",1,"LineStyle","-","Marker",".","MarkerSize",10,"DisplayName",['Linewidth: ',num2str(laser_linewidth.*1e-6),' MHz']);
|
||||||
xlabel('Signal to Interference Ratio (dB)');
|
xlabel('Signal to Interference Ratio (dB)');
|
||||||
|
|||||||
54
test/TestRand_examplecode.m
Normal file
54
test/TestRand_examplecode.m
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
classdef TestRand_examplecode < matlab.unittest.TestCase
|
||||||
|
properties (ClassSetupParameter)
|
||||||
|
generator = {'twister','combRecursive','multFibonacci'};
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
seed = {0,123,4294967295};
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (TestParameter)
|
||||||
|
dim1 = struct('small',1,'medium',2,'large',3);
|
||||||
|
dim2 = struct('small',2,'medium',3,'large',4);
|
||||||
|
dim3 = struct('small',3,'medium',4,'large',5);
|
||||||
|
type = {'single','double'};
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (TestClassSetup)
|
||||||
|
function classSetup(testCase,generator)
|
||||||
|
orig = rng;
|
||||||
|
testCase.addTeardown(@rng,orig)
|
||||||
|
rng(0,generator)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (TestMethodSetup)
|
||||||
|
function methodSetup(testCase,seed)
|
||||||
|
orig = rng;
|
||||||
|
testCase.addTeardown(@rng,orig)
|
||||||
|
rng(seed)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test, ParameterCombination = 'sequential')
|
||||||
|
function testSize(testCase,dim1,dim2,dim3)
|
||||||
|
testCase.verifySize(rand(dim1,dim2,dim3),[dim1 dim2 dim3])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test, ParameterCombination = 'pairwise')
|
||||||
|
function testRepeatable(testCase,dim1,dim2,dim3)
|
||||||
|
state = rng;
|
||||||
|
firstRun = rand(dim1,dim2,dim3);
|
||||||
|
rng(state)
|
||||||
|
secondRun = rand(dim1,dim2,dim3);
|
||||||
|
testCase.verifyEqual(firstRun,secondRun)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test)
|
||||||
|
function testClass(testCase,dim1,dim2,type)
|
||||||
|
testCase.verifyClass(rand(dim1,dim2,type),type)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
useprbs = 1;
|
useprbs = 1;
|
||||||
M = 8;
|
M = 6;
|
||||||
randkey = 1;
|
randkey = 1;
|
||||||
fsym = 112e9;
|
datarate = 448e9;
|
||||||
|
fsym = round(datarate / log2(M)) ;
|
||||||
|
|
||||||
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||||
O = 18; %order of prbs
|
O = 17; %order of prbs
|
||||||
N = 2^(O-1); %length of prbs
|
N = 2^(O); %length of prbs
|
||||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||||
bitpattern=[];
|
bitpattern=[];
|
||||||
|
|
||||||
@@ -34,12 +35,6 @@ Symbols = Duobinary().precode(Symbols_tx);
|
|||||||
|
|
||||||
Symbols = Duobinary().encode(Symbols);
|
Symbols = Duobinary().encode(Symbols);
|
||||||
|
|
||||||
% Symbols.spectrum("displayname","db","fignum",12)
|
|
||||||
|
|
||||||
% Symbols = Duobinary().feedbackdetector(Symbols);
|
|
||||||
|
|
||||||
% Symbols.eye(fsym,M);
|
|
||||||
|
|
||||||
Symbols = Duobinary().decode(Symbols);
|
Symbols = Duobinary().decode(Symbols);
|
||||||
|
|
||||||
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||||
@@ -48,15 +43,35 @@ Rx_bits = PAMmapper(M,0).demap(Symbols);
|
|||||||
|
|
||||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||||
%
|
%
|
||||||
figure;hold on
|
|
||||||
subplot(2,1,1)
|
|
||||||
title('Bits Compare')
|
figure(3);
|
||||||
stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits')
|
clf
|
||||||
stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits');
|
%sgtitle(['BER: ',num2str(ber),' // Error is at position: ',num2str(error_pos),''])
|
||||||
legend
|
subplot(2,2,1)
|
||||||
subplot(2,1,2)
|
|
||||||
hold on
|
hold on
|
||||||
title('Symbols Compare')
|
title('First Bits')
|
||||||
stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
stairs(Tx_bits.signal(1:100,1),'LineStyle','-','LineWidth',2,'DisplayName','Tx Bits');
|
||||||
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols')
|
stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits','LineStyle',':')
|
||||||
|
legend
|
||||||
|
|
||||||
|
subplot(2,2,2)
|
||||||
|
title('Last Bits')
|
||||||
|
hold on
|
||||||
|
stairs(Tx_bits.signal(end-50:end,1),'LineStyle','-','LineWidth',2,'DisplayName','Tx Bits');
|
||||||
|
stairs(Rx_bits.signal(end-50:end,1),'LineWidth',2,'DisplayName','Rx Bits','LineStyle',':')
|
||||||
|
legend
|
||||||
|
|
||||||
|
subplot(2,2,3)
|
||||||
|
hold on
|
||||||
|
title('First Symbols Compare')
|
||||||
|
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle','-')
|
||||||
|
stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
||||||
|
legend
|
||||||
|
|
||||||
|
subplot(2,2,4)
|
||||||
|
hold on
|
||||||
|
title('Last Symbols Compare')
|
||||||
|
stairs(Symbols_tx.signal(end-50:end,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle','-')
|
||||||
|
stairs(Symbols.signal(end-50:end,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
||||||
legend
|
legend
|
||||||
@@ -30,8 +30,6 @@ end
|
|||||||
|
|
||||||
Tx_bits = Informationsignal(bitpattern);
|
Tx_bits = Informationsignal(bitpattern);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%% ACTUAL TEST: Back to Back Mapping: Bits -> Symbols and Symbols -> Bits %%%%%%
|
%%%%% ACTUAL TEST: Back to Back Mapping: Bits -> Symbols and Symbols -> Bits %%%%%%
|
||||||
|
|
||||||
Digi_Mod = PAMmapper(M,0);
|
Digi_Mod = PAMmapper(M,0);
|
||||||
@@ -41,14 +39,11 @@ Symbols = Digi_Mod.map(Tx_bits);
|
|||||||
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%% VALIDATION: BER is required to be zero %%%%%%
|
%%%%% VALIDATION: BER is required to be zero %%%%%%
|
||||||
|
|
||||||
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
%%%%% For User: Show Debug Info and Results %%%%%%
|
%%%%% For User: Show Debug Info and Results %%%%%%
|
||||||
|
|
||||||
if viewresults
|
if viewresults
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
useprbs = 1;
|
useprbs = 0;
|
||||||
M = 8;
|
M = 4;
|
||||||
randkey = 1;
|
randkey = 2;
|
||||||
fsym = 112e9;
|
fsym = 112e9;
|
||||||
|
|
||||||
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
%%%%% PRBS Generation in correct shape for Modulation Format %%%%%%
|
||||||
@@ -31,29 +31,50 @@ Digi_Mod = PAMmapper(M,0);
|
|||||||
Symbols_tx = Digi_Mod.map(Tx_bits);
|
Symbols_tx = Digi_Mod.map(Tx_bits);
|
||||||
Symbols_tx.fs = fsym;
|
Symbols_tx.fs = fsym;
|
||||||
|
|
||||||
Symbols = Duobinary().precode(Symbols_tx);
|
if 0
|
||||||
|
|
||||||
Symbols = Duobinary().encode(Symbols);
|
Symbols = Duobinary().precode(Symbols_tx);
|
||||||
|
|
||||||
Symbols = MLSE("DIR",[1,1],"duobinary_output",1,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols);
|
Symbols = Duobinary().encode(Symbols);
|
||||||
|
|
||||||
Symbols = Duobinary().decode(Symbols);
|
Symbols = MLSE("DIR",[1 1],"duobinary_output",1,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols);
|
||||||
|
|
||||||
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
Symbols = Duobinary().decode(Symbols);
|
||||||
|
|
||||||
|
else
|
||||||
|
cnt = 1;
|
||||||
|
|
||||||
|
Symbols = Symbols_tx;
|
||||||
|
|
||||||
|
coeff = [1,0.5,0.2,0.1];
|
||||||
|
|
||||||
|
Symbols.signal = filter(coeff, 1, Symbols.signal);
|
||||||
|
|
||||||
|
Symbols.spectrum("fignum",129,"displayname",['coeff:',num2str(coeff)]);
|
||||||
|
|
||||||
|
Symbols = MLSE("DIR",coeff,"duobinary_output",0,"trellis_states",Digi_Mod.levels,"M",M).process(Symbols);
|
||||||
|
|
||||||
|
Rx_bits = PAMmapper(M,0).demap(Symbols);
|
||||||
|
|
||||||
|
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
||||||
|
|
||||||
|
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
[~,error_num,ber,error_pos] = calc_ber(Tx_bits.signal,Rx_bits.signal,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
|
||||||
|
|
||||||
disp(['BER: ',sprintf('%.1E',ber),' - - PAM-',num2str(M)]);
|
|
||||||
%
|
%
|
||||||
figure;hold on
|
figure(494)
|
||||||
|
clf
|
||||||
subplot(2,1,1)
|
subplot(2,1,1)
|
||||||
title('Bits Compare')
|
title('Bits Compare')
|
||||||
|
hold on
|
||||||
stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits')
|
stairs(Rx_bits.signal(1:100,1),'LineWidth',2,'DisplayName','Rx Bits')
|
||||||
stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits');
|
stairs(Tx_bits.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Tx Bits');
|
||||||
legend
|
legend
|
||||||
subplot(2,1,2)
|
subplot(2,1,2)
|
||||||
hold on
|
hold on
|
||||||
title('Symbols Compare')
|
title('Symbols Compare')
|
||||||
stairs(Symbols.signal(1:100,1),'LineStyle',':','LineWidth',2,'DisplayName','Rx Symbols');
|
stairs(Symbols.signal(1:100,1),'LineStyle','-','LineWidth',2,'DisplayName','Rx Symbols');
|
||||||
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols')
|
stairs(Symbols_tx.signal(1:100,1),'LineWidth',2,'DisplayName','Tx Symbols','LineStyle',':')
|
||||||
legend
|
legend
|
||||||
@@ -1,36 +1,74 @@
|
|||||||
|
classdef test_modulation < matlab.unittest.TestCase
|
||||||
|
|
||||||
|
properties
|
||||||
|
Tx_bits
|
||||||
|
Digi_Mod
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
% Define method-level parameters for PRBS and bit pattern
|
||||||
|
useprbs = struct('false', 0, 'true', 1); % variations: {0, 1}
|
||||||
|
M = struct('M2', 2, 'M4', 4, 'M6', 6, 'M8', 8); % variations: {2, 4, 6, 8}
|
||||||
|
O = struct('O10', 10, 'O15', 15, 'O17', 17); % variations: {10, 15, 17}
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (TestParameter)
|
||||||
|
% Define test-level parameters for M and O
|
||||||
|
|
||||||
O = 10; %order of prbs
|
end
|
||||||
N = 2^(O-1); %length of prbs
|
|
||||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
methods (TestMethodSetup)
|
||||||
bitpattern=[];
|
|
||||||
M=6;
|
function setupModulation(testCase, useprbs, M, O)
|
||||||
|
% Setup PRBS and bit pattern for the test case using parameters
|
||||||
|
|
||||||
|
% Setup PRBS parameters
|
||||||
|
N = 2^(O-1); % Length of PRBS
|
||||||
|
randkey = 1; % Random key for random stream
|
||||||
|
|
||||||
|
[~, seed] = prbs(O, 1); % Initialize first seed of PRBS
|
||||||
|
bitpattern = [];
|
||||||
|
if useprbs
|
||||||
|
for i = 1:log2(M)
|
||||||
|
[bitpattern(:, i), seed] = prbs(O, N, seed);
|
||||||
|
end
|
||||||
|
else
|
||||||
|
s = RandStream('twister', 'Seed', randkey);
|
||||||
|
for i = 1:log2(M)
|
||||||
|
bitpattern(:, i) = randi(s, [0 1], N, 1);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if M == 6
|
||||||
|
bitpattern = reshape(bitpattern, [], 1);
|
||||||
|
bitpattern = bitpattern(1:end-mod(length(bitpattern), 5));
|
||||||
|
end
|
||||||
|
|
||||||
|
testCase.Tx_bits = Informationsignal(bitpattern);
|
||||||
|
testCase.Digi_Mod = PAMmapper(M, 0);
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test, ParameterCombination = 'sequential')
|
||||||
|
% Test with sequential combination of parameters
|
||||||
|
function testBackToBackMapping(testCase, M, useprbs, O)
|
||||||
|
% Test Bits -> Symbols -> Bits (Back-to-Back Mapping)
|
||||||
|
|
||||||
|
% Map bits to symbols
|
||||||
|
Symbols = testCase.Digi_Mod.map(testCase.Tx_bits);
|
||||||
|
|
||||||
|
% Demap symbols back to bits
|
||||||
|
Rx_bits = testCase.Digi_Mod.demap(Symbols);
|
||||||
|
|
||||||
|
% Validate BER is zero
|
||||||
|
[~, error_num, ber, ~] = calc_ber(testCase.Tx_bits.signal, Rx_bits.signal, ...
|
||||||
|
"skip_front", 0, "skip_end", 0, "returnErrorLocation", 1);
|
||||||
|
|
||||||
|
% Assert that BER is zero
|
||||||
|
testCase.verifyEqual(ber, 0, 'BER should be zero');
|
||||||
|
testCase.verifyEqual(error_num, 0, 'No errors should occur in the mapping process');
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
for i = 1:log2(M)
|
|
||||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
|
||||||
end
|
end
|
||||||
|
|
||||||
if M == 6
|
|
||||||
bitpattern = reshape(bitpattern,[],1);
|
|
||||||
end
|
|
||||||
|
|
||||||
% [bitpattern,seed] = prbs(O,N,seed);
|
|
||||||
% %
|
|
||||||
% bitpattern = bitpattern';
|
|
||||||
|
|
||||||
% 2 ) Build Inf. signal class
|
|
||||||
bits = Informationsignal(bitpattern);
|
|
||||||
|
|
||||||
|
|
||||||
% 3) Digi modulation -> PAM-M signal
|
|
||||||
digimod_out = PAMmapper(M,0).map(bits);
|
|
||||||
|
|
||||||
Rx_Bits = PAMmapper(M,0).demap(digimod_out);
|
|
||||||
|
|
||||||
[~,errors_bm,BER,errors] = calc_ber(Rx_Bits.signal,bitpattern,"skip_front",0,"skip_end",0,"returnErrorLocation",1);
|
|
||||||
|
|
||||||
formatted_ber = sprintf('%.1e', BER);
|
|
||||||
disp(['BER: ',formatted_ber]);
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user