diff --git a/Classes/01_transmit/AWG.m b/Classes/01_transmit/AWG.m index 1193db5..c82b5b3 100644 --- a/Classes/01_transmit/AWG.m +++ b/Classes/01_transmit/AWG.m @@ -1,4 +1,4 @@ -classdef AWG +classdef AWG < handle %AWG Summary of this class goes here % Detailed explanation goes here @@ -63,18 +63,22 @@ classdef AWG len_in = length(signalclass_in.signal); if signalclass_in.fs ~= obj.fdac + k = obj.kover*obj.fdac / signalclass_in.fs; signalclass_in = signalclass_in.resample("fs_in",signalclass_in.fs,"fs_out",obj.fdac); end - + % 1-3. actual processing of the signal (normalize->quantize->sample hold) signalclass_in.signal = obj.process_(signalclass_in.signal); - - % cast the inform. signal to electrical signal - signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook); + % cast the inform. signal to electrical signal + if ~isa(signalclass_in,'Electricalsignal') + signalclass_in = Electricalsignal(signalclass_in,"fs",obj.fdac*obj.kover,"logbook",signalclass_in.logbook); + end + % normalize to 0dBm before applying the lowpass %signalclass_in = signalclass_in.normalize("mode","milliwatt"); - signalclass_in = signalclass_in.setPower(6,"dBm"); + signalclass_in = signalclass_in.setPower(13,"dBm"); + % 4. Apply LPF on the signal if obj.lpf_active @@ -89,7 +93,7 @@ classdef AWG end end - signalclass_in.power + disp(['AWG output power: ',num2str(signalclass_in.power),' dBm']); % append to logbook current_class = class(obj); @@ -123,12 +127,15 @@ classdef AWG if obj.normalize2dac % 0a Normalize the signal to full scale DAC range - data_in = data_in - min(data_in); - data_in = data_in/(max(data_in)-min(data_in)); - data_in = data_in * (obj.dac_max-obj.dac_min); - data_in = data_in + obj.dac_min; + + data_in = data_in - min(data_in); %set "foot" to zero + data_in = data_in / (max(data_in)-min(data_in)); %scale between 0 and 1 + data_in = data_in * (obj.dac_max-obj.dac_min); %scale to desired total range of DAC + data_in = data_in + obj.dac_min; %set "foot" to desired value end + data_in = data_in - mean(data_in); + % 1. Quantize the signal - Full Scale is between obj.dac_min % and dac_max. If signal is smaller in between, you won't use % the full bit-resolution. @@ -137,6 +144,7 @@ classdef AWG else elec_out = data_in; end + % 2. Sample and hold + repeat (data_out: 1xsignal length) if obj.upsampling_method == 1 @@ -149,6 +157,7 @@ classdef AWG else error('chosen upsampling method not implemented?'); end + % 3. Add skew (not implemented so far) if obj.skew_active @@ -182,7 +191,7 @@ classdef AWG 1i*min(max(imag(x_in)-obj.dac_min,0),obj.dac_max-obj.dac_min); % quantize signal and shift back signal - x_in = round((steps-1)/(obj.max-obj.dac_min)*x_in); + x_in = round((steps-1)/(obj.dac_max-obj.dac_min)*x_in); % scale and shift back quant_out = x_in*(obj.dac_max-obj.dac_min)/(steps-1) +(1+1i)*obj.dac_min; diff --git a/Classes/02_etc/Filter.m b/Classes/02_etc/Filter.m index 10118a3..05ae2fb 100644 --- a/Classes/02_etc/Filter.m +++ b/Classes/02_etc/Filter.m @@ -249,8 +249,12 @@ classdef Filter < handle end function showHere(obj) - obj.signal_length = 512; - [H_,~] = obj.buildFilter(); + if isempty(obj.H) + obj.signal_length = 4096; + [H_,~] = obj.buildFilter(); + else + H_ = obj.H; + end fs = obj.fs; frex = linspace(-fs/2,fs/2,numel(H_)).*1e-9; @@ -265,6 +269,12 @@ classdef Filter < handle [~, index] = min(abs(filt - (-3))); threedB = frex(index); + [~, index] = min(abs(filt - (-6))); + sixdB = frex(index); + + [~, index] = min(abs(filt - (-10))); + ninedB = frex(index); + cur_module_name = ''; filter_desc = char([num2str(obj.filtdegree),'th-order ',char(obj.filterType),'; f cut:',num2str(fc.*1e-9),' GHz']); @@ -273,10 +283,17 @@ classdef Filter < handle legend Interpreter none title('Magnitude') hold on - p = plot(frex,filt,'LineWidth',1,'LineStyle','-','DisplayName',[cur_module_name,': ',filter_desc]); + p = plot(frex,filt,'LineWidth',1,'LineStyle','-','DisplayName',[cur_module_name,': ',filter_desc, '; 3/6/10 dB: ', num2str(threedB),'/ ',num2str(sixdB),'/ ',num2str(ninedB)]); + xline([-threedB,threedB],'LineStyle','-','LineWidth',1,'HandleVisibility','off','Color',p.Color); + xline([-sixdB,sixdB],'LineStyle','-','LineWidth',1,'HandleVisibility','off','Color',p.Color); + xline([-ninedB,ninedB],'LineStyle','-','LineWidth',1,'HandleVisibility','off','Color',p.Color); + xline(fcut_,'LineStyle',':','LineWidth',1,'HandleVisibility','off','Color',p.Color); - yline(-3,'LineStyle',':','LineWidth',1,'HandleVisibility','off'); + yline([-3, -6, -9],'LineStyle',':','LineWidth',1,'HandleVisibility','off'); + + xlim([0 fc.*2].*1e-9); + ylim([ninedB-6, 2]); legend end diff --git a/Functions/plot_eye.m b/Functions/plot_eye.m index c4fc406..aa271c0 100644 --- a/Functions/plot_eye.m +++ b/Functions/plot_eye.m @@ -19,6 +19,9 @@ function plot_eye(signal, fs, fsym) maxA = max(eye_mat(:))*1.1; minA = min(eye_mat(:))*1.1; + maxA = max(x); + minA =min(x); + difference= maxA-minA; data_ind_y=round((eye_mat-minA)/difference*(histpoints-1)) +1; @@ -28,7 +31,7 @@ function plot_eye(signal, fs, fsym) hist_data(:,n)=hist_data(:,n)+nn.'; end - figure; + image(hist_data); colormap(cbrewer2("Reds",92)); diff --git a/projects/MPI_April/mpi_simulation_cspr.m b/projects/MPI_April/mpi_simulation_cspr.m index 482055e..9dca01d 100644 --- a/projects/MPI_April/mpi_simulation_cspr.m +++ b/projects/MPI_April/mpi_simulation_cspr.m @@ -1,7 +1,7 @@ %% Settings clear -for M=[4,6,8] +for M=[4] filename = '112G_2'; @@ -11,7 +11,7 @@ for M=[4,6,8] kover = 8; fsym = round(datarate*1e-9 / log2(M))*1e9; - fdac = 256e9; + fdac = fsym;%256e9; fadc = 256e9; lowpass_cutoff = fsym/2 * 1.1; @@ -20,21 +20,22 @@ for M=[4,6,8] phd_bw = lowpass_cutoff; scp_bw = lowpass_cutoff; - LP_awg = Filter('filtdegree',4,"f_cutoff",90e9,"fs",fdac*kover,"filterType",filtertypes.butterworth); + LP_awg = Filter('filtdegree',4,"f_cutoff",75e9,"fs",fdac*kover,"filterType",filtertypes.butterworth); LP_modulator= Filter('filtdegree',2,"f_cutoff",70e9,"fs",fdac*kover,"filterType",filtertypes.butterworth); LP_opt = Filter('filtdegree',3,"f_cutoff",fsym/log2(M).*1.5,"fs",fdac*kover,"filterType",filtertypes.gaussian); LP_phd = Filter('filtdegree',2,"f_cutoff",70e9,"fs",fdac*kover,"filterType",filtertypes.butterworth); LP_scpe = Filter('filtdegree',4,"f_cutoff",110e9,"fs",fadc,"filterType",filtertypes.butterworth); - % 1) PRBS Generation O = 18; %order of prbs N = 2^(O-1); %length of prbs [~,seed] = prbs(O,1); %initialize first seed of prbs bitpattern=[]; + for i = 1:log2(M) [bitpattern(:,i),seed] = prbs(O,N,seed); end + if M == 6 bitpattern = reshape(bitpattern,[],1); bitpattern = bitpattern(1:end-mod(length(bitpattern),5)); @@ -62,13 +63,13 @@ for M=[4,6,8] vp = [0.25,0.5,0.75,1]; vb = [1:0.1:1.8]; - rop = -5:5; + rop = 0; sir = 28; laser_linewidth = 10e6; pn_key = 9; vp = 0.5; vb = 1;%[1:0.1:1.8]; - mpi_path=50; + mpi_path = 50; cnt = 1; @@ -81,10 +82,59 @@ for M=[4,6,8] %digimod_out = digimod_out.normalize("mode","oneone"); % cnt = cnt+1; - X = Pulseformer("fsym",fsym,"fdac",fdac,"pulse","rrc","pulselength",16,"rrcalpha",0.5).process(digimod_out); + %X = Pulseformer("fsym",fsym,"fdac",fdac,"pulse","rrc","pulselength",16,"rrcalpha",0.05).process(digimod_out); + X = digimod_out; +% % precomp + [b,a] = butter(2,75e9/(fsym/2),"low"); + H=freqz(b,a,length(X),fsym,'whole'); + max_amp_db = 3; + p = find(abs(H)<10^(-max_amp_db/20)); + H(p) = 10^(-max_amp_db/20); + H_maxatt = H; + H_maxatt = max(H,10^(-20/20)); + H_inv = 1./H_maxatt; + + freq_vec = linspace(-X.fs/2,X.fs/2,length(X)); + + h = sin(pi*freq_vec/fdac)./(pi*freq_vec/fdac); + + max_amp_db = 40; + max_amp_lin = 10^(-max_amp_db/20); + + p = find(h OPTICAL DOMAIN u_pi = 4; -vbias = -1.8; +vbias = 2; extmodlaser = EML("mode",eml_mode.im_cosinus,"power",0,"fsimu",X.fs,"lambda",1290,"bias",vbias,"u_pi",u_pi,"linewidth",laser_linewidth,"randomkey",5); [Opt,extmodlaser] = extmodlaser.process(X); if 1 - f = figure(22); - tiledlayout(2,2); - nexttile - hold on - scatter(X.signal(1:100000),(abs(Opt.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF') - xlabel('Input in V') - ylabel('Output in mW') + f = figure(120); + f.Name = 'bla'; + tiledlayout(2,4); nexttile + rms_ = rms(X.signal); + max_ = max(X.signal); + min_ = min(X.signal); hold on plot(X.signal,'LineWidth',0.1); yline([max_, min_],'LineWidth',2,'LineStyle','--'); @@ -68,16 +71,38 @@ if 1 ylim([-3 3]); title(['AWG output: ',num2str(X.power), 'dBm']); + % Add text boxes for MIN, MAX, and RMS voltage + text(0.5, min_-0.3, ['MIN: ', num2str(min_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left'); + text(0.5, max_+0.3, ['MAX: ', num2str(max_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left'); + text(0.5, rms_+0.22, ['RMS: ', num2str(rms_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left'); + text(0.5, -rms_-0.22, ['RMS: ', num2str(rms_),' V'],'FontSize', 10, 'HorizontalAlignment', 'left'); nexttile - spectrum_plot(Opt.signal,Opt.fs); - - - rms_ = rms(X.signal); - max_ = max(X.signal); - min_ = min(X.signal); + plot_eye(X.signal,X.fs,fsym); + ylabel('Signal in V') + + nexttile + hold on + v_in_curve = [-u_pi*1.5/2:0.1:u_pi*1.5/2]; + field=sqrt(10^(extmodlaser.power/10-3)); + mzm_curve = ((field.*cos(pi/2*(real(v_in_curve)+vbias)/u_pi)).^2)*1e3; + scatter(v_in_curve+vbias,mzm_curve,10,'o','filled','DisplayName','Modulator TF complete'); + scatter(X.signal(1:100000)+vbias,(abs(Opt.signal(1:100000)).^2)*1e3,0.1,'.','DisplayName','Modulator TF') + scatter(min_+vbias,((field.*cos(pi/2*(real(min_)+vbias)/u_pi)).^2)*1e3,50,'x','LineWidth',2); + scatter(max_+vbias,((field.*cos(pi/2*(real(max_)+vbias)/u_pi)).^2)*1e3,50,'x','LineWidth',2); + xlim([-u_pi*1.5/2+vbias, u_pi*1.5/2+vbias]); + ylim([min(mzm_curve),max(mzm_curve)]); + xlabel('Input in V') + ylabel('Output in mW') + title("MZM input (v) to output (w)"); + + nexttile + plot_eye(abs(Opt.signal.^2).*1e3 ,Opt.fs,fsym); + ylabel('Opt. Signal in mW') + nexttile([1 2]) + spectrum_plot( Opt.signal,Opt.fs, 'bla'); end