Minimal Working - seems too good?!

This commit is contained in:
Silas Oettinghaus
2023-05-16 17:43:51 +02:00
parent 709cee9ecd
commit f5c3a1b902
23 changed files with 1476 additions and 260 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -79,7 +79,29 @@ classdef AWG
end end
function elec_out = process_channel(obj,data_in) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% 4. Apply LPF on the signal
if obj.lpf_active
lpf = Filter('filtdegree',4,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",filtertypes.bessel_inp);
signalclass_in = lpf.process(signalclass_in);
end
% cast the inform. signal to electrical signal
signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook);
% append to logbook
signalclass_in = signalclass_in.logbookentry();
% write to output
signalclass_out = signalclass_in;
end
function elec_out = process_(obj,data_in)
%METHOD1 Summary of this method goes here %METHOD1 Summary of this method goes here
% Detailed explanation goes here % Detailed explanation goes here
arguments(Input) arguments(Input)
@@ -119,13 +141,7 @@ classdef AWG
elec_out = obj.skew(elec_out); elec_out = obj.skew(elec_out);
end end
% 4. Apply LPF on the signal
if obj.lpf_active
lpf = Filter('filtdegree',4,"f_cutoff",obj.f_cutoff,"fsamp",obj.kover*obj.fdac,"filterType",filtertypes.bessel_inp);
elec_out = lpf.process(elec_out);
% obj.H_lpf = obj.buildFilter(1);
% data_out = obj.lpf(data_out) ;
end
end end

View File

@@ -53,7 +53,22 @@ classdef Amplifier
end end
function [y_out,nase] = process(obj,x_in,optional) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% append to logbook
lbdesc = ['Amp '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function [y_out,nase] = process_(obj,x_in,optional)
arguments arguments
obj obj
@@ -102,7 +117,7 @@ classdef Amplifier
end end
if ~seemsright if ~seemsright
warning("Amplifier output not correct, please check the reason"); % warning("Amplifier output not correct, please check the reason");
end end
end end

View File

@@ -64,7 +64,25 @@ classdef EML
end end
function [opt_out,obj] = process(obj,elec_in) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% cast the inform. signal to electrical signal
signalclass_in = Opticalsignal(signalclass_in,"fs",obj.fsimu,"logbook",signalclass_in.logbook,"lambda",obj.lambda*1e-9,"nase",0);
% append to logbook
lbdesc = ['EML '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function [opt_out,obj] = process_(obj,elec_in)
%METHOD1 Summary of this method goes here %METHOD1 Summary of this method goes here
% Detailed explanation goes here % Detailed explanation goes here
@@ -76,6 +94,8 @@ classdef EML
if obj.linewidth ~= 0 if obj.linewidth ~= 0
ph_noi = obj.createPhaseNoise; ph_noi = obj.createPhaseNoise;
laserfield = obj.field.*exp(1i*ph_noi); laserfield = obj.field.*exp(1i*ph_noi);
%remember phase (! you need to receive the altered eml object in you sim program !)
obj.phase = ph_noi(end);
else else
laserfield = obj.field; laserfield = obj.field;
end end
@@ -83,8 +103,7 @@ classdef EML
%modulate the laserfield with the electrical signal %modulate the laserfield with the electrical signal
opt_out = obj.externalmodulation(laserfield,elec_in); opt_out = obj.externalmodulation(laserfield,elec_in);
%remember phase (! you need to receive the altered eml object in you sim program !)
obj.phase = ph_noi(end);
end end

View File

@@ -33,9 +33,24 @@ classdef EQ
mode3rd %0: no reduction | 1: polynomial | 2: restricted to interval mode3rd %0: no reduction | 1: polynomial | 2: restricted to interval
len_3rd %length of the interval (only for 3rd order mode = 3/4) len_3rd %length of the interval (only for 3rd order mode = 3/4)
plottrain
plotfinal
load_decisions
save_taps
%during simulation %during simulation
k0 k0
b
b2
b3
e
e2
e3
coeff_number
constellation_in
end end
@@ -44,13 +59,65 @@ classdef EQ
%EQ Construct an instance of this class %EQ Construct an instance of this class
% Detailed explanation goes here % Detailed explanation goes here
arguments(Input) arguments(Input)
options options.Ne = [10 0 0] %Number of feed forward coefficients (1st, 2nd and 3rd order)
options.Nb = [10 0 0]%Number of decision feedback coefficients (1st, 2nd and 3rd order)
options.K = 1 %Number of samples per symbol
options.delay = 0 %Delay of incoming signal
options.training_length = 1024 %Number of training symbols
options.training_loops = 1 %Number of loops through sequence for training mode
options.ideal_dfe = 0 %Error free DFE decisions
options.DB_aim %Aim at duobinary output sequence
options.M = 1 %Order of the PAM constellation (only relevant in case of DB aim)
options.FFEmu = 0 %mu parameter for FFE part in training mode (0 means normalized LMS)
options.DFEmu = 0.005 % mu parameter for DFE part in training mode
options.dd_loops = 1% Number of loops through sequence for DD mode
options.DDmu = [0.0004 0.0004 0.0004 0.0004 ] % mu parameters for DD mode (individual value for each order)
options.DCmu = 0.005 % mu parameter for the dc tap
options.l1act = 0 %Activate/deactive l1 regularization
options.rho = 5e-4%Parameter for speed of coeff shrinking
options.epsilon = [10 100 1000] %Reciprocal value of the magnitude of the coeff to converge to zero (1st,2nd,3rd order)
options.thres = [5e-3 4e-3 5e-4]%Theshold for neglecting coefficienties (1st,2nd,3rd order)
options.static_act = 0 %Activate/deactive static coefficient reduction
options.mode2nd = 1%0: no reduction | 1: polynomial | 2: restricted to interval
options.len_2nd = 1 %length of the interval (only for 2nd order mode = 2)
options.mode3rd = 1%0: no reduction | 1: polynomial | 2: restricted to interval
options.len_3rd = 1%length of the interval (only for 3rd order mode = 3/4)
options.plottrain = 0
options.plotfinal = 0
options.load_decisions = 0
options.save_taps = 0
end end
% alles nochmal mappen fn = fieldnames(options);
for n = 1:numel(fn)
obj.(fn{n}) = options.(fn{n});
end end
function yout = process(obj,data_in,ref_in) end
function signalclass_out = process(obj,signalclass_in, reference_signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal', reference_signalclass_in.signal');
signalclass_in.signal = signalclass_in.signal';
% append to logbook
lbdesc = ['EQ '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function yout = process_(obj,data_in,ref_in)
%METHOD1 Summary of this method goes here %METHOD1 Summary of this method goes here
% Detailed explanation goes here % Detailed explanation goes here
@@ -141,107 +208,107 @@ classdef EQ
[ind_mat_DFE_2nd,ind_mat_DFE_3rd] = obj.calc_DFE_ind(obj.Nb(2),Nb2,obj.Nb(3),Nb3); [ind_mat_DFE_2nd,ind_mat_DFE_3rd] = obj.calc_DFE_ind(obj.Nb(2),Nb2,obj.Nb(3),Nb3);
if obj.l1act if obj.l1act
epsilon = diag([ones(1,obj.Ne(1))*obj.epsilon(1) ones(1,N2)*obj.epsilon(2) ones(1,N3)*obj.epsilon(3)]); epsilon_ = diag([ones(1,obj.Ne(1))*obj.epsilon(1) ones(1,N2)*obj.epsilon(2) ones(1,N3)*obj.epsilon(3)]);
end end
obj.k0 = obj.delay; % input delay compared to training sequence obj.k0 = obj.delay; % input delay compared to training sequence
if 1 % obj.active if 1 % obj.active
%% Calculation of the filter coefficients in training based LMS mode %% Calculation of the filter coefficients in training based LMS mode
e = zeros(obj.Ne(1)+N2+N3,1); % initialization of filter coefficients e_ = zeros(obj.Ne(1)+N2+N3,1); % initialization of filter coefficients
% e(ceil(obj.Ne(1)/2)) = 1; % set central tap to 1 (better starting point since it's closer to the expected solution) % e(ceil(obj.Ne(1)/2)) = 1; % set central tap to 1 (better starting point since it's closer to the expected solution)
b = zeros(obj.Nb(1)+Nb2+Nb3,1); b_ = zeros(obj.Nb(1)+Nb2+Nb3,1);
e_dc = mean(data_in); % initilaization of the dc tap with the mean value of the data e_dc = mean(data_in); % initilaization of the dc tap with the mean value of the data
% e_save = NaN(361,8.6e5); % e_save = NaN(361,8.6e5);
% save_ind = 1; % save_ind = 1;
for trainloops = 1:obj.training_loops for trainloops = 1:obj.training_loops
m = state.k0+1; % starting symbol index at the delay compared to the training sequence m = obj.k0+1; % starting symbol index at the delay compared to the training sequence
for n = obj.K*state.k0+1:obj.K:obj.K*obj.training_length for n = obj.K*obj.k0+1:obj.K:obj.K*obj.training_length
m = m+1; m = m+1;
X_1 = data(obj.Ne(1)+n+(obj.K-1):-1:n+obj.K).'; X_1 = data(obj.Ne(1)+n+(obj.K-1):-1:n+obj.K).';
[X_2,X_3] = calc_nl_vecs(X_1,ind_mat_2nd,ind_mat_3rd,norm_fac2,norm_fac3,delta_2,delta_3,cplx); [X_2,X_3] = obj.calc_nl_vecs(X_1,ind_mat_2nd,ind_mat_3rd,norm_fac2,norm_fac3,delta_2,delta_3,cplx);
D_1 = ref(obj.Nb(1)-state.k0+m-2:-1:m-state.k0-1).'; D_1 = ref(obj.Nb(1)-obj.k0+m-2:-1:m-obj.k0-1).';
[D_2,D_3] = calc_nl_vecs(D_1,ind_mat_DFE_2nd,ind_mat_DFE_3rd,norm_fac_DFE2,norm_fac_DFE3,delta_DFE2,delta_DFE3,cplx); [D_2,D_3] = obj.calc_nl_vecs(D_1,ind_mat_DFE_2nd,ind_mat_DFE_3rd,norm_fac_DFE2,norm_fac_DFE3,delta_DFE2,delta_DFE3,cplx);
input_vec = [X_1;X_2;X_3]; input_vec = [X_1;X_2;X_3];
reference_vec = [D_1;D_2;D_3]; reference_vec = [D_1;D_2;D_3];
error = e_dc + e.'*input_vec - b.'*reference_vec - ref_in(m-state.k0); % error = e_dc + e.'*input_vec - b.'*reference_vec - ref_in(m-state.k0); error = e_dc + e_.'*input_vec - b_.'*reference_vec - ref_in(m-obj.k0); % error = e_dc + e.'*input_vec - b.'*reference_vec - ref_in(m-obj.k0);
if real(obj.FFEmu) if real(obj.FFEmu)
if obj.l1act if obj.l1act
sgn_e = e; sgn_e = e_;
sgn_e(e~=0) = e(e~=0)./abs(e(e~=0)); sgn_e(e_~=0) = e_(e_~=0)./abs(e_(e_~=0));
e = e - obj.rho*sgn_e./(1+epsilon*abs(e)) - error*input_vec*obj.FFEmu; e_ = e_ - obj.rho*sgn_e./(1+epsilon_*abs(e_)) - error*input_vec*obj.FFEmu;
else else
e = e - error*conj(input_vec)*obj.FFEmu; %e = e - error*conj(input_vec)*obj.FFEmu; %e = e - error*input_vec*obj.FFEmu; e_ = e_ - error*conj(input_vec)*obj.FFEmu; %e = e - error*conj(input_vec)*obj.FFEmu; %e = e - error*input_vec*obj.FFEmu;
end end
else else
if obj.l1act if obj.l1act
sgn_e = e; sgn_e = e_;
sgn_e(e~=0) = e(e~=0)./abs(e(e~=0)); sgn_e(e_~=0) = e_(e_~=0)./abs(e_(e_~=0));
e = e - obj.rho*sgn_e./(1+epsilon*abs(e)) - error*input_vec/(input_vec.'*input_vec); e_ = e_ - obj.rho*sgn_e./(1+epsilon_*abs(e_)) - error*input_vec/(input_vec.'*input_vec);
else else
e = e - error*input_vec/(input_vec.'*input_vec); e_ = e_ - error*input_vec/(input_vec.'*input_vec);
end end
end end
% e_save(:,save_ind) = e; % e_save(:,save_ind) = e;
% save_ind = save_ind+1; % save_ind = save_ind+1;
e_dc = e_dc - obj.dcmu*error; e_dc = e_dc - obj.DCmu*error;
if obj.Nb(1) > 0 if obj.Nb(1) > 0
b = b + obj.DFEmu*error*reference_vec; % Seems like normalized DFE has worse performance b_ = b_ + obj.DFEmu*error*reference_vec; % Seems like normalized DFE has worse performance
end end
end end
end end
%% %%
% Plot the intermediate coefficients after training mode % Plot the intermediate coefficients after training mode
state.b = b(1:obj.Nb(1)); obj.b = b_(1:obj.Nb(1));
state.b2 = b(obj.Nb(1)+1:obj.Nb(1)+Nb2); obj.b2 = b_(obj.Nb(1)+1:obj.Nb(1)+Nb2);
state.b3 = b(obj.Nb(1)+Nb2+1:end); obj.b3 = b_(obj.Nb(1)+Nb2+1:end);
state.e = e(1:obj.Ne(1)); obj.e = e_(1:obj.Ne(1));
state.e2 = e(obj.Ne(1)+1:obj.Ne(1)+N2); obj.e2 = e_(obj.Ne(1)+1:obj.Ne(1)+N2);
state.e3 = e(obj.Ne(1)+N2+1:end); obj.e3 = e_(obj.Ne(1)+N2+1:end);
if obj.plottrain if obj.plottrain
figure(8052) figure(8052)
subplot(2,3,1); stem(abs(state.e),'Markersize',2); subplot(2,3,1); stem(abs(obj.e),'Markersize',2);
title('FFE coeff linear') title('FFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,2); stem(state.e2,'Markersize',2); subplot(2,3,2); stem(obj.e2,'Markersize',2);
title('FFE coeff nl 2nd') title('FFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,3); stem(state.e3,'Markersize',2); subplot(2,3,3); stem(obj.e3,'Markersize',2);
title('FFE coeff nl 3rd') title('FFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,4);stem(state.b,'Markersize',2); subplot(2,3,4);stem(obj.b,'Markersize',2);
title('DFE coeff linear') title('DFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,5);stem(state.b2,'Markersize',2); subplot(2,3,5);stem(obj.b2,'Markersize',2);
title('DFE coeff nl 2nd') title('DFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,6);stem(state.b3,'Markersize',2); subplot(2,3,6);stem(obj.b3,'Markersize',2);
title('DFE coeff nl 3rd') title('DFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12) xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
set(gcf,'Position',[200 500 700 400]) set(gcf,'Position',[200 500 700 400])
end end
if obj.l1act if obj.l1act
neg_lin = find(abs(state.e) < obj.thres(1)); neg_lin = find(abs(obj.e) < obj.thres(1));
neg_2nd = find(abs(state.e2) < obj.thres(2)); neg_2nd = find(abs(obj.e2) < obj.thres(2));
neg_3rd = find(abs(state.e3) < obj.thres(3)); neg_3rd = find(abs(obj.e3) < obj.thres(3));
neg = [neg_lin;neg_2nd+obj.Ne(1);neg_3rd+obj.Ne(1)+N2]; % indices of the neglected coefficients neg = [neg_lin;neg_2nd+obj.Ne(1);neg_3rd+obj.Ne(1)+N2]; % indices of the neglected coefficients
rel_lin = find(abs(state.e) >= obj.thres(1)); rel_lin = find(abs(obj.e) >= obj.thres(1));
rel_2nd = find(abs(state.e2) >= obj.thres(2)); rel_2nd = find(abs(obj.e2) >= obj.thres(2));
rel_3rd = find(abs(state.e3) >= obj.thres(3)); rel_3rd = find(abs(obj.e3) >= obj.thres(3));
state.coeff_number = length(rel_lin)+2*length(rel_2nd)+3*length(rel_3rd); obj.coeff_number = length(rel_lin)+2*length(rel_2nd)+3*length(rel_3rd);
rel = [rel_lin;rel_2nd+obj.Ne(1);rel_3rd+obj.Ne(1)+N2]; % indices of the relevant coefficients rel = [rel_lin;rel_2nd+obj.Ne(1);rel_3rd+obj.Ne(1)+N2]; % indices of the relevant coefficients
e(neg) = 0; e_(neg) = 0;
ind_mat_2nd(neg_2nd,:) = []; ind_mat_2nd(neg_2nd,:) = [];
@@ -250,24 +317,25 @@ classdef EQ
%% decision directed mode %% decision directed mode
if ~obj.DB_aim if ~obj.DB_aim
constellation_in = unique(ref_in); % getting the symbol constellation from reference data constellation_in_ = unique(ref_in); % getting the symbol constellation from reference data
else else
if obj.M == 2 if obj.M == 2
constellation_in = [-3 -2 -1 0 1 2 3]/sqrt(5)*2; constellation_in_ = [-3 -2 -1 0 1 2 3]/sqrt(5)*2;
elseif obj.M == 2.5 elseif obj.M == 2.5
constellation_in = [-5 -4 -3 -2 -1 0 1 2 3 4 5]/sqrt(10)*2; constellation_in_ = [-5 -4 -3 -2 -1 0 1 2 3 4 5]/sqrt(10)*2;
elseif obj.M == 3 elseif obj.M == 3
constellation_in = [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]/sqrt(21)*2; constellation_in_ = [-7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7]/sqrt(21)*2;
else else
constellation_in = unique(ref_in); constellation_in_ = unique(ref_in);
end end
end end
state.constellation_in = constellation_in; obj.constellation_in = constellation_in_;
if obj.l1act if obj.l1act
coeff = [e(rel);b]; % combine FFE and DFE coefficient vectors for DD mode coeff = [e_(rel);b_]; % combine FFE and DFE coefficient vectors for DD mode
else else
coeff = [e;b]; coeff = [e_;b_];
end end
for dd_loop = 1:obj.dd_loops for dd_loop = 1:obj.dd_loops
@@ -277,20 +345,21 @@ classdef EQ
D_2 = zeros(Nb2,1); D_2 = zeros(Nb2,1);
D_3 = zeros(Nb3,1); D_3 = zeros(Nb3,1);
if all(obj.mu == obj.mu(1)) if all(obj.DDmu == obj.DDmu(1))
mu_mat = obj.mu(1); mu_mat = obj.DDmu(1);
else else
if obj.l1act if obj.l1act
mu_mat = diag([ones(1,length(rel_lin))*obj.mu(1) ones(1,length(rel_2nd))*obj.mu(2) ones(1,length(rel_3rd))*obj.mu(3) ones(1,obj.Nb)*obj.mu(4)]); mu_mat = diag([ones(1,length(rel_lin))*obj.DDmu(1) ones(1,length(rel_2nd))*obj.DDmu(2) ones(1,length(rel_3rd))*obj.DDmu(3) ones(1,obj.Nb)*obj.DDmu(4)]);
else else
mu_mat = diag([ones(1,obj.Ne(1))*obj.mu(1) ones(1,N2)*obj.mu(2) ones(1,N3)*obj.mu(3) ones(1,obj.Nb(1)+Nb2+Nb3)*obj.mu(4)]); mu_mat = diag([ones(1,obj.Ne(1))*obj.DDmu(1) ones(1,N2)*obj.DDmu(2) ones(1,N3)*obj.DDmu(3) ones(1,obj.Nb(1)+Nb2+Nb3)*obj.DDmu(4)]);
end end
end end
if obj.load_decisions if obj.load_decisions
pathn = evalin('base','modeldir'); pathn = evalin('base','modeldir');
temp = load([pathn, 'MLSE_out', '.mat']) ; temp = load([pathn, 'MLSE_out', '.mat']) ;
eval(['dd_out_vals = temp.', 'a', ';']) ; %eval(['dd_out_vals = temp.', 'a', ';']) ;
dd_out_vals=temp.a;
dd_out = zeros(size(data_in)); dd_out = zeros(size(data_in));
dd_out(1:2:length(data_in)) = dd_out_vals; dd_out(1:2:length(data_in)) = dd_out_vals;
else else
@@ -300,7 +369,7 @@ classdef EQ
for k = 1:obj.K:length(data_in) for k = 1:obj.K:length(data_in)
m=m+1; % Symbol index m=m+1; % Symbol index
X_1 = data(obj.Ne(1)+k-1:-1:k).'; X_1 = data(obj.Ne(1)+k-1:-1:k).';
[X_2,X_3] = calc_nl_vecs(X_1,ind_mat_2nd,ind_mat_3rd,norm_fac2,norm_fac3,delta_2,delta_3,cplx); [X_2,X_3] = obj.calc_nl_vecs(X_1,ind_mat_2nd,ind_mat_3rd,norm_fac2,norm_fac3,delta_2,delta_3,cplx);
if obj.l1act if obj.l1act
input_vec = [X_1(rel_lin);X_2;X_3;-dd_DFE;-D_2;-D_3]; input_vec = [X_1(rel_lin);X_2;X_3;-dd_DFE;-D_2;-D_3];
@@ -311,18 +380,18 @@ classdef EQ
output_vec(m) = e_dc + input_vec.'*coeff; output_vec(m) = e_dc + input_vec.'*coeff;
if ~obj.load_decisions if ~obj.load_decisions
[~,dd_idx] = min(abs(output_vec(m) - constellation_in)); % decision for closest constellation point [~,dd_idx] = min(abs(output_vec(m) - constellation_in_)); % decision for closest constellation point
dd_out(k) = constellation_in(dd_idx); dd_out(k) = constellation_in_(dd_idx);
end end
if obj.Nb(1) > 0 if obj.Nb(1) > 0
dd_DFE(2:end) = dd_DFE(1:end-1); dd_DFE(2:end) = dd_DFE(1:end-1);
dd_DFE(1) = dd_out(k); dd_DFE(1) = dd_out(k);
if obj.error_free && m > state.k0 if obj.ideal_dfe && m > obj.k0
dd_DFE(1) = ref_in(m-state.k0); dd_DFE(1) = ref_in(m-obj.k0);
end end
[D_2,D_3] = calc_nl_vecs(dd_DFE,ind_mat_DFE_2nd,ind_mat_DFE_3rd,norm_fac_DFE2,norm_fac_DFE3,delta_DFE2,delta_DFE3,cplx); [D_2,D_3] = obj.calc_nl_vecs(dd_DFE,ind_mat_DFE_2nd,ind_mat_DFE_3rd,norm_fac_DFE2,norm_fac_DFE3,delta_DFE2,delta_DFE3,cplx);
end end
% if dd_loop ~= 21 % if dd_loop ~= 21
error = output_vec(m) - dd_out(k); error = output_vec(m) - dd_out(k);
@@ -335,18 +404,96 @@ classdef EQ
% save_ind = save_ind+1; % save_ind = save_ind+1;
if mu_mat ~= 0 if mu_mat ~= 0
e_dc = e_dc - obj.dcmu*error; e_dc = e_dc - obj.DCmu*error;
end end
end end
end end
% shifting the output sequence by k0 symbols
yout = (circshift(output_vec.',-(obj.k0))).'; %(circshift(dd_out.',-(obj.k0))).';
e_ = coeff(1:end-obj.Nb(1)-Nb2-Nb3);
b_ = coeff(end-obj.Nb(1)-Nb2-Nb3+1:end);
if obj.l1act
obj.e = e_(1:length(rel_lin));
obj.e2 = e_(length(rel_lin)+1:length(rel_lin)+length(rel_2nd));
obj.e3 = e_(length(rel_lin)+length(rel_2nd)+1:end);
else
obj.e = e_(1:obj.Ne(1));
obj.e2 = e_(obj.Ne(1)+1:obj.Ne(1)+N2);
obj.e3 = e_(obj.Ne(1)+N2+1:end);
end
obj.b = b_(1:obj.Nb(1));
obj.b2 = b_(obj.Nb(1)+1:obj.Nb(1)+Nb2);
obj.b3 = b_(obj.Nb(1)+Nb2+1:end);
% plot the final coefficients after DD mode
if obj.plotfinal
figure(8054)
if obj.l1act
subplot(2,3,1); stem(rel_lin,obj.e,'Markersize',2);
title('FFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,2); stem(rel_2nd,obj.e2,'Markersize',2);
title('FFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,3); stem(rel_3rd,obj.e3,'Markersize',2);
title('FFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,4);stem(obj.b,'Markersize',2);
title('DFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,5);stem(obj.b2,'Markersize',2);
title('DFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,6);stem(obj.b3,'Markersize',2);
title('DFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
else
subplot(2,3,1); stem(obj.e/max(e_),'Markersize',2);
title('FFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,2); stem(obj.e2,'Markersize',2);
title('FFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,3); stem(obj.e3,'Markersize',2);
title('FFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,4);stem(obj.b,'Markersize',2);
title('DFE coeff linear')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,5);stem(obj.b2,'Markersize',2);
title('DFE coeff nl 2nd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
subplot(2,3,6);stem(obj.b3,'Markersize',2);
title('DFE coeff nl 3rd')
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
end
set(gcf,'Position',[1000 500 700 400])
end
% save frequency response to the work space
if obj.save_taps
% save the FFE coefficients to the work space
% pathn = evalin('base','modeldir');
% eval([obj.field_ffe, ' = obj.e ;']) ;
% eval([obj.field_dfe, ' = b ;']) ;
% eval(['save(''', pathn, '\',obj.filen,''', ''', obj.field_ffe,''', ''',obj.field_dfe,''') ;']) ;
save("coefficients",obj.e, obj.b);
end
else
yout = data_in;
end end
end end
function [X_2,X_3] = calc_nl_vecs(X_1,ind_mat_2,ind_mat_3,norm_fac2,norm_fac3,delta_2,delta_3,cplx) function [X_2,X_3] = calc_nl_vecs(obj,X_1,ind_mat_2,ind_mat_3,norm_fac2,norm_fac3,delta_2,delta_3,cplx)
% calculation of the vectors containing all combinations of input symbols % calculation of the vectors containing all combinations of input symbols
% of second and third order based on the linear symbols % of second and third order based on the linear symbols
@@ -370,7 +517,7 @@ classdef EQ
end end
end end
function [ind_mat_2nd,ind_mat_3rd] = calc_ind(Ne2,N2,Ne3,N3,mode2nd,mode3rd,len_2nd,len_3rd,cplx) function [ind_mat_2nd,ind_mat_3rd] = calc_ind(obj,Ne2,N2,Ne3,N3,mode2nd,mode3rd,len_2nd,len_3rd,cplx)
if Ne2 > 0 if Ne2 > 0
ind_mat_2nd = NaN(N2,2); ind_mat_2nd = NaN(N2,2);
@@ -498,7 +645,7 @@ classdef EQ
end end
function [ind_mat_2nd,ind_mat_3rd] = calc_DFE_ind(Ne2,N2,Ne3,N3) function [ind_mat_2nd,ind_mat_3rd] = calc_DFE_ind(obj,Ne2,N2,Ne3,N3)
if Ne2 > 0 if Ne2 > 0
ind_mat_2nd = NaN(N2,2); ind_mat_2nd = NaN(N2,2);

View File

@@ -3,23 +3,43 @@ classdef Electricalsignal < Signal
% Detailed explanation goes here % Detailed explanation goes here
properties properties
fs
end end
methods methods
function obj = Electricalsignal(signal) function obj = Electricalsignal(signal, options)
%ELECTRICALSIGNAL Construct an instance of this class %ELECTRICALSIGNAL Construct an instance of this class
% Detailed explanation goes here % Detailed explanation goes here
arguments
signal
options.fs
options.logbook
end
obj = obj@Signal(signal); obj = obj@Signal(signal);
fn = fieldnames(options);
for l = 1:numel(fn)
obj.(fn{l}) = options.(fn{l});
end end
function outputArg = method1(obj,inputArg)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
outputArg = obj.Property1 + inputArg;
end end
function pow = power(obj)
pow = mean(abs(obj.signal),"all") ;
end
function obj = normalize(obj)
obj.signal = obj.signal/sqrt(mean(abs(obj.signal),"all"));
end
end end
end end

View File

@@ -51,7 +51,21 @@ classdef Fiber
end end
function opt_out = process(obj,opt_in) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% append to logbook
lbdesc = ['Fiber '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function opt_out = process_(obj,opt_in)
%METHOD1 Summary of this method goes here %METHOD1 Summary of this method goes here
% Detailed explanation goes here % Detailed explanation goes here
@@ -62,7 +76,6 @@ classdef Fiber
obj.linstep = -obj.alpha_lin/2 - 2*1j*pi^2*obj.b2*faxis.^2 - 4/3*1j*pi^3*obj.b3*faxis.^3; obj.linstep = -obj.alpha_lin/2 - 2*1j*pi^2*obj.b2*faxis.^2 - 4/3*1j*pi^3*obj.b3*faxis.^3;
opt_out = obj.NLSE(opt_in); opt_out = obj.NLSE(opt_in);
%attenuate nase %attenuate nase

View File

@@ -40,7 +40,21 @@ classdef Filter
end end
function yout = process(obj,xin) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal
signalclass_in.signal = obj.process_(signalclass_in.signal);
% append to logbook
filterdesc = [num2str(obj.filtdegree),'. order ',char(obj.filterType),' filter with f_cutoff at ', num2str(obj.f_cutoff*1e-9), ' GHz.'];
signalclass_in = signalclass_in.logbookentry(filterdesc);
% write to output
signalclass_out = signalclass_in;
end
function yout = process_(obj,xin)
obj.signal_length = length(xin); obj.signal_length = length(xin);

View File

@@ -3,8 +3,8 @@ classdef Informationsignal < Signal
% Detailed explanation goes here % Detailed explanation goes here
properties properties
nase
lambda_nm
end end
methods methods
@@ -15,11 +15,18 @@ classdef Informationsignal < Signal
end end
function outputArg = method1(obj,inputArg) function pow = power(obj)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here pow = mean(abs(obj.signal),"all") ;
outputArg = obj.Property1 + inputArg;
end end
function obj = normalize(obj)
obj.signal = obj.signal/sqrt(mean(abs(obj.signal),"all"));
end
end end
end end

View File

@@ -4,24 +4,45 @@ classdef Opticalsignal < Signal
properties properties
nase nase
lambda_nm lambda
fs
end end
methods methods
function obj = Opticalsignal(signal, fsym, fsimu) function obj = Opticalsignal(signal, options)
%OPTICALSIGNAL Construct an instance of this class %OPTICALSIGNAL Construct an instance of this class
% Detailed explanation goes here % Detailed explanation goes here
obj = obj@Signal(signal, fsym, fsimu); arguments
signal
options.fs
options.logbook
options.lambda
options.nase
end
obj = obj@Signal(signal);
fn = fieldnames(options);
for l = 1:numel(fn)
obj.(fn{l}) = options.(fn{l});
end
obj.nase = 0;
obj.lambda_nm = [];
end end
function outputArg = method1(obj,inputArg)
%METHOD1 Summary of this method goes here function obj = normalize(obj)
% Detailed explanation goes here
outputArg = obj.Property1 + inputArg; obj.signal = obj.signal/sqrt(mean(abs(obj.signal).^2));
end
function pow = power(obj)
pow = mean(abs(obj.signal.^2)) ;
end end
end end
end end

183
Classes/PAMmapper.m Normal file
View File

@@ -0,0 +1,183 @@
classdef PAMmapper
%PAMMAPPER Summary of this class goes here
% Detailed explanation goes here
properties
M
unipolar
thresholds
end
methods
function obj = PAMmapper(M, unipolar)
%PAMMAPPER Construct an instance of this class
% Detailed explanation goes here
obj.M = M;
obj.unipolar = unipolar;
obj.thresholds = obj.get_demodulation_thresholds();
end
function signalclass_out = map(obj,signalclass_in)
signalclass_in.signal = obj.map_(signalclass_in.signal);
signalclass_in = signalclass_in.logbookentry();
signalclass_out = signalclass_in;
end
function signalclass_out = demap(obj,signalclass_in)
signalclass_in.signal = obj.demap_(signalclass_in.signal);
signalclass_in = signalclass_in.logbookentry();
signalclass_out = signalclass_in;
end
function pam_sig = map_(obj,bitpattern)
switch log2(obj.M)
case 1
% 2-ASK: BPSK / OOK
pam_sig=bitpattern(:,1);
if obj.unipolar==0
pam_sig=2*pam_sig-1;
end
case 2
% 4-ASK:
pam_sig=2*bitpattern(:,1)+(bitpattern(:,1)==bitpattern(:,2));
if obj.unipolar==0
pam_sig=2*pam_sig-3;
end
case 3
% 8-ASK:
x1 = bitpattern(:,1);
x2 = (bitpattern(:,1)==bitpattern(:,3));
x3 = x2~=bitpattern(:,2);
pam_sig = 4*x1 + 2*x2 + x3;
if obj.unipolar==0
pam_sig=2*pam_sig-7;
end
case 4
% 16-ASK:
x1 = bitpattern(:,1);
x2 = (bitpattern(:,1)==bitpattern(:,4));
x3 = x2~=bitpattern(:,3);
x4 = x3~=bitpattern(:,2);
pam_sig = 8*x1 + 4*x2 + 2*x3 + x4;
if obj.unipolar==0
pam_sig=2*pam_sig-15;
end
end
end
function thres = get_demodulation_thresholds(obj)
%simply get the obj.thresholdseshold values for PAM
%28.03.2023 - Silas Oett. - Extracted from digi_demod.m
%
obj.thresholds = 0;
switch log2(obj.M)
case 1
% 2-ASK
if obj.unipolar
thres=0.5;
else %bi polar
thres=0;
end
case 2
% 4-ASK
if obj.unipolar==0
thres=[-2,0,2];
elseif obj.unipolar==1
thres=[0.5,1.5,2.5];
end
case 3
% 8-ASK
if obj.unipolar==0
thres=-6:2:6;
elseif obj.unipolar==1
thres=0.5:6.5;
end
case 4
% 16-ASK
if obj.unipolar==0 && scale_mode==1
thres=-14:2:14;
elseif obj.unipolar==1 && scale_mode==1
thres=0.5:14.5;
end
end
end
function [data_out] = demap_(obj,data_in)
data_in= data_in';
% create output
if ~isempty(obj.thresholds)
a = squeeze(repmat(real(data_in),[1 1 length(obj.thresholds)])); %Eingangssignal in 3 spalten
b = squeeze(repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in) 1])); %Threshold in 3 Spalten
comp_real = a > b; %check for each symbol/ sampling if it exeeds the obj.thresholdseshold 1, 2 or 3
comp_real=repmat(real(data_in),[1 1 length(obj.thresholds)]) > repmat(reshape(obj.thresholds(:).',[1 1 length(obj.thresholds)]),[1 length(data_in) 1]);
else
comp_real=[];
end
s1=size(comp_real,1);
s2=size(comp_real,2);
switch log2(obj.M)
case 1
% 2-ASK
data_out=comp_real(:,:,1);
case 2
% 4-ASK
data_out=[comp_real(:,:,2); ones(s1,s2)-comp_real(:,:,1)+comp_real(:,:,3)];
case 3
% 8-ASK
data_out=[comp_real(:,:,4);
comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7);
1-comp_real(:,:,2)+comp_real(:,:,6)];
case 4
% 16-ASK
data_out=[comp_real(:,:,8);
comp_real(:,:,1)-comp_real(:,:,3)+comp_real(:,:,5)-comp_real(:,:,7)+comp_real(:,:,9)-comp_real(:,:,11)+comp_real(:,:,13)-comp_real(:,:,15);
comp_real(:,:,2)-comp_real(:,:,6)+comp_real(:,:,10)-comp_real(:,:,14);
1-comp_real(:,:,4)+comp_real(:,:,12)];
end
end
end
end

View File

@@ -28,7 +28,24 @@ classdef Photodiode
end end
function yout = process(obj,xin) function signalclass_out = process(obj,signalclass_in)
% actual processing of the signal (steps 1. - 3.)
signalclass_in.signal = obj.process_(signalclass_in.signal);
% cast the inform. signal to electrical signal
[signalclass_in, nase, lambda] = Electricalsignal(signalclass_in,"fs",obj.fsimu,"logbook",signalclass_in.logbook);
% append to logbook
lbdesc = ['Photo Diode '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function yout = process_(obj,xin)
%METHOD1 Summary of this method goes here %METHOD1 Summary of this method goes here
% Detailed explanation goes here % Detailed explanation goes here

View File

@@ -68,18 +68,32 @@ classdef Scope
end end
function yout = process(obj,xin) function signalclass_out = process(obj,signalclass_in)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
% apply LPF % apply LPF
lpf = Filter('filtdegree',4,"f_cutoff",obj.lpf_bw,"fsamp",obj.fsimu,"filterType",obj.filtertype); lpf = Filter('filtdegree',4,"f_cutoff",obj.lpf_bw,"fsamp",obj.fsimu,"filterType",obj.filtertype);
yout = lpf.process(xin); signalclass_in = lpf.process(signalclass_in);
% actual processing of the signal
signalclass_in.signal = obj.process_(signalclass_in.signal);
% append to logbook
lbdesc = ['Scope '];
signalclass_in = signalclass_in.logbookentry(lbdesc);
% write to output
signalclass_out = signalclass_in;
end
function yout = process_(obj,xin)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
% sample signal % sample signal
% TODO: implement and test the delays. Also look for delay of % TODO: implement and test the delays. Also look for delay of
% lpf filter % lpf filter
yout = obj.sampleSignal(yout); yout = obj.sampleSignal(xin);
% quantize signal % quantize signal
yout = obj.quantize(yout); yout = obj.quantize(yout);

View File

@@ -4,8 +4,7 @@ classdef Signal
properties properties
signal signal
fsym logbook
fsimu
end end
methods methods
@@ -14,34 +13,140 @@ classdef Signal
% Detailed explanation goes here % Detailed explanation goes here
obj.signal = signal; obj.signal = signal;
obj.fsym = 0; SignalType = [];
TimeStamp = [];
Length = [];
SignalPower = [];
Nase = [];
Description = [];
obj.fsimu = 0; obj.logbook = table(SignalType,TimeStamp,Length,SignalPower,Nase,Description);
end end
function [e_sig, nase, lambda_nm] = Electricalsignal(obj) function [i_sig, varargout] = Informationsignal(obj)
if isa(obj,'Electricalsignal')
%convert to optical
disp("Convert signal: elec. -> info.!");
varargout{1} = obj.fs;
i_sig = Informationsignal(obj.signal);
elseif isa(obj,'Opticalsignal')
error("Cannot convert from optical- to informationsignal. Use O/E conversion first.");
end
end
function [e_sig, varargout] = Electricalsignal(obj,options)
arguments
obj
options.fs
options.logbook
end
obj.logbook = options.logbook;
if isa(obj,'Opticalsignal') if isa(obj,'Opticalsignal')
%convert to electrical %convert to electrical
disp("Convert signal: opt. -> elec. Fetch all properties (e.g. nase)!"); disp("Convert signal: opt. -> elec. Fetch all properties (e.g. nase)!");
nase = obj.nase; varargout{1} = obj.nase;
lambda_nm = obj.lambda_nm; varargout{2} = obj.lambda;
e_sig = Electricalsignal(obj.signal,obj.fsym, obj.fsimu); e_sig = Electricalsignal(obj.signal,"fs",obj.fs,"logbook",obj.logbook);
elseif isa(obj,'Informationsignal')
try
% specify fs at varargin{1}
e_sig = Electricalsignal(obj.signal,"fs",options.fs,"logbook",options.logbook);
catch
error("Signal Conversion failed [I -> E] ");
end end
end end
function o_sig = Opticalsignal(obj) end
function o_sig = Opticalsignal(obj, options)
arguments
obj
options.fs
options.logbook
options.nase
options.lambda
end
fn = fieldnames(options);
for l = 1:numel(fn)
try
obj.(fn{l}) = options.(fn{l});
end
end
if isa(obj,'Electricalsignal') if isa(obj,'Electricalsignal')
%convert to optical %convert to optical
disp("Convert signal: elec. -> opt.!"); disp("Convert signal: elec. -> opt.!");
o_sig = Opticalsignal(obj.signal,obj.fsym, obj.fsimu);
end o_sig = Opticalsignal(obj.signal,"fs",obj.fs,"lambda",options.lambda,"logbook",obj.logbook,"nase",options.nase);
elseif isa(obj,'Informationsignal')
error("Cannot convert from information- to opticalsignal. Use E/O conversion first.");
end end
function normalizedsignal = signal_(obj) end
normalizedsignal = obj.signal / norm(obj.signal);
function return_length = length(obj)
%METHOD1 Summary of this method goes here
% Detailed explanation goes here
return_length = length(obj.signal);
end
function obj = logbookentry(obj,varargin)
if nargin > 1
Description = varargin{1};
else
Description = "";
end
SignalType = [string(class(obj))];
TimeStamp = [(datetime('now','TimeZone','local','Format','HH:mm:ss'))];
Length = [obj.length];
SignalPower = [obj.power];
Nase = [0];
cell = {SignalType , TimeStamp , Length , SignalPower , Nase, Description};
obj.logbook = [obj.logbook;cell];
end
function obj = resample(obj,options)
arguments
obj Signal
options.fs_in double
options.fs_out double
end
obj.signal = resample(obj.signal,options.fs_out,options.fs_in);
desc = ['resample signal from ', num2str(options.fs_in*1e-9), ' GHz to ', num2str(options.fs_out*1e-9), ' GHz' ];
obj = obj.logbookentry(desc);
end end
end end

BIN
Functions/.DS_Store vendored Normal file

Binary file not shown.

11
Functions/settingsdlg/.gitignore vendored Normal file
View File

@@ -0,0 +1,11 @@
slprj/
*.mexw32
*.mexglx
*.mexmaci
*.mexw64
*.mexmaci64
*.mexa64
*.zip
*.m~
*.asv

View File

@@ -0,0 +1,26 @@
Copyright (c) 2018, Rody Oldenhuis
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
The views and conclusions contained in the software and documentation are those
of the authors and should not be interpreted as representing official policies,
either expressed or implied, of this project.

View File

@@ -0,0 +1,114 @@
[![View Settings dialog on File Exchange](https://www.mathworks.com/matlabcentral/images/matlab-file-exchange.svg)](https://www.mathworks.com/matlabcentral/fileexchange/26312-settings-dialog)
[![Donate to Rody](https://i.stack.imgur.com/bneea.png)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4M7RMVNMKAXXQ&source=url)
# FEX-settingsdlg
The function settingsdlg() is a GUI-dialog much like MATLAB's default errordlg(), questiondlg() and warndlg(), which provides a standardized way to assign specific values to a structure. This structure can then be used to insert specific settings
into one of MATLAB's many standard algorithms, or your own. The most basic usage is as follows:
[ settings, button] = settingsdlg(...
'TolX' , 1e-6,...
'TolFun', 1e-6);
which will produce a nice dialog box with the fields and edit boxes as you'd expect them. After pressing OK or Cancel, the structure settings will be
settings =
TolX: 1.0000e-006
TolFun: 1.0000e-006
button =
'ok'
or any relevant values you have assigned. Naturally, you can add as many fields as you want; the dialog will automatically adjust its size to match your input. If you would like the user to not just insert numeric values, but select values from a
string list, use
settings = settingsdlg(...
'TolX' , 1e-6,...
'TolFun' , 1e-6,...
'Algorithm', {'active-set','interior-point'});
which will produce the same dialog, with a popup-list added. The resulting structure in this case is:
settings =
TolX: 1.0000e-006
TolFun: 1.0000e-006
Algorithm: 'active-set'
Of course, it isn't always convenient to have the text for each option in the dialog box equal to the fieldname in the resulting structure. If you want the fieldname to be different from the displayed string, you can use something like:
settings = settingsdlg(...
{'Tolerance X' ;'TolX' }, 1e-6,...
{'Tolerance Fun';'TolFun'}, 1e-6,...
'Algorithm', {'active-set','interior-point'});
which produces the dialog displaying the *first* entries in the cell-arrays, but the associated structure has the fieldnames
settings =
TolX: 1.0000e-006
TolFun: 1.0000e-006
Algorithm: 'active-set'
Also, you can add separators, a different dialog title, and a brief description:
settings = settingsdlg(...
'Description', 'This dialog will set the parameters used by FMINCON()',...
'title' , 'FMINCON() options',...
'separator' , 'Unconstrained/General',...
{'Tolerance X' ;'TolX' }, 1e-6,...
{'Tolerance on Function';'TolFun'}, 1e-6,...
'Algorithm' , {'active-set','interior-point'},...
'separator' , 'Constrained',...
{'Tolerance on Constraint';'TolCon'}, 1e-6);
The 'title' and 'description' options can appear anywhere in the argument list, they will not affect the fields in the output structure. The order of the 'separator' option of course *does* matter, but, it will *not* be added as a field to the output structure. You can also use logicals, which produce checkboxes:
settings = settingsdlg(...
'Description', 'This dialog will set the parameters used by FMINCON()',...
'title' , 'FMINCON() options',...
'separator' , 'Unconstrained/General',...
{'Tolerance X';'TolX'}, 1e-6,...
{'Tolerance on Function';'TolFun'}, 1e-6,...
'Algorithm' , {'active-set','interior-point'},...
'separator' , 'Constrained',...
{'This is a checkbox'; 'Check'}, true,...
{'Tolerance on Constraints';'TolCon'}, 1e-6);
which results in
settings =
TolX: 1.0000e-006
TolFun: 1.0000e-006
Algorithm: 'active-set'
Check: 1
TolCon: 1.0000e-006
You can also assign multiple (logical!) values to a single checkbox, in which case the fields below the checkbox are all disabled/enabled when you check it:
settings = settingsdlg(...
'Description', 'This dialog will set the parameters used by FMINCON()',...
'title' , 'FMINCON() options',...
'separator' , 'Unconstrained/General',...
{'This is a checkbox'; 'Check'}, [true, true],...
{'Tolerance X';'TolX'}, 1e-6,...
{'Tolerance on Function';'TolFun'}, 1e-6,...
'Algorithm' , {'active-set','interior-point'},...
'separator' , 'Constrained',...
{'Tolerance on Constraints';'TolCon'}, 1e-6);
Setting the checkbox value to [true, true] will cause the dialog box to appear with all fields below the appropriate separator disabled, whereas a value of [true, false] will have all fields initially enabled. Checking or un-checking the checkbox will simply swap the enabled/disabled states.
Finally, you can insert a single structure as a (single!) argument, which produces a dialog box according to its settings and fieldnames:
settings = struct(...
'TolX' , 1e-6,...
'TolFun', 1e-6);
settings = settingsdlg(settings);
Naturally, since all other information is absent in this last example, the functionality in this case is rather limited. But if the intent is to change a fairly simple structure, it certainly suffices.
If you like this work, please consider [a donation](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4M7RMVNMKAXXQ&source=url).

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@@ -0,0 +1,488 @@
function [settings, button] = settingsdlg(varargin)
% SETTINGSDLG Default dialog to produce a settings-structure
%
% settings = SETTINGSDLG('fieldname', default_value, ...) creates a modal
% dialog box that returns a structure formed according to user input. The
% input should be given in the form of 'fieldname', default_value - pairs,
% where 'fieldname' is the fieldname in the structure [settings], and
% default_value the initial value displayed in the dialog box.
%
% SETTINGSDLG uses UIWAIT to suspend execution until the user responds.
%
% settings = SETTINGSDLG(settings) uses the structure [settings] to form
% the various input fields. This is the most basic (and limited) usage of
% SETTINGSDLG.
%
% [settings, button] = SETTINGSDLG(settings) returns which button was
% pressed, in addition to the (modified) structure [settings]. Either 'ok',
% 'cancel' or [] are possible values. The empty output means that the
% dialog was closed before either Cancel or OK were pressed.
%
% SETTINGSDLG('title', 'window_title') uses 'window_title' as the dialog's
% title. The default is 'Adjust settings'.
%
% SETTINGSDLG('description', 'brief_description',...) starts the dialog box
% with 'brief_description', followed by the input fields.
%
% SETTINGSDLG('windowposition', P, ...) positions the dialog box according to
% the string or vector [P]; see movegui() for valid values.
%
% SETTINGSDLG( {'display_string', 'fieldname'}, default_value,...) uses the
% 'display_string' in the dialog box, while assigning the corresponding
% user-input to fieldname 'fieldname'.
%
% SETTINGSDLG(..., 'checkbox_string', true, ...) displays a checkbox in
% stead of the default edit box, and SETTINGSDLG('fieldname', {'string1',
% 'string2'},... ) displays a popup box with the strings given in
% the second cell-array.
%
% Additionally, you can put [..., 'separator', 'seperator_string',...]
% anywhere in the argument list, which will divide all the arguments into
% sections, with section headings 'seperator_string'.
%
% You can also modify the display behavior in the case of checkboxes. When
% defining checkboxes with a 2-element logical array, the second boolean
% determines whether all fields below that checkbox are initially disabled
% (true) or not (false).
%
% Example:
%
% [settings, button] = settingsdlg(...
% 'Description', 'This dialog will set the parameters used by FMINCON()',...
% 'title' , 'FMINCON() options',...
% 'separator' , 'Unconstrained/General',...
% {'This is a checkbox'; 'Check'}, [true true],...
% {'Tolerance X';'TolX'}, 1e-6,...
% {'Tolerance on Function';'TolFun'}, 1e-6,...
% 'Algorithm' , {'active-set','interior-point'},...
% 'separator' , 'Constrained',...
% {'Tolerance on Constraints';'TolCon'}, 1e-6)
%
% See also inputdlg, dialog, errordlg, helpdlg, listdlg, msgbox, questdlg, textwrap,
% uiwait, warndlg.
% Please report bugs and inquiries to:
%
% Name : Rody P.S. Oldenhuis
% E-mail : oldenhuis@gmail.com
% Licence: 2-clause BSD (See Licence.txt)
% If you find this work useful, please consider a donation:
% https://www.paypal.me/RodyO/3.5
%% Initialize
% errortraps
narg = nargin;
if verLessThan('MATLAB', '8.6')
error(nargchk(1, inf, narg, 'struct')); %#ok<NCHKN>
else
narginchk(1, inf);
end
% parse input (+errortrap)
have_settings = 0;
if isstruct(varargin{1})
settings = varargin{1}; have_settings = 1; end
if (narg == 1)
if isstruct(varargin{1})
parameters = fieldnames(settings);
values = cellfun(@(x)settings.(x), parameters, 'UniformOutput', false);
else
error('settingsdlg:incorrect_input',...
'When pasing a single argument, that argument must be a structure.')
end
else
parameters = varargin(1+have_settings : 2 : end);
values = varargin(2+have_settings : 2 : end);
end
% Initialize data
button = [];
fields = cell(numel(parameters),1);
tags = fields;
% Fill [settings] with default values & collect data
for ii = 1:numel(parameters)
% Extract fields & tags
if iscell(parameters{ii})
tags{ii} = parameters{ii}{1};
fields{ii} = parameters{ii}{2};
else
% More errortraps
if ~ischar(parameters{ii})
error('settingsdlg:nonstring_parameter',...
'Arguments should be given as [''parameter'', value,...] pairs.')
end
tags{ii} = parameters{ii};
fields{ii} = parameters{ii};
end
% More errortraps
if ~ischar(fields{ii})
error('settingsdlg:fieldname_not_char',...
'Fieldname should be a string.')
end
if ~ischar(tags{ii})
error('settingsdlg:tag_not_char',...
'Display name should be a string.')
end
% NOTE: 'Separator' is now in 'fields' even though
% it will not be used as a fieldname
% Make sure all fieldnames are properly formatted
% (alternating capitals, no whitespace)
if ~strcmpi(fields{ii}, {'Separator';'Title';'Description'})
whitespace = isspace(fields{ii});
capitalize = circshift(whitespace,[0,1]);
fields{ii}(capitalize) = upper(fields{ii}(capitalize));
fields{ii} = fields{ii}(~whitespace);
% insert associated value in output
if iscell(values{ii})
settings.(fields{ii}) = values{ii}{1};
elseif (length(values{ii}) > 1)
settings.(fields{ii}) = values{ii}(1);
else
settings.(fields{ii}) = values{ii};
end
end
end
% Avoid (some) confusion
clear parameters
% Use default colorscheme from the OS
bgcolor = get(0, 'defaultUicontrolBackgroundColor');
% Default fontsize
fontsize = get(0, 'defaultuicontrolfontsize');
% Edit-bgcolor is platform-dependent.
% MS/Windows: white.
% UNIX: same as figure bgcolor
% if ispc, edit_bgcolor = 'White';
% else edit_bgcolor = bgcolor;
% end
% TODO: not really applicable since defaultUicontrolBackgroundColor
% doesn't really seem to work on Unix...
edit_bgcolor = 'White';
% Get basic window properties
title = getValue('Adjust settings', 'Title');
description = getValue( [], 'Description');
total_width = getValue(325, 'WindowWidth');
control_width = getValue(100, 'ControlWidth');
% Window positioning:
% Put the window in the center of the screen by default.
% This will usually work fine, except on some multi-monitor setups.
scz = get(0, 'ScreenSize');
scxy = round(scz(3:4)/2-control_width/2);
scx = min(scz(3),max(1,scxy(1)));
scy = min(scz(4),max(1,scxy(2)));
% String to pass on to movegui
window_position = getValue('center', 'WindowPosition');
% Calculate best height for all uicontrol()
control_height = max(18, (fontsize+6));
% Calculate figure height (will be adjusted later according to description)
total_height = numel(fields)*1.25*control_height + ... % to fit all controls
1.5*control_height + 20; % to fit "OK" and "Cancel" buttons
% Total number of separators
num_separators = nnz(strcmpi(fields,'Separator'));
% Draw figure in background
fighandle = figure(...
'integerhandle' , 'off',... % use non-integers for the handle (prevents accidental plots from going to the dialog)
'Handlevisibility', 'off',... % only visible from within this function
'position' , [scx, scy, total_width, total_height],...% figure position
'visible' , 'off',... % hide the dialog while it is being constructed
'backingstore' , 'off',... % DON'T save a copy in the background
'resize' , 'off', ... % but just keep it resizable
'renderer' , 'zbuffer', ... % best choice for speed vs. compatibility
'WindowStyle' ,'modal',... % window is modal
'units' , 'pixels',... % better for drawing
'DockControls' , 'off',... % force it to be non-dockable
'name' , title,... % dialog title
'menubar' ,'none', ... % no menubar of course
'toolbar' ,'none', ... % no toolbar
'NumberTitle' , 'off',... % "Figure 1.4728...:" just looks corny
'color' , bgcolor); % use default colorscheme
%% Draw all required uicontrols(), and unhide window
% Define X-offsets (different when separators are used)
separator_offset_X = 2;
if num_separators > 0
text_offset_X = 20;
text_width = (total_width-control_width-text_offset_X);
else
text_offset_X = separator_offset_X;
text_width = (total_width-control_width);
end
% Handle description
description_offset = 0;
if ~isempty(description)
% create textfield (negligible height initially)
description_panel = uicontrol(...
'parent' , fighandle,...
'style' , 'text',...
'Horizontalalignment', 'left',...
'position', [separator_offset_X,...
total_height,total_width,1]);
% wrap the description
description = textwrap(description_panel, {description});
% adjust the height of the figure
textheight = size(description,1)*(fontsize+6);
description_offset = textheight + 20;
total_height = total_height + description_offset;
set(fighandle,...
'position', [scx, scy, total_width, total_height])
% adjust the position of the textfield and insert the description
set(description_panel, ...
'string' , description,...
'position', [separator_offset_X, total_height-textheight, ...
total_width, textheight]);
end
% Define Y-offsets (different when descriptions are used)
control_offset_Y = total_height-control_height-description_offset;
% initialize loop
controls = zeros(numel(tags)-num_separators,1);
ii = 1; sep_ind = 1;
enable = 'on'; separators = zeros(num_separators,1);
% loop through the controls
if numel(tags) > 0
while true
% Should we draw a separator?
if strcmpi(tags{ii}, 'Separator')
% Print separator
uicontrol(...
'style' , 'text',...
'parent' , fighandle,...
'string' , values{ii},...
'horizontalalignment', 'left',...
'fontweight', 'bold',...
'position', [separator_offset_X,control_offset_Y-4, ...
total_width, control_height]);
% remove separator, but save its position
fields(ii) = [];
tags(ii) = []; separators(sep_ind) = ii;
values(ii) = []; sep_ind = sep_ind + 1;
% reset enable (when neccessary)
if strcmpi(enable, 'off')
enable = 'on'; end
% NOTE: DON'T increase loop index
% ... or a setting?
else
% logicals: use checkbox
if islogical(values{ii})
% First draw control
controls(ii) = uicontrol(...
'style' , 'checkbox',...
'parent' , fighandle,...
'enable' , enable,...
'string' , tags{ii},...
'value' , values{ii}(1),...
'position', [text_offset_X,control_offset_Y-4, ...
total_width, control_height]);
% Should everything below here be OFF?
if (length(values{ii})>1)
% turn next controls off when asked for
if values{ii}(2)
enable = 'off'; end
% Turn on callback function
set(controls(ii),...
'Callback', @(varargin) EnableDisable(ii,varargin{:}));
end
% doubles : use edit box
% cells : use popup
% cell-of-cells: use table
else
% First print parameter
uicontrol(...
'style' , 'text',...
'parent' , fighandle,...
'string' , [tags{ii}, ':'],...
'horizontalalignment', 'left',...
'position', [text_offset_X,control_offset_Y-4, ...
text_width, control_height]);
% Popup, edit box or table?
style = 'edit';
draw_table = false;
if iscell(values{ii})
style = 'popup';
if all(cellfun('isclass', values{ii}, 'cell'))
draw_table = true; end
end
% Draw appropriate control
if ~draw_table
controls(ii) = uicontrol(...
'enable' , enable,...
'style' , style,...
'Background', edit_bgcolor,...
'parent' , fighandle,...
'string' , values{ii},...
'position', [text_width,control_offset_Y,...
control_width, control_height]);
else
% TODO
% ...table? ...radio buttons? How to do this?
warning(...
'settingsdlg:not_yet_implemented',...
'Treatment of cells is not yet implemented.');
end
end
% increase loop index
ii = ii + 1;
end
% end loop?
if ii > numel(tags)
break, end
% Decrease offset
control_offset_Y = control_offset_Y - 1.25*control_height;
end
end
% Draw cancel button
uicontrol(...
'style' , 'pushbutton',...
'parent' , fighandle,...
'string' , 'Cancel',...
'position', [separator_offset_X,2, total_width/2.5,control_height*1.5],...
'Callback', @Cancel)
% Draw OK button
uicontrol(...
'style' , 'pushbutton',...
'parent' , fighandle,...
'string' , 'OK',...
'position', [total_width*(1-1/2.5)-separator_offset_X,2, ...
total_width/2.5,control_height*1.5],...
'Callback', @OK)
% move to center of screen and make visible
movegui(fighandle, window_position);
set(fighandle, 'Visible', 'on');
% WAIT until OK/Cancel is pressed
uiwait(fighandle);
%% Helper funcitons
% Get a value from the values array:
% - if it does not exist, return the default value
% - if it exists, assign it and delete the appropriate entries from the
% data arrays
function val = getValue(default, tag)
index = strcmpi(fields, tag);
if any(index)
val = values{index};
values(index) = [];
fields(index) = [];
tags(index) = [];
else
val = default;
end
end
%% callback functions
% Enable/disable controls associated with (some) checkboxes
function EnableDisable(which, varargin) %#ok<VANUS>
% find proper range of controls to switch
if (num_separators > 1)
range = (which+1):(separators(separators > which)-1);
else range = (which+1):numel(controls);
end
% enable/disable these controls
if strcmpi(get(controls(range(1)), 'enable'), 'off')
set(controls(range), 'enable', 'on')
else
set(controls(range), 'enable', 'off')
end
end
% OK button:
% - update fields in [settings]
% - assign [button] output argument ('ok')
% - kill window
function OK(varargin) %#ok<VANUS>
% button pressed
button = 'OK';
% fill settings
for i = 1:numel(controls)
% extract current control's string, value & type
str = get(controls(i), 'string');
val = get(controls(i), 'value');
style = get(controls(i), 'style');
% popups/edits
if ~strcmpi(style, 'checkbox')
% extract correct string (popups only)
if strcmpi(style, 'popupmenu'), str = str{val}; end
% try to convert string to double
val = str2double(str);
% insert this double in [settings]. If it was not a
% double, insert string instead
if ~isnan(val), settings.(fields{i}) = val;
else settings.(fields{i}) = str;
end
% checkboxes
else
% we can insert value immediately
settings.(fields{i}) = val;
end
end
% kill window
delete(fighandle);
end
% Cancel button:
% - assign [button] output argument ('cancel')
% - delete figure (so: return default settings)
function Cancel(varargin) %#ok<VANUS>
button = 'cancel';
delete(fighandle);
end
end

Binary file not shown.

Binary file not shown.

194
comm_tb.m
View File

@@ -1,9 +1,11 @@
O = 14; %order of prbs clear all
O = 17; %order of prbs
N = 2^(O-1); %length of prbs N = 2^(O-1); %length of prbs
[~,seed] = prbs(O,1); %initialize first seed of prbs [~,seed] = prbs(O,1); %initialize first seed of prbs
% Modulation % Modulation
M = 4; M = 4; %PAM-M
bitpattern = zeros(N,log2(M)); bitpattern = zeros(N,log2(M));
% Symbol Rate % Symbol Rate
@@ -17,136 +19,90 @@ fadc = 256e9;
% Simulation frequency in "analog domain" % Simulation frequency in "analog domain"
fsimu = kover * fdac ; fsimu = kover * fdac ;
%SIMULATE [settings, button] = settingsdlg(...
'Description' , ['This dialog will set the ', ...
'parameters used by FMINCON()'], ...
'title' , 'FMINCON() options', ...
'separator' , 'Unconstrained/General', ...
{'This is a checkbox'; 'Check'} , [false, false],...
{'Tolerance X';'TolX'} , 1e-6, ...
{'Tolerance on Function';'TolFun'} , 1e-6, ...
'Algorithm' , {'active-set','interior-point'}, ...
'separator' , 'Constrained', ...
{'Tolerance on Constraints';'TolCon'}, 1e-6);
for i = 1:log2(M) %CONSTRUCTION
[bitpattern(:,i),seed] = prbs(O,N,seed); pam_mapper = PAMmapper(M,0);
end
Bits = Informationsignal(bitpattern); awg = AWG('preset','M8196A','fdac',fdac,'kover',kover,'lpf_active',0);
Bits.signal = pam_mapping(Bits.signal,M,0); fil_tx = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac,"filterType",filtertypes.bessel_bilin);
Bits.signal = applyPulseShaping(Bits.signal,fsym,fdac);
awg = AWG('preset','M8196A','fdac',fdac,'kover',kover,'lpf_active',1);
awgSignal = awg.process_channel(Bits.signal);
fil = Filter('filtdegree',4,"f_cutoff",50e9,"fsamp",fdac,"filterType",filtertypes.bessel_bilin);
filtered = fil.process(awgSignal);
u_pi = 3.5; u_pi = 3.5;
vbias = (0.5*u_pi)-u_pi; vbias = (0.5*u_pi)-u_pi;
extmodlaser = EML("mode",emlmodes.im_cosinus,"power",10,"fsimu",fsimu,"lambda",1550,"bias",vbias,"u_pi",u_pi,"linewidth",1000000); extmodlaser = EML("mode",emlmodes.im_cosinus,"power",10,"fsimu",fsimu,"lambda",1550,"bias",vbias,"u_pi",u_pi,"linewidth",0);
laserfield = extmodlaser.process(filtered);
att = Amplifier("amplification_db",10,"amp_mode","gain","type","ideal","saturation_mode",0,'saturation_power',10); amp = Amplifier("amplification_db",10,"amp_mode","gain","type","ideal","saturation_mode",0,'saturation_power',10);
att_out = att.process(laserfield);
fib = Fiber("fsimu",fdac*kover,"fiber_length",0,"alpha",0.2,"D",17,"lambda0",1550); fib = Fiber("fsimu",fdac*kover,"fiber_length",2,"alpha",0.2,"D",17,"lambda0",1550);
fib_out = fib.process(att_out);
phdiode = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20); phdiode = Photodiode("fsimu",fdac*kover,"dark_current",2e-08,"responsivity",1,"temperature",20);
phdiod_out = phdiode.process(fib_out);
fil = Filter('filtdegree',4,"f_cutoff",70e9,"fsamp",fdac,"filterType",filtertypes.bessel_bilin);
phdiod_out2 = fil.process(phdiod_out);
fil_diode = Filter('filtdegree',4,"f_cutoff",70e9,"fsamp",fdac,"filterType",filtertypes.bessel_bilin);
scp = Scope("fsimu",fdac*kover,"fadc",fadc,... scp = Scope("fsimu",fdac*kover,"fadc",fadc,...
"delay",0,"fixed_delay",0,"lpf_bw",120e9,"filtertype",filtertypes.bessel_inp,... "delay",0,"fixed_delay",0,"lpf_bw",120e9,"filtertype",filtertypes.bessel_inp,...
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,... "samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
"adcresolution",6,"quantbuffer",0.1); "adcresolution",6,"quantbuffer",0.1);
scope_out = scp.process(phdiod_out2); eq = EQ("K",2,"plottrain",0,"plotfinal",1,"training_length",2048,"Ne",[25,5,5],"Nb",[2,0,0],"training_loops",5,"DCmu",0.005,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"thres",[0.005 0.004 0.0005 ]);
resample_out = resample(scope_out,fsym,fadc); %SIMULATE
% INFORMATION SIGNAL
for i = 1:log2(M)
[bitpattern(:,i),seed] = prbs(O,N,seed);
figure;
hold on
plot( nmlze(resample(shapedData,fadc,fdac)),'DisplayName','shapedData Data');
plot( nmlze(resample(awgSignal,fadc,fdac*kover)),'DisplayName','AWG Data');
plot( nmlze(scope_out),'DisplayName','scope out out');
hold off
% figure;
% hold on
% plot(awgSignal,'DisplayName','skew 0');
% plot(filtered,'DisplayName','filtered');
% plot(abs(laserfield),'DisplayName','laser');
% plot(abs(att_out),'DisplayName','att_out');
% plot(abs(fib_out),'DisplayName','fiber_out');
% plot(abs(phdiod_out),'DisplayName','photo diode out');
% hold off
% figure;
% hold on
% plot(nmlze(pamData),'DisplayName','PAM Data');
% plot(nmlze(resample_out),'DisplayName','system out');
% hold off
function y = nmlze(x)
y = (x-min(x)) / max((x-min(x)));
end end
function pam_sig = pam_mapping(bitpattern, M, unipolar) X = Informationsignal(bitpattern);
switch log2(M) PAMSIG = pam_mapper.map(X);
case 1
% 2-ASK: BPSK / OOK
pam_sig=bitpattern(:,1);
if unipolar==0 X.signal = applyPulseShaping(PAMSIG.signal,fsym,fdac);
pam_sig=2*pam_sig-1;
end
case 2 % ELECTRICAL DOMAIN
% 4-ASK: X = awg.process(X);
pam_sig=2*bitpattern(:,1)+(bitpattern(:,1)==bitpattern(:,2));
if unipolar==0 X = fil_tx.process(X);
pam_sig=2*pam_sig-3;
end % OPTICAL DOMAIN
X = extmodlaser.process(X);
X = amp.process(X);
X = fib.process(X);
X = phdiode.process(X);
X = fil_diode.process(X);
% ELECTRICAL DOMAIN
X = scp.process(X);
X = X.resample("fs_out",2*fsym,"fs_in",fadc);
case 3 % INFORMATION SIGNAL
% 8-ASK: X = eq.process(X,PAMSIG);
x1 = bitpattern(:,1);
x2 = (bitpattern(:,1)==bitpattern(:,3));
x3 = x2~=bitpattern(:,2);
pam_sig = 4*x1 + 2*x2 + x3; X = pam_mapper.demap(X);
if unipolar==0 % BER
pam_sig=2*pam_sig-7; [bits,errors,BER] = calc_ber(X.signal(:,10000:end-20),bitpattern(10000:end-20,:)',0);
end
disp(['BER: ', sprintf('%2E',BER)]);
case 4 disp(X.logbook);
% 16-ASK:
x1 = bitpattern(:,1);
x2 = (bitpattern(:,1)==bitpattern(:,4));
x3 = x2~=bitpattern(:,3);
x4 = x3~=bitpattern(:,2);
pam_sig = 8*x1 + 4*x2 + 2*x3 + x4;
if unipolar==0
pam_sig=2*pam_sig-15;
end
end
end
function yout = applyPulseShaping(xin,fsym,fdac) function yout = applyPulseShaping(xin,fsym,fdac)
@@ -171,14 +127,44 @@ function yout = applyPulseShaping(xin,fsym,fdac)
yout = upfirdn(xin,h,up,dn); yout = upfirdn(xin,h,up,dn);
%cut signal, which is longer due to fir filter %cut signal, which is longer due to fir filter
st = up/dn*racos_len/2; %we need to cut y_out st = round(up/dn*racos_len/2); %we need to cut y_out
en = st + (length(xin)*up/dn) -1; en = round(st + (length(xin)*up/dn) -1);
yout = yout(st:en); yout = yout(st:en);
%Check output integrity %Check output integrity
if (up/dn * length(xin)) ~= length(yout) if round(up/dn * length(xin)) ~= length(yout)
warning('Check signal length after pulse shaping'); warning('Check signal length after pulse shaping');
end end
end end
function [bits,errors,BER] = calc_ber(data_in,data_ref,skip)
data_ref=logical(data_ref);
data_in = logical(data_in);
bits = 0;
errors=0;
data_ref_overlap=zeros(size(data_ref,1),skip+(length(data_ref)-size(data_in,2)));
data_ref_pointer=0;
% Determine BER
bits = bits+size(data_in,2)-skip;
try
errors = sum( data_in(:,skip+1:end,:) ~= data_ref(:,skip+1:end,:),2 );
catch
%warning('BER calculation not optimal: Arrays have incompatible sizes for this operation.')
errors = NaN;
end
try
errors = sum( data_in(:,skip+1:end,:) ~= data_ref(:,skip+1:end-1,:),2 );
end
try
errors = sum( data_in(:,skip+1:end,:) ~= data_ref(:,skip+1:end-2,:),2 );
end
BER = sum(errors)/sum(bits);
end