Minimal Working - seems too good?!
This commit is contained in:
@@ -79,7 +79,29 @@ classdef AWG
|
||||
|
||||
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
|
||||
% Detailed explanation goes here
|
||||
arguments(Input)
|
||||
@@ -119,13 +141,7 @@ classdef AWG
|
||||
elec_out = obj.skew(elec_out);
|
||||
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
|
||||
|
||||
|
||||
@@ -53,7 +53,22 @@ classdef Amplifier
|
||||
|
||||
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
|
||||
obj
|
||||
@@ -102,7 +117,7 @@ classdef Amplifier
|
||||
end
|
||||
|
||||
if ~seemsright
|
||||
warning("Amplifier output not correct, please check the reason");
|
||||
% warning("Amplifier output not correct, please check the reason");
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -64,7 +64,25 @@ classdef EML
|
||||
|
||||
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
|
||||
% Detailed explanation goes here
|
||||
|
||||
@@ -76,6 +94,8 @@ classdef EML
|
||||
if obj.linewidth ~= 0
|
||||
ph_noi = obj.createPhaseNoise;
|
||||
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
|
||||
laserfield = obj.field;
|
||||
end
|
||||
@@ -83,8 +103,7 @@ classdef EML
|
||||
%modulate the laserfield with the electrical signal
|
||||
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
|
||||
|
||||
|
||||
277
Classes/EQ.m
277
Classes/EQ.m
@@ -33,9 +33,24 @@ classdef EQ
|
||||
mode3rd %0: no reduction | 1: polynomial | 2: restricted to interval
|
||||
len_3rd %length of the interval (only for 3rd order mode = 3/4)
|
||||
|
||||
plottrain
|
||||
plotfinal
|
||||
load_decisions
|
||||
|
||||
save_taps
|
||||
|
||||
|
||||
%during simulation
|
||||
k0
|
||||
b
|
||||
b2
|
||||
b3
|
||||
e
|
||||
e2
|
||||
e3
|
||||
|
||||
coeff_number
|
||||
constellation_in
|
||||
|
||||
end
|
||||
|
||||
@@ -44,13 +59,65 @@ classdef EQ
|
||||
%EQ Construct an instance of this class
|
||||
% Detailed explanation goes here
|
||||
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
|
||||
|
||||
% alles nochmal mappen
|
||||
fn = fieldnames(options);
|
||||
for n = 1:numel(fn)
|
||||
obj.(fn{n}) = options.(fn{n});
|
||||
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
|
||||
% 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);
|
||||
|
||||
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
|
||||
|
||||
obj.k0 = obj.delay; % input delay compared to training sequence
|
||||
|
||||
if 1 % obj.active
|
||||
%% 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)
|
||||
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_save = NaN(361,8.6e5);
|
||||
% save_ind = 1;
|
||||
for trainloops = 1:obj.training_loops
|
||||
m = state.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
|
||||
m = obj.k0+1; % starting symbol index at the delay compared to the training sequence
|
||||
for n = obj.K*obj.k0+1:obj.K:obj.K*obj.training_length
|
||||
m = m+1;
|
||||
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_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_1 = ref(obj.Nb(1)-obj.k0+m-2:-1:m-obj.k0-1).';
|
||||
[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];
|
||||
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 obj.l1act
|
||||
sgn_e = e;
|
||||
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;
|
||||
sgn_e = e_;
|
||||
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;
|
||||
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
|
||||
else
|
||||
if obj.l1act
|
||||
sgn_e = e;
|
||||
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);
|
||||
sgn_e = e_;
|
||||
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);
|
||||
else
|
||||
e = e - error*input_vec/(input_vec.'*input_vec);
|
||||
e_ = e_ - error*input_vec/(input_vec.'*input_vec);
|
||||
end
|
||||
end
|
||||
% e_save(:,save_ind) = e;
|
||||
% save_ind = save_ind+1;
|
||||
e_dc = e_dc - obj.dcmu*error;
|
||||
e_dc = e_dc - obj.DCmu*error;
|
||||
|
||||
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
|
||||
%%
|
||||
|
||||
% Plot the intermediate coefficients after training mode
|
||||
state.b = b(1:obj.Nb(1));
|
||||
state.b2 = b(obj.Nb(1)+1:obj.Nb(1)+Nb2);
|
||||
state.b3 = b(obj.Nb(1)+Nb2+1:end);
|
||||
state.e = e(1:obj.Ne(1));
|
||||
state.e2 = e(obj.Ne(1)+1:obj.Ne(1)+N2);
|
||||
state.e3 = e(obj.Ne(1)+N2+1: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);
|
||||
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);
|
||||
|
||||
if obj.plottrain
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
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')
|
||||
xlabel('coefficient index'); ylabel('value'); set(gca,'Fontsize',12)
|
||||
set(gcf,'Position',[200 500 700 400])
|
||||
end
|
||||
|
||||
if obj.l1act
|
||||
neg_lin = find(abs(state.e) < obj.thres(1));
|
||||
neg_2nd = find(abs(state.e2) < obj.thres(2));
|
||||
neg_3rd = find(abs(state.e3) < obj.thres(3));
|
||||
neg_lin = find(abs(obj.e) < obj.thres(1));
|
||||
neg_2nd = find(abs(obj.e2) < obj.thres(2));
|
||||
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
|
||||
|
||||
rel_lin = find(abs(state.e) >= obj.thres(1));
|
||||
rel_2nd = find(abs(state.e2) >= obj.thres(2));
|
||||
rel_3rd = find(abs(state.e3) >= obj.thres(3));
|
||||
rel_lin = find(abs(obj.e) >= obj.thres(1));
|
||||
rel_2nd = find(abs(obj.e2) >= obj.thres(2));
|
||||
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
|
||||
e(neg) = 0;
|
||||
e_(neg) = 0;
|
||||
|
||||
ind_mat_2nd(neg_2nd,:) = [];
|
||||
|
||||
@@ -250,24 +317,25 @@ classdef EQ
|
||||
|
||||
%% decision directed mode
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
constellation_in = unique(ref_in);
|
||||
constellation_in_ = unique(ref_in);
|
||||
end
|
||||
end
|
||||
|
||||
state.constellation_in = constellation_in;
|
||||
obj.constellation_in = constellation_in_;
|
||||
|
||||
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
|
||||
coeff = [e;b];
|
||||
coeff = [e_;b_];
|
||||
end
|
||||
|
||||
for dd_loop = 1:obj.dd_loops
|
||||
@@ -277,20 +345,21 @@ classdef EQ
|
||||
D_2 = zeros(Nb2,1);
|
||||
D_3 = zeros(Nb3,1);
|
||||
|
||||
if all(obj.mu == obj.mu(1))
|
||||
mu_mat = obj.mu(1);
|
||||
if all(obj.DDmu == obj.DDmu(1))
|
||||
mu_mat = obj.DDmu(1);
|
||||
else
|
||||
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
|
||||
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
|
||||
|
||||
if obj.load_decisions
|
||||
pathn = evalin('base','modeldir');
|
||||
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(1:2:length(data_in)) = dd_out_vals;
|
||||
else
|
||||
@@ -300,7 +369,7 @@ classdef EQ
|
||||
for k = 1:obj.K:length(data_in)
|
||||
m=m+1; % Symbol index
|
||||
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
|
||||
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;
|
||||
|
||||
if ~obj.load_decisions
|
||||
[~,dd_idx] = min(abs(output_vec(m) - constellation_in)); % decision for closest constellation point
|
||||
dd_out(k) = constellation_in(dd_idx);
|
||||
[~,dd_idx] = min(abs(output_vec(m) - constellation_in_)); % decision for closest constellation point
|
||||
dd_out(k) = constellation_in_(dd_idx);
|
||||
end
|
||||
|
||||
if obj.Nb(1) > 0
|
||||
dd_DFE(2:end) = dd_DFE(1:end-1);
|
||||
dd_DFE(1) = dd_out(k);
|
||||
|
||||
if obj.error_free && m > state.k0
|
||||
dd_DFE(1) = ref_in(m-state.k0);
|
||||
if obj.ideal_dfe && m > obj.k0
|
||||
dd_DFE(1) = ref_in(m-obj.k0);
|
||||
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
|
||||
% if dd_loop ~= 21
|
||||
error = output_vec(m) - dd_out(k);
|
||||
@@ -335,18 +404,96 @@ classdef EQ
|
||||
% save_ind = save_ind+1;
|
||||
|
||||
if mu_mat ~= 0
|
||||
e_dc = e_dc - obj.dcmu*error;
|
||||
e_dc = e_dc - obj.DCmu*error;
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
% of second and third order based on the linear symbols
|
||||
|
||||
@@ -370,7 +517,7 @@ classdef EQ
|
||||
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
|
||||
ind_mat_2nd = NaN(N2,2);
|
||||
@@ -498,7 +645,7 @@ classdef EQ
|
||||
|
||||
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
|
||||
ind_mat_2nd = NaN(N2,2);
|
||||
|
||||
@@ -3,23 +3,43 @@ classdef Electricalsignal < Signal
|
||||
% Detailed explanation goes here
|
||||
|
||||
properties
|
||||
|
||||
fs
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = Electricalsignal(signal)
|
||||
function obj = Electricalsignal(signal, options)
|
||||
%ELECTRICALSIGNAL Construct an instance of this class
|
||||
% Detailed explanation goes here
|
||||
arguments
|
||||
signal
|
||||
options.fs
|
||||
options.logbook
|
||||
end
|
||||
|
||||
obj = obj@Signal(signal);
|
||||
|
||||
fn = fieldnames(options);
|
||||
|
||||
for l = 1:numel(fn)
|
||||
obj.(fn{l}) = options.(fn{l});
|
||||
end
|
||||
|
||||
function outputArg = method1(obj,inputArg)
|
||||
%METHOD1 Summary of this method goes here
|
||||
% Detailed explanation goes here
|
||||
outputArg = obj.Property1 + inputArg;
|
||||
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
|
||||
|
||||
|
||||
@@ -51,7 +51,21 @@ classdef Fiber
|
||||
|
||||
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
|
||||
% 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;
|
||||
|
||||
|
||||
opt_out = obj.NLSE(opt_in);
|
||||
|
||||
%attenuate nase
|
||||
|
||||
@@ -40,7 +40,21 @@ classdef Filter
|
||||
|
||||
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);
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@ classdef Informationsignal < Signal
|
||||
% Detailed explanation goes here
|
||||
|
||||
properties
|
||||
nase
|
||||
lambda_nm
|
||||
|
||||
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -15,11 +15,18 @@ classdef Informationsignal < Signal
|
||||
|
||||
end
|
||||
|
||||
function outputArg = method1(obj,inputArg)
|
||||
%METHOD1 Summary of this method goes here
|
||||
% Detailed explanation goes here
|
||||
outputArg = obj.Property1 + inputArg;
|
||||
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
|
||||
|
||||
|
||||
@@ -4,24 +4,45 @@ classdef Opticalsignal < Signal
|
||||
|
||||
properties
|
||||
nase
|
||||
lambda_nm
|
||||
lambda
|
||||
fs
|
||||
|
||||
end
|
||||
|
||||
methods
|
||||
function obj = Opticalsignal(signal, fsym, fsimu)
|
||||
function obj = Opticalsignal(signal, options)
|
||||
%OPTICALSIGNAL Construct an instance of this class
|
||||
% 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
|
||||
|
||||
function outputArg = method1(obj,inputArg)
|
||||
%METHOD1 Summary of this method goes here
|
||||
% Detailed explanation goes here
|
||||
outputArg = obj.Property1 + inputArg;
|
||||
|
||||
function obj = normalize(obj)
|
||||
|
||||
obj.signal = obj.signal/sqrt(mean(abs(obj.signal).^2));
|
||||
|
||||
end
|
||||
|
||||
function pow = power(obj)
|
||||
|
||||
pow = mean(abs(obj.signal.^2)) ;
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
183
Classes/PAMmapper.m
Normal file
183
Classes/PAMmapper.m
Normal 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
|
||||
|
||||
@@ -28,7 +28,24 @@ classdef Photodiode
|
||||
|
||||
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
|
||||
% Detailed explanation goes here
|
||||
|
||||
|
||||
@@ -68,18 +68,32 @@ classdef Scope
|
||||
|
||||
end
|
||||
|
||||
function yout = process(obj,xin)
|
||||
%METHOD1 Summary of this method goes here
|
||||
% Detailed explanation goes here
|
||||
function signalclass_out = process(obj,signalclass_in)
|
||||
|
||||
% apply LPF
|
||||
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
|
||||
% TODO: implement and test the delays. Also look for delay of
|
||||
% lpf filter
|
||||
yout = obj.sampleSignal(yout);
|
||||
yout = obj.sampleSignal(xin);
|
||||
|
||||
% quantize signal
|
||||
yout = obj.quantize(yout);
|
||||
|
||||
131
Classes/Signal.m
131
Classes/Signal.m
@@ -4,8 +4,7 @@ classdef Signal
|
||||
|
||||
properties
|
||||
signal
|
||||
fsym
|
||||
fsimu
|
||||
logbook
|
||||
end
|
||||
|
||||
methods
|
||||
@@ -14,34 +13,140 @@ classdef Signal
|
||||
% Detailed explanation goes here
|
||||
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
|
||||
|
||||
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')
|
||||
|
||||
%convert to electrical
|
||||
disp("Convert signal: opt. -> elec. Fetch all properties (e.g. nase)!");
|
||||
nase = obj.nase;
|
||||
lambda_nm = obj.lambda_nm;
|
||||
e_sig = Electricalsignal(obj.signal,obj.fsym, obj.fsimu);
|
||||
varargout{1} = obj.nase;
|
||||
varargout{2} = obj.lambda;
|
||||
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
|
||||
|
||||
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')
|
||||
|
||||
%convert to optical
|
||||
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
|
||||
|
||||
function normalizedsignal = signal_(obj)
|
||||
normalizedsignal = obj.signal / norm(obj.signal);
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
|
||||
BIN
Functions/.DS_Store
vendored
Normal file
BIN
Functions/.DS_Store
vendored
Normal file
Binary file not shown.
11
Functions/settingsdlg/.gitignore
vendored
Normal file
11
Functions/settingsdlg/.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
slprj/
|
||||
*.mexw32
|
||||
*.mexglx
|
||||
*.mexmaci
|
||||
*.mexw64
|
||||
*.mexmaci64
|
||||
*.mexa64
|
||||
*.zip
|
||||
*.m~
|
||||
*.asv
|
||||
|
||||
26
Functions/settingsdlg/License.txt
Normal file
26
Functions/settingsdlg/License.txt
Normal 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.
|
||||
114
Functions/settingsdlg/README.md
Normal file
114
Functions/settingsdlg/README.md
Normal file
@@ -0,0 +1,114 @@
|
||||
[](https://www.mathworks.com/matlabcentral/fileexchange/26312-settings-dialog)
|
||||
|
||||
|
||||
[](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).
|
||||
BIN
Functions/settingsdlg/Screen.png
Normal file
BIN
Functions/settingsdlg/Screen.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 5.1 KiB |
488
Functions/settingsdlg/settingsdlg.m
Normal file
488
Functions/settingsdlg/settingsdlg.m
Normal 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
|
||||
BIN
Functions/settingsdlg/settingsdlg.odt
Normal file
BIN
Functions/settingsdlg/settingsdlg.odt
Normal file
Binary file not shown.
BIN
Functions/settingsdlg/settingsdlg.pdf
Normal file
BIN
Functions/settingsdlg/settingsdlg.pdf
Normal file
Binary file not shown.
194
comm_tb.m
194
comm_tb.m
@@ -1,9 +1,11 @@
|
||||
O = 14; %order of prbs
|
||||
clear all
|
||||
|
||||
O = 17; %order of prbs
|
||||
N = 2^(O-1); %length of prbs
|
||||
[~,seed] = prbs(O,1); %initialize first seed of prbs
|
||||
|
||||
% Modulation
|
||||
M = 4;
|
||||
M = 4; %PAM-M
|
||||
bitpattern = zeros(N,log2(M));
|
||||
|
||||
% Symbol Rate
|
||||
@@ -17,136 +19,90 @@ fadc = 256e9;
|
||||
% Simulation frequency in "analog domain"
|
||||
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)
|
||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||
end
|
||||
%CONSTRUCTION
|
||||
pam_mapper = PAMmapper(M,0);
|
||||
|
||||
Bits = Informationsignal(bitpattern);
|
||||
awg = AWG('preset','M8196A','fdac',fdac,'kover',kover,'lpf_active',0);
|
||||
|
||||
Bits.signal = pam_mapping(Bits.signal,M,0);
|
||||
|
||||
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);
|
||||
fil_tx = Filter('filtdegree',1,"f_cutoff",50e9,"fsamp",fdac,"filterType",filtertypes.bessel_bilin);
|
||||
|
||||
u_pi = 3.5;
|
||||
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);
|
||||
laserfield = extmodlaser.process(filtered);
|
||||
extmodlaser = EML("mode",emlmodes.im_cosinus,"power",10,"fsimu",fsimu,"lambda",1550,"bias",vbias,"u_pi",u_pi,"linewidth",0);
|
||||
|
||||
att = Amplifier("amplification_db",10,"amp_mode","gain","type","ideal","saturation_mode",0,'saturation_power',10);
|
||||
att_out = att.process(laserfield);
|
||||
amp = Amplifier("amplification_db",10,"amp_mode","gain","type","ideal","saturation_mode",0,'saturation_power',10);
|
||||
|
||||
fib = Fiber("fsimu",fdac*kover,"fiber_length",0,"alpha",0.2,"D",17,"lambda0",1550);
|
||||
fib_out = fib.process(att_out);
|
||||
fib = Fiber("fsimu",fdac*kover,"fiber_length",2,"alpha",0.2,"D",17,"lambda0",1550);
|
||||
|
||||
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,...
|
||||
"delay",0,"fixed_delay",0,"lpf_bw",120e9,"filtertype",filtertypes.bessel_inp,...
|
||||
"samplingdelay",0,"rand_samplingdelay",0,"freq_offset",0,"samp_jitter",0,...
|
||||
"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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
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)));
|
||||
% INFORMATION SIGNAL
|
||||
for i = 1:log2(M)
|
||||
[bitpattern(:,i),seed] = prbs(O,N,seed);
|
||||
end
|
||||
|
||||
function pam_sig = pam_mapping(bitpattern, M, unipolar)
|
||||
X = Informationsignal(bitpattern);
|
||||
|
||||
switch log2(M)
|
||||
case 1
|
||||
% 2-ASK: BPSK / OOK
|
||||
pam_sig=bitpattern(:,1);
|
||||
PAMSIG = pam_mapper.map(X);
|
||||
|
||||
if unipolar==0
|
||||
pam_sig=2*pam_sig-1;
|
||||
end
|
||||
X.signal = applyPulseShaping(PAMSIG.signal,fsym,fdac);
|
||||
|
||||
case 2
|
||||
% 4-ASK:
|
||||
pam_sig=2*bitpattern(:,1)+(bitpattern(:,1)==bitpattern(:,2));
|
||||
% ELECTRICAL DOMAIN
|
||||
X = awg.process(X);
|
||||
|
||||
if unipolar==0
|
||||
pam_sig=2*pam_sig-3;
|
||||
end
|
||||
X = fil_tx.process(X);
|
||||
|
||||
% 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
|
||||
% 8-ASK:
|
||||
x1 = bitpattern(:,1);
|
||||
x2 = (bitpattern(:,1)==bitpattern(:,3));
|
||||
x3 = x2~=bitpattern(:,2);
|
||||
% INFORMATION SIGNAL
|
||||
X = eq.process(X,PAMSIG);
|
||||
|
||||
pam_sig = 4*x1 + 2*x2 + x3;
|
||||
X = pam_mapper.demap(X);
|
||||
|
||||
if unipolar==0
|
||||
pam_sig=2*pam_sig-7;
|
||||
end
|
||||
% BER
|
||||
[bits,errors,BER] = calc_ber(X.signal(:,10000:end-20),bitpattern(10000:end-20,:)',0);
|
||||
|
||||
|
||||
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 unipolar==0
|
||||
pam_sig=2*pam_sig-15;
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
disp(['BER: ', sprintf('%2E',BER)]);
|
||||
disp(X.logbook);
|
||||
|
||||
function yout = applyPulseShaping(xin,fsym,fdac)
|
||||
|
||||
@@ -171,14 +127,44 @@ function yout = applyPulseShaping(xin,fsym,fdac)
|
||||
yout = upfirdn(xin,h,up,dn);
|
||||
|
||||
%cut signal, which is longer due to fir filter
|
||||
st = up/dn*racos_len/2; %we need to cut y_out
|
||||
en = st + (length(xin)*up/dn) -1;
|
||||
st = round(up/dn*racos_len/2); %we need to cut y_out
|
||||
en = round(st + (length(xin)*up/dn) -1);
|
||||
|
||||
yout = yout(st:en);
|
||||
|
||||
%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');
|
||||
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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user