ChannelFreqResp optimized and compared to move-it

minimal lab setup
This commit is contained in:
Silas Labor Zizou
2024-10-07 08:19:56 +02:00
parent 8577f5f6f4
commit 135d0e7cfc
16 changed files with 369 additions and 146 deletions

View File

@@ -192,6 +192,19 @@ classdef Signal
end end
%% Add signals from one signal to another, the first object will sustain
function Diff = minus(X,y)
if isa(y,'Signal')
Diff = X;
Diff.signal = X.signal - y.signal;
elseif isnumeric(y)
Diff = X;
Diff.signal = X.signal - y;
end
end
function Product = times(X,y) function Product = times(X,y)
if isa(y,'Signal') if isa(y,'Signal')
@@ -282,9 +295,11 @@ classdef Signal
xlim([-obj.fs/2 obj.fs/2].*1e-9) xlim([-obj.fs/2 obj.fs/2].*1e-9)
edgetick = 2^(nextpow2(obj.fs*1e-9)); edgetick = 2^(nextpow2(obj.fs*1e-9));
% xticks([-edgetick:16:edgetick]); % xticks([-edgetick:16:edgetick]);
xlim([-244, 244]) xlim([100*round( min(w.*1e-9)/100,1)-10,100*round( max(w.*1e-9)/100,1)+10])
ylim([-120,10]); ylim([100*round( min(p_dbm)/100,1)-3,100*round( max(p_dbm)/100,1)+3]);
yticks([-200:10:10]); yticks([-200:10:10]);
grid on
grid minor
legend legend
end end
@@ -437,10 +452,13 @@ classdef Signal
end end
%plot all synced signals and the ref signal %plot all synced signals and the ref signal
figure;hold on; debug = 0;
for i = 1:size(S,1) if debug
plot(S{i}.normalize('mode','oneone').signal(1000:1100),'LineWidth',0.1,'Color',[0.2157 0.4941 0.7216]); figure;hold on;
plot(b(1000:1100),'LineWidth',1); for i = 1:size(S,1)
plot(S{i}.normalize('mode','oneone').signal(1000:1100),'LineWidth',0.1,'Color',[0.2157 0.4941 0.7216]);
plot(b(1000:1100),'LineWidth',1);
end
end end
%return the sinal with the highest correlation... %return the sinal with the highest correlation...
@@ -602,7 +620,6 @@ classdef Signal
% beautify % beautify
colormap(cbrewer2("Blues",4096)); colormap(cbrewer2("Blues",4096));
if isa(obj,'Opticalsignal') if isa(obj,'Opticalsignal')
title("Optical Eye") title("Optical Eye")
ylabel("Power in mW"); ylabel("Power in mW");
@@ -652,41 +669,15 @@ classdef Signal
% Define properties
boxPosition = [0.15 0.86 0.2 0.05]; % Position for the first box [x y width height]
boxColor = [0.9 0.9 0.9]; % Light grey background color
boxEdgeColor = 'k'; % Black edge color
boxLineStyle = '--'; % Dashed line style
boxFontWeight = 'bold'; % Bold font
% Create first annotation box for Power
annotation('textbox', boxPosition, ...
'String', ['Power: ',num2str(pwr_dbm),' dBm'], ...
'BackgroundColor', boxColor, ...
'EdgeColor', boxEdgeColor, ...
'LineStyle', boxLineStyle, ...
'FontWeight', boxFontWeight, ...
'HorizontalAlignment', 'center');
% Adjust position for the second box (slightly to the right)
boxPosition = [0.37 0.86 0.2 0.05]; % Adjusted position
% Create second annotation box for PAPR
annotation('textbox', boxPosition, ...
'String', ['PAPR(lin):',num2str(papr_),''], ...
'BackgroundColor', boxColor, ...
'EdgeColor', boxEdgeColor, ...
'LineStyle', boxLineStyle, ...
'FontWeight', boxFontWeight, ...
'HorizontalAlignment', 'center');
try try
hist_interest = plot_data(:,posxall); hist_interest = plot_data(:,posxall);
hist_interest_smoth = smooth(hist_interest,20); hist_interest_smoth = smooth(hist_interest,20);
a = scatter(hist_interest_smoth+posxall,1:length(hist_interest_smoth),4,'.','MarkerEdgeColor','red'); a = scatter(hist_interest_smoth+posxall,1:length(hist_interest_smoth),4,'.','MarkerEdgeColor','red');
[pk,loc] = findpeaks(hist_interest_smoth,"MinPeakDistance",40,"NPeaks",M,"MinPeakHeight",30); [pk,loc] = findpeaks(hist_interest_smoth,"MinPeakDistance",10,"NPeaks",M,"MinPeakHeight",30,"MinPeakProminence",10);
scatter(posxall,loc,'red','Marker','x','LineWidth',2); scatter(posxall,loc,'red','Marker','x','LineWidth',2);
yline(loc,'Color','red','LineWidth',1,'LineStyle',':'); yline(loc,'Color','red','LineWidth',1,'LineStyle',':');
for i = 1:numel(loc) for i = 1:numel(loc)
@@ -717,6 +708,37 @@ classdef Signal
thirdboxstring = ['OMA outer:',num2str(er),' V']; thirdboxstring = ['OMA outer:',num2str(er),' V'];
end end
plot_infos = 0;
if plot_infos
% Define properties
boxPosition = [0.15 0.86 0.2 0.05]; % Position for the first box [x y width height]
boxColor = [0.9 0.9 0.9]; % Light grey background color
boxEdgeColor = 'k'; % Black edge color
boxLineStyle = '--'; % Dashed line style
boxFontWeight = 'bold'; % Bold font
% Create first annotation box for Power
annotation('textbox', boxPosition, ...
'String', ['Power: ',num2str(pwr_dbm),' dBm'], ...
'BackgroundColor', boxColor, ...
'EdgeColor', boxEdgeColor, ...
'LineStyle', boxLineStyle, ...
'FontWeight', boxFontWeight, ...
'HorizontalAlignment', 'center');
% Adjust position for the second box (slightly to the right)
boxPosition = [0.37 0.86 0.2 0.05]; % Adjusted position
% Create second annotation box for PAPR
annotation('textbox', boxPosition, ...
'String', ['PAPR(lin):',num2str(papr_),''], ...
'BackgroundColor', boxColor, ...
'EdgeColor', boxEdgeColor, ...
'LineStyle', boxLineStyle, ...
'FontWeight', boxFontWeight, ...
'HorizontalAlignment', 'center');
annotation('textbox', boxPosition, ... annotation('textbox', boxPosition, ...
@@ -728,6 +750,8 @@ classdef Signal
'HorizontalAlignment', 'center'); 'HorizontalAlignment', 'center');
end end
end
yticks(linspace(0,histpoints,16)); yticks(linspace(0,histpoints,16));
y_tickstring = sprintfc('%.2f', y_tickstring); y_tickstring = sprintfc('%.2f', y_tickstring);
yticklabels(y_tickstring); yticklabels(y_tickstring);

View File

@@ -132,7 +132,7 @@ classdef ChannelFreqResp < handle
fstarget = Target.fs; fstarget = Target.fs;
% Build new frequencie axis (with current fs) % Build new frequency axis (with current fs)
fnew = linspace(0,fstarget/2,length(Target)/2+1); fnew = linspace(0,fstarget/2,length(Target)/2+1);
fnew = fnew(2:end-1); fnew = fnew(2:end-1);
@@ -154,7 +154,7 @@ classdef ChannelFreqResp < handle
%smoothing takes time and sometimes the result looks odd, %smoothing takes time and sometimes the result looks odd,
%however the performance is most of the time better %however the performance is most of the time better
smoothing = 1; smoothing = 0;
if smoothing if smoothing
iH = smooth(fnew,iH,0.1,'loess')'; iH = smooth(fnew,iH,0.1,'loess')';
end end
@@ -163,16 +163,10 @@ classdef ChannelFreqResp < handle
% angle (-pi,pi) at lowest frequency % angle (-pi,pi) at lowest frequency
iH = iH.*exp(-1j*angle(iH(1))); % to be checked (<- not from silas, so what needs to be checked?) iH = iH.*exp(-1j*angle(iH(1))); % to be checked (<- not from silas, so what needs to be checked?)
% Phase difference between lowest and hiughest frequency
% component -> but what is this for? dPhase is not used...
noncausal = 0;
if noncausal
dPhase = angle(iH(end))-angle(iH(1));
end
% normalize complex freq. resp. by magnitude at the first % normalize complex freq. resp. by magnitude at the first
% five frequencies -> should be the vaue at f=0=DC component? % five frequencies -> should be the vaue at f=0=DC component?
iH = iH./mean(abs(iH(1:100))); %why 1:5?? iH = iH./mean(abs(iH)); %why 1:5??
% set maximum amplification % set maximum amplification
% set als values higher than hmax to hmax and keep the % set als values higher than hmax to hmax and keep the
@@ -191,19 +185,20 @@ classdef ChannelFreqResp < handle
% iH(1) is DC ---> iH(end) is High Freq. % iH(1) is DC ---> iH(end) is High Freq.
H_inv = [iH(1) iH fliplr(conj(iH)) conj(iH(1))]; H_inv = [iH(1) iH fliplr(conj(iH)) conj(iH(1))];
H_inv = [iH(1) iH 0 fliplr(conj(iH))];
% H_inv = [iH(1) iH iH(end) fliplr(conj(iH)) conj(iH(1))]; % H_inv = [iH(1) iH iH(end) fliplr(conj(iH)) conj(iH(1))];
obj.H_apply = H_inv; obj.H_apply = H_inv;
Target.signal = real((ifft( ( fft(real( Target.signal )) .* H_inv' ) ))); Target.signal = real((ifft( ( fft(real( Target.signal' )) .* H_inv ) )));
Target.signal = Target.signal';
end end
function plot(obj) function plot(obj)
figure(55551); figure(55);
clf; clf;
Havg = obj.H; Havg = obj.H;
@@ -290,6 +285,7 @@ classdef ChannelFreqResp < handle
end end
function data = load(obj, options) function data = load(obj, options)
% Function to load data from a specified file and path. % Function to load data from a specified file and path.
arguments arguments
obj obj
@@ -334,12 +330,20 @@ classdef ChannelFreqResp < handle
% Load the data from the specified file % Load the data from the specified file
loadedData = load(fullFileName); loadedData = load(fullFileName);
% Replace whole obj here.. is this save or unsave?! if ~strcmp(fieldnames(loadedData),'obj')
fn = fieldnames(loadedData.obj); % user want to load a moveit precomp file
for n = 1:numel(fn) obj.H = 1./loadedData.uFF;
try obj.faxis = loadedData.f;
obj.(fn{n}) = loadedData.obj.(fn{n}); else
% Replace whole obj here.. is this save or unsave?!
fn = fieldnames(loadedData.obj);
for n = 1:numel(fn)
try
obj.(fn{n}) = loadedData.obj.(fn{n});
end
end end
end end
fprintf('Frequency response information successfully loaded from %s\n', fullFileName); fprintf('Frequency response information successfully loaded from %s\n', fullFileName);
@@ -373,25 +377,28 @@ classdef ChannelFreqResp < handle
function [rH] = estHfromDMT(obj, data_in, ref_in) function [rH] = estHfromDMT(obj, data_in, ref_in)
%! Dont (circ)shift the signal here as this would remove the phase information!
%tested with a butterworth filter this exactly reconstructs the
%phase and the magnitude. However, the option is here
estimatephase = 1;
if ~estimatephase Nfft = 2*obj.Nacq + 1 ;
data_in = reshape(data_in,1,length(data_in));
ref_in = reshape(ref_in,1,length(ref_in));
if length(data_in) ~= length(ref_in)
% 0. cross-correlate the received signal with its reference to extract the periods % 0. cross-correlate the received signal with its reference to extract the periods
corr = abs(ifft( fft(data_in(1:length(ref_in))).* conj(fft(ref_in)) )) ; corr = abs(ifft( fft(data_in(1:length(ref_in))) .* conj(fft(ref_in)) )) ;
% find max % find max
[~, peak] = max(corr) ; [~, peak] = max(corr) ;
peak=max(1,peak-1); peak=max(1,peak-1);
data_in = circshift(data_in,-peak) ; %! Dont (circ)shift the signal here (if signals are equally long) as this would remove the phase information!
%Y = data_in(peak:peak+(Nfft+obj.Ncp)*obj.Navg-1) ; %tested with a butterworth filter this exactly reconstructs the
%phase and the magnitude. However, the option is here
% data_in = circshift(data_in,-peak) ;
data_in = data_in(peak:peak+(Nfft+obj.Ncp)*obj.Navg-1) ;
end end
% 1. Reshape signal to a matrix to support noise averaging % 1. Reshape signal to a matrix to support noise averaging
Nfft = 2*obj.Nacq + 1 ;
Y = reshape(data_in, Nfft+obj.Ncp, obj.Navg).' ; Y = reshape(data_in, Nfft+obj.Ncp, obj.Navg).' ;

View File

@@ -110,6 +110,9 @@ classdef EQ
[signalclass_in.signal,error_log] = obj.process_(signalclass_in.signal', reference_signalclass_in.signal'); [signalclass_in.signal,error_log] = obj.process_(signalclass_in.signal', reference_signalclass_in.signal');
signalclass_in.signal = signalclass_in.signal'; signalclass_in.signal = signalclass_in.signal';
signalclass_in.fs = reference_signalclass_in.fs;
% append to logbook % append to logbook
lbdesc = ['EQ ']; lbdesc = ['EQ '];
signalclass_in = signalclass_in.logbookentry(lbdesc); signalclass_in = signalclass_in.logbookentry(lbdesc);

View File

@@ -124,6 +124,7 @@ classdef FFE_adaptive_decision < handle
d_hat(symbol,1) = obj.constellation(symbol_idx); d_hat(symbol,1) = obj.constellation(symbol_idx);
end end
y_buffer(symbol_idx,1) = y(symbol); y_buffer(symbol_idx,1) = y(symbol);
y_buffer(symbol_idx,:) = circshift(y_buffer(symbol_idx,:),1); y_buffer(symbol_idx,:) = circshift(y_buffer(symbol_idx,:),1);

View File

@@ -148,18 +148,19 @@ classdef VNLE < handle
y(symbol,1) = obj.e.' * x_in; % Calculating output of LMS __ * | y(symbol,1) = obj.e.' * x_in; % Calculating output of LMS __ * |
if training if training
err(symbol) = y(symbol) - d(symbol); % Instantaneous error err = y(symbol) - d(symbol); % Instantaneous error
else else
[~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point [~,symbol_idx] = min(abs(y(symbol) - obj.constellation)); % decision for closest constellation point
d_hat(symbol,1) = obj.constellation(symbol_idx); d_hat(symbol,1) = obj.constellation(symbol_idx);
err(symbol) = y(symbol) - d_hat(symbol); % Instantaneous error err = y(symbol) - d_hat(symbol); % Instantaneous error
end end
if ~all(mu==0,'all') %mu has not only zeros if ~all(mu==0,'all') %mu has not only zeros
obj.e = obj.e - (mu * err(symbol) * x_in) ; % Weight update rule of LMS % obj.e = obj.e - (mu * err * x_in) ; % Weight update rule of LMS
obj.e = obj.e - ( (mu * x_in) * err ) ; % Weight update rule of LMS
else else
normalizationfactor = (x_in.' * x_in); normalizationfactor = (x_in.' * x_in);
obj.e = obj.e - err(symbol) * x_in / normalizationfactor; % Weight update rule of NLMS obj.e = obj.e - err * x_in / normalizationfactor; % Weight update rule of NLMS
end end
if mod(sample,100) == 1 && showviz if mod(sample,100) == 1 && showviz
@@ -173,7 +174,7 @@ classdef VNLE < handle
drawnow; drawnow;
end end
obj.error(epoch,symbol) = err(symbol) * err(symbol)'; % Instantaneous square error obj.error(epoch,symbol) = err * err'; % Instantaneous square error
end end
end end

View File

@@ -203,6 +203,8 @@ classdef AwgKeysight
v = visadev('TCPIP0::localhost::hislip0::INSTR'); v = visadev('TCPIP0::localhost::hislip0::INSTR');
end end
disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
%check if channel config matches %check if channel config matches
writeline(v,'*opt?'); writeline(v,'*opt?');
aw=readline(v); aw=readline(v);

View File

@@ -47,8 +47,7 @@ classdef DC_supply
%connect to device %connect to device
v = visadev("GPIB1::19::INSTR"); v = visadev("GPIB1::19::INSTR");
writeline(v, '*IDN?;'); disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
disp(['DC Source: ' readline(v)]);
cmd = 'INST:SEL?'; cmd = 'INST:SEL?';
writeline(v, cmd); writeline(v, cmd);
@@ -109,13 +108,14 @@ classdef DC_supply
end end
% choose channel % choose channel
cmd = ['INST:SEL ',prev_selected_channel]; cmd = ['INST:SEL ',char(strtrim(prev_selected_channel))];
writeline(v, cmd); writeline(v, cmd);
%disconnect %disconnect
delete(v); delete(v);
catch catch
end end
end end
end end

View File

@@ -1,4 +1,4 @@
classdef OptAtten classdef OptAtten < handle
% control optical attenuator Keysight N7764a via LAN % control optical attenuator Keysight N7764a via LAN
% set parameters of optical attenuator, e.g. attenuation, wavelength, etc. and read out output power from attenuator % set parameters of optical attenuator, e.g. attenuation, wavelength, etc. and read out output power from attenuator
@@ -10,6 +10,14 @@ classdef OptAtten
avgTime %'Enter a desired averaging time [ms]. Higher averaging times will increase stability of the readings but will slow down measurement speed. Range: [2, 1000]'; avgTime %'Enter a desired averaging time [ms]. Higher averaging times will increase stability of the readings but will slow down measurement speed. Range: [2, 1000]';
dbOffset %'A non-zero attenuation offset shifts the logarithmic attenuation scale. Then, the set attenuation value differs from the internally calibrated attenuation. Range [-200, 200]'; dbOffset %'A non-zero attenuation offset shifts the logarithmic attenuation scale. Then, the set attenuation value differs from the internally calibrated attenuation. Range [-200, 200]';
psetOffset %'A non-zero power offset shifts the logarithnic power scale. Then, the power reading and the set power (Pset) values differ from the internal power calibration. Range [-60, 60]'; psetOffset %'A non-zero power offset shifts the logarithnic power scale. Then, the power reading and the set power (Pset) values differ from the internal power calibration. Range [-60, 60]';
atten_state
value_state
power_state
speed_state
wavelength_state
end end
methods (Access=public) methods (Access=public)
@@ -34,6 +42,7 @@ classdef OptAtten
end end
function success = set(obj,options) function success = set(obj,options)
arguments arguments
@@ -46,47 +55,47 @@ classdef OptAtten
%connect to device %connect to device
v = visadev('TCPIP::134.245.243.248::INSTR'); v = visadev('TCPIP::134.245.243.248::INSTR');
writeline(v, '*IDN?;'); disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
disp(['Active atten: ' readline(v)]); %Keysight Technologies, N7764A, MY49A00696, 1.13.1 %Keysight Technologies, N7764A, MY49A00696, 1.13.1
slot = 0; %init slot number slot = 0; %init slot number
%loop to set values for every attenuator slot %loop to set values for every attenuator slot
for i = 1:length(obj.active) for i = 1:length(options.active)
%convert index number i into slot number %convert index number i into slot number
slot = 2*i - 1; slot = 2*i - 1;
%check whether attenuator is used or unused %check whether attenuator is used or unused
if ~obj.active(i) %atten slot unused if ~options.active(i) %atten slot unused
writeline(v, [':OUTP' num2str(slot) ':STAT OFF']); writeline(v, [':OUTP' num2str(slot) ':STAT OFF']);
else %atten slot used (attenuation/const output power) else %atten slot used (attenuation/const output power)
%set attenuation or output power %set attenuation or output power
if obj.active(i) == 1 %attenuation if options.active(i) == 1 %attenuation
if obj.value(i) < 0 if options.value(i) < 0
obj.value(i) = 0; options.value(i) = 0;
hMsgBox = msgbox(['Value for attenuation out of range. Please consider minimum value. Attenuation set to ' num2str(obj.value(i)) 'dB']); hMsgBox = msgbox(['Value for attenuation out of range. Please consider minimum value. Attenuation set to ' num2str(options.value(i)) 'dB']);
uiwait(hMsgBox); uiwait(hMsgBox);
elseif obj.value(i) > 45 elseif options.value(i) > 45
obj.value(i) = 45; options.value(i) = 45;
hMsgBox = msgbox(['Value for attenuation out of range. Please consider maximum value. Attenuation set to ' num2str(obj.value(i)) 'dB']); hMsgBox = msgbox(['Value for attenuation out of range. Please consider maximum value. Attenuation set to ' num2str(options.value(i)) 'dB']);
uiwait(hMsgBox); uiwait(hMsgBox);
end end
writeline(v, [':OUTP' num2str(slot) ':POW:CONTR OFF']); writeline(v, [':OUTP' num2str(slot) ':POW:CONTR OFF']);
writeline(v, [':INP' num2str(slot) ':ATT ' num2str(obj.value(i)) 'dB']); writeline(v, [':INP' num2str(slot) ':ATT ' num2str(options.value(i)) 'dB']);
elseif obj.active(i) == 2 %constant output power elseif options.active(i) == 2 %constant output power
if obj.value(i) < -50 if options.value(i) < -50
obj.value(i) = -50; options.value(i) = -50;
hMsgBox = msgbox(['Value for output power out of range. Please consider minimum value. Output power set to ' num2str(obj.value(i)) 'dBm']); hMsgBox = msgbox(['Value for output power out of range. Please consider minimum value. Output power set to ' num2str(options.value(i)) 'dBm']);
uiwait(hMsgBox); uiwait(hMsgBox);
elseif obj.value(i) > 20 elseif options.value(i) > 20
obj.value(i) = 20; options.value(i) = 20;
hMsgBox = msgbox(['Value for output power out of range. Please consider maximum value. Output set to ' num2str(obj.value(i)) 'dBm']); hMsgBox = msgbox(['Value for output power out of range. Please consider maximum value. Output set to ' num2str(options.value(i)) 'dBm']);
uiwait(hMsgBox); uiwait(hMsgBox);
end end
writeline(v, [':OUTP' num2str(slot) ':POW:CONTR ON']); writeline(v, [':OUTP' num2str(slot) ':POW:CONTR ON']);
writeline(v, [':OUTP' num2str(slot) ':POW ' num2str(obj.value(i))]); writeline(v, [':OUTP' num2str(slot) ':POW ' num2str(options.value(i))]);
end end
%set value for speed %set value for speed
@@ -160,8 +169,8 @@ classdef OptAtten
pause(2); pause(2);
%read output power from attenuator and save to state.ouputpower %read output power from attenuator and save to state.ouputpower
for i = 1:length(obj.active) for i = 1:length(options.active)
if obj.active(i) if options.active(i)
%convert index number i into slot number %convert index number i into slot number
slot = 2*i - 1; slot = 2*i - 1;
@@ -174,11 +183,11 @@ classdef OptAtten
%create warning message when measured output power differs from %create warning message when measured output power differs from
%set output power by 2dB. %set output power by 2dB.
for i = 1:length(obj.active) for i = 1:length(options.active)
if obj.active(i) == 2 if options.active(i) == 2
%determine absolute difference %determine absolute difference
differ = abs(state.outputpower(i)-obj.value(i)); differ = abs(state.outputpower(i)-options.value(i));
%create msgbox when necessary %create msgbox when necessary
if differ >= 2 if differ >= 2
hMsgBox = msgbox(['Output Power at attenuator slot ' num2str(2) ' differs by 2dB or more!']); hMsgBox = msgbox(['Output Power at attenuator slot ' num2str(2) ' differs by 2dB or more!']);
@@ -188,22 +197,27 @@ classdef OptAtten
end end
%create output %create output
for i = 1:length(obj.active) silent = 0;
if obj.active(i) == 2 if silent
% Output power mode: for i = 1:length(options.active)
%differ = abs(state.outputpower(i)-obj.value(i)); if options.active(i) == 2
ch_info_txt = ['OptAtten: ',num2str(i),' -> Desired: ',num2str(obj.value(i)),' dBm; Cur Output: ',num2str(state.outputpower(i)),'dBm']; % Output power mode:
disp(ch_info_txt); %differ = abs(state.outputpower(i)-options.value(i));
else ch_info_txt = ['OptAtten: ',num2str(i),' -> Desired: ',num2str(options.value(i)),' dBm; Cur Output: ',num2str(state.outputpower(i)),'dBm'];
ch_info_txt = ['OptAtten: ',num2str(i),' -> Attenuated by: ',num2str(obj.value(i)),' dB; Cur Output: ',num2str(state.outputpower(i)),'dBm']; disp(ch_info_txt);
disp(ch_info_txt); else
end ch_info_txt = ['OptAtten: ',num2str(i),' -> Attenuated by: ',num2str(options.value(i)),' dB; Cur Output: ',num2str(state.outputpower(i)),'dBm'];
disp(ch_info_txt);
end
end
end end
%disconnect %disconnect
delete(v); delete(v);
obj.readvals();
catch error catch error
%disconnect if error occurrs %disconnect if error occurrs
@@ -216,57 +230,51 @@ classdef OptAtten
end end
function readvals(obj) function readvals(obj,options)
arguments
obj
options.print2console = 0;
end
try try
%connect to device %connect to device
v = visadev('TCPIP::134.245.243.248::INSTR'); v = visadev('TCPIP::134.245.243.248::INSTR');
writeline(v, '*IDN?;'); cnt = 1;
disp(['Active atten: ' readline(v)]); %Keysight Technologies, N7764A, MY49A00696, 1.13.1
power=[];
for s = 1:2:7 for s = 1:2:7
writeline(v, [':OUTP' num2str(s) ':STAT?']);
line = readline(v);
answer = sscanf(line,'%f');
disp(['Slot ' num2str(s) ' enabled state: ' num2str(answer)]);
writeline(v, [':OUTP' num2str(s) ':POW?']); writeline(v, [':OUTP' num2str(s) ':POW?']);
line = readline(v); line = readline(v);
answer = sscanf(line,'%f'); answer = sscanf(line,'%f');
disp(['P_set (output power) for Slot ' num2str(s) ': ' num2str(answer) ' dBm']); obj.value_state(cnt) = answer;
writeline(v, [':OUTP' num2str(s) ':POW:CONTR?']); writeline(v, [':READ' num2str(s) ':POW?']);
line = readline(v); line = readline(v);
answer = sscanf(line,'%f'); answer = sscanf(line,'%f');
disp(['Power control for Slot ' num2str(s) ': ' num2str(answer)]); obj.power_state(cnt) = answer;
if answer == 1 writeline(v, [':READ' num2str(s) ':POW?']);
writeline(v, [':READ' num2str(s) ':POW?']); line = readline(v);
line = readline(v); answer = sscanf(line,'%f');
answer = sscanf(line,'%f'); obj.power_state(cnt) = answer;
disp([' -> Slot ' num2str(s) ' desired outut power: ' num2str(answer) ' dBm']);
else writeline(v, [':INP' num2str(s) ':ATT?']);
writeline(v, [':INP' num2str(s) ':ATT?']); line = readline(v);
line = readline(v); answer = sscanf(line,'%f');
answer = sscanf(line,'%f'); obj.atten_state(cnt) = answer;
disp([' -> Alpha (fix attenuation) for slot ' num2str(s) ': ' num2str(answer) ' dB']);
end
writeline(v, [':INP' num2str(s) ':WAV?']); writeline(v, [':INP' num2str(s) ':WAV?']);
line = readline(v); line = readline(v);
answer = sscanf(line,'%f'); answer = sscanf(line,'%f');
disp(['Wavelength for Slot ' num2str(s) ': ' num2str(answer) ' nm']); obj.wavelength_state(cnt) = answer;
writeline(v, [':OUTP' num2str(s) ':ATIM?']); writeline(v, [':INP' num2str(s) ':WAV?']);
line = readline(v); line = readline(v);
answer = sscanf(line,'%f'); answer = sscanf(line,'%f');
disp(['Averaging time for Slot ' num2str(s) ': ' num2str(answer) ' s']); obj.speed_state(cnt) = answer;
fprintf('\n') cnt = cnt+1;
end end
delete(v); delete(v);

View File

@@ -8,6 +8,7 @@ classdef ScopeKeysight
channel channel
autoScale autoScale
extRef extRef
removeDC
interpolate interpolate
recordLen recordLen
IPaddress IPaddress
@@ -25,6 +26,7 @@ classdef ScopeKeysight
options.channel logical = [0,0,0,0]; options.channel logical = [0,0,0,0];
options.autoScale logical = 0; options.autoScale logical = 0;
options.extRef logical = 1; options.extRef logical = 1;
options.removeDC logical = 1;
options.interpolate logical = 0; options.interpolate logical = 0;
options.recordLen double = 1000000; options.recordLen double = 1000000;
options.IPaddress options.IPaddress
@@ -169,11 +171,21 @@ classdef ScopeKeysight
recordedSignals = cell(size(obj.channel)); recordedSignals = cell(size(obj.channel));
for n = find(obj.channel == 1) for n = find(obj.channel == 1)
% record
recordedSignals{n} = obj.readChannel(v,n); recordedSignals{n} = obj.readChannel(v,n);
% cut "safety samples" that were added at the end
recordedSignals{n} = recordedSignals{n}(1:obj.recordLen); recordedSignals{n} = recordedSignals{n}(1:obj.recordLen);
if obj.removeDC
recordedSignals{n} = recordedSignals{n}-mean(recordedSignals{n});
end
obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n)); obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n));
end end
% fill all other channels with nothing
for n = find(obj.channel == 0) for n = find(obj.channel == 0)
recordedSignals{n} = []; recordedSignals{n} = [];
end end
@@ -181,6 +193,16 @@ classdef ScopeKeysight
obj.writeNcheck(v,sprintf(':%s',scope_state)); obj.writeNcheck(v,sprintf(':%s',scope_state));
obj.writeNcheck(v,'*OPC?'); obj.writeNcheck(v,'*OPC?');
opdone = 0;
acqdone = 0;
procdone = 0;
while ~opdone || ~acqdone || ~procdone
opdone = sscanf(obj.writeReceiveCheck(v,'*opc?'), '%f');
acqdone = sscanf(obj.writeReceiveCheck(v,'ader?'), '%f');
procdone = sscanf(obj.writeReceiveCheck(v,'pder?'), '%f');
pause(0.005);
end
end end
end end

View File

@@ -1 +0,0 @@

View File

@@ -0,0 +1,146 @@
%%% SIR Sweep for MPI Experiment %%%
params = struct;
params.i_atten = 10;
wh = DataStorage(params);
wh.addStorage("ber");
wh.addStorage("sir");
wh.addStorage("pd_in");
playandrecord = 0;
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active
M = 4;
pn_key = 2;
usemrds = 0;
fdac = 92e9;
fsym = 92e9;
fadc = 160e9;
rrcalpha = 0.05;
v_bias = 2.27;
i_atten = 40;
pd_in_desired = 7;
disp(['Start Measurement of ',num2str(prod(wh.dim)),' loops...'])
%%%%% SET Volatges %%%%%%
dcs = DC_supply("active",[1,1],"voltage",[v_bias, 9]);
dcs.set("voltage",[v_bias, 9]);
voa = OptAtten("active",[0,2,1,1],"value",[0,pd_in_desired,0,i_atten],"wavelength",[1310,1310,1310,1310]);
voa.set('active',[0,2,1,1],'value',[0,pd_in_desired,0,i_atten]);
voa.readvals();
%%%%% SET Volatges %%%%%%
if 1
precomp_path = "C:\Users\sioe\Documents\MATLAB\imdd_simulation\projects\standard_system\";
precomp_fn = "lab_mpi_setup_2";
else
precomp_path = "C:\Users\sioe\Documents\MATLAB\model-collection\sioe_models\Labor_2024\Lab_PAM4\";
precomp_fn = "precomp_bla__loop1_1";
end
%%%%% Symbol Generation %%%%%%
Pform = Pulseformer("fsym",fsym,"fdac",4*fsym,"pulse","rrc","pulselength",16,"rrcalpha",rrcalpha);
[Digi_sig,Symbols,Bits] = PAMsource("fsym",fsym,"M",M,"order",18,"useprbs",1,...
"fs_out",fdac,"applyclipping",0,"clipfactor",1.7,...
"applypulseform",0,"pulseformer",Pform,"randkey",pn_key,...
"db_precode",0,...
"mrds_code",usemrds,"mrds_blocklength",512).process();
if precomp_mode == 1 % measure channel
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = freqresp.buildOFDM();
elseif precomp_mode == 2 % apply precomp
freqresp = ChannelFreqResp("Nacq",1024,"Navg",64,"Ncp",63,'f_ref',Digi_sig.fs);
Digi_sig = freqresp.precomp(Digi_sig,'maxampdb',3,'loadPath',precomp_path,'fileName',precomp_fn);
end
%%%%% AWG %%%%%%
AWG = AwgKeysight("model","M8196A","fdac",fdac,"scaletodac",[1,1,1,1],"skews",[0,0,0,0],"voltages",[0,0,0,0.62]);
AWG.upload("signal4",Digi_sig);
for i_atten = wh.parameter.i_atten.values
%%%%% SET ATTENUATOR %%%%%%
voa.set('active',[0,2,1,1],'value',[0,7,0,i_atten]);
%%%%% Scope %%%%%%
SCP = ScopeKeysight("model","DSAZ634A",'autoscale',1,"fadc",'GSa_160',"channel",[1],"recordLen",2000000,"removeDC",1);
Scpe_sig = SCP.read();
Scpe_sig = Electricalsignal(Scpe_sig{1},"fs",fadc);
% Scpe_sig.spectrum("displayname",'Rx Signal','fignum',10);
%%%%%% Sample to 2x fsym %%%%%%
Scpe_sig = Scpe_sig.resample("fs_in",160e9,"fs_out",2*92e9);
if precomp_mode == 1
freqresp.estimate(Scpe_sig,"save",true,"savePath",precomp_path,"fileName",precomp_fn);
freqresp.plot();
end
%%%%%% Sync Rx signal with reference %%%%%%
[Scpe_sig,S] = Scpe_sig.tsynch("reference",Symbols,"fs_ref",fsym);
Scpe_sig.eye(fsym,M);
%%%%% EQUALIZE %%%%%%
Eq_ffe_only = FFE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0);
ber_ffe_only = runEQ(Eq_ffe_only,Scpe_sig,Symbols,Bits,M);
Eq_move_it = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.05,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
ber_move_it = runEQ(Eq_move_it,Scpe_sig,Symbols,Bits,M);
Eq_nonlin = EQ("Ne",[50,7,7],"Nb",[0,0,0],"training_length",4096*2,"training_loops",5,"dd_loops",5,"K",2,"DCmu",0.0,"DDmu",[0.0004 0.0004 0.0004 0.0004 ],"DFEmu",0.005,"FFEmu",0,"plotfinal",0,"ideal_dfe",1);
%VNLE("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",[0.0004 0.0005 0.0006],"mu_tr",0,"order",[50,7,7],"sps",2,"decide",0);
ber_nonlin = runEQ(Eq_nonlin,Scpe_sig,Symbols,Bits,M);
Eq_adaptive_decision = FFE_adaptive_decision("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0,"buffer_length",80);
ber_adaptive_decision = runEQ(Eq_adaptive_decision,Scpe_sig,Symbols,Bits,M);
FFE_FFDCAVG("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0,"mu_buff",128);
ber_ff_dcavg = runEQ(FFE_FFDCAVG,Scpe_sig,Symbols,Bits,M);
Eq_feedback_removal = FFE_DCremoval("epochs_tr",5,"epochs_dd",5,"len_tr",4096*2,"mu_dd",1e-4,"mu_tr",0,"order",25,"sps",2,"decide",0,"mu_dc",0.05,"dc_buffer_len",1);
ber_feedback_removal = runEQ(Eq_feedback_removal,Scpe_sig,Symbols,Bits,M);
sir = voa.power_state(3)-voa.power_state(4);
pd_in = voa.power_state(2);
disp(['BER: ',sprintf('%.1E',ber_eq),' | SIR: ',num2str(sir),' dB | PD_in: ',num2str(pd_in),' dBm']);
wh.addValueToStorage(ber_eq,'ber',i_atten);
wh.addValueToStorage(sir,'sir',i_atten);
wh.addValueToStorage(pd_in,'pd_in',i_atten);
end
cols = linspecer(8);
sir_vals = wh.parameter.i_atten.values;
bers = wh.getStoValue('ber',sir_vals);
figure(44);
a = gca;
hold on; % Retain the plot so new points can be added without complete redraw
plot(sir_vals,bers,"LineWidth",0.5,"LineStyle","-","Marker",".","MarkerSize",15,"DisplayName","FFE only");
yline(3.8e-3,'DisplayName','HD-FEC','LineStyle','--','HandleVisibility','off');
xlabel('Received Optical Power (dBm)');
ylabel('Bit Error Rate (BER)');
title('Bit Error Rate vs. ROP');
set(gca,'yscale','log');
set(gca,'Box','on');
grid on;
grid minor
legend

13
projects/Lab_2024/runEQ.m Normal file
View File

@@ -0,0 +1,13 @@
function BER = runEQ(Eq_class,Scpe_sig,Symbols,Bits,M)
[EQ_sig] = Eq_class.process(Scpe_sig,Symbols);
error = EQ_sig-Symbols;
error.spectrum("displayname",['Error PSD after: ',inputname(1),' '],'fignum',564);
Rx_bits = PAMmapper(M,0).demap(EQ_sig);
[~,errors_bm,BER,errors] = calc_ber(Rx_bits.signal,Bits.signal,"skip_front",100,"skip_end",150,"returnErrorLocation",1);
end

View File

@@ -4,9 +4,9 @@ params = struct;
params.M = [4]; params.M = [4];
params.datarate = [224]; params.datarate = [224];
params.rop = [-5]; params.rop = [-12:-7];
precomp_mode = 2; %0=do nothing ; 1= measure; 2=precomp active precomp_mode = 0; %0=do nothing ; 1= measure; 2=precomp active
if ismac if ismac
precomp_path = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/standard_system"; precomp_path = "/Users/silasoettinghaus/Documents/MATLAB/imdd_simulation/projects/standard_system";
@@ -165,7 +165,7 @@ for M = wh.parameter.M.values
for i = 1:i_ for i = 1:i_
rop=wh.parameter.rop.values(i); rop=wh.parameter.rop.values(i);
wh.addValueToStorage(ber_ffe(i) ,'ber_ffe',M,datarate,rop); wh.addValueToStorage(ber_ffe(i),'ber_ffe',M,datarate,rop);
end end
@@ -182,7 +182,6 @@ cols = linspecer(8);
%cnt = cnt+1; %cnt = cnt+1;
ber_ffe = wh.getStoValue('ber_ffe',M,datarate,wh.parameter.rop.values); ber_ffe = wh.getStoValue('ber_ffe',M,datarate,wh.parameter.rop.values);
% Create the initial plot % Create the initial plot
figure(44); figure(44);
@@ -190,8 +189,6 @@ a = gca;
hold on; % Retain the plot so new points can be added without complete redraw hold on; % Retain the plot so new points can be added without complete redraw
plot(wh.parameter.rop.values,ber_ffe,"LineWidth",0.5,"LineStyle","-","Marker",".","MarkerSize",15,"DisplayName","FFE only"); plot(wh.parameter.rop.values,ber_ffe,"LineWidth",0.5,"LineStyle","-","Marker",".","MarkerSize",15,"DisplayName","FFE only");
yline(3.8e-3,'DisplayName','HD-FEC','LineStyle','--','HandleVisibility','off'); yline(3.8e-3,'DisplayName','HD-FEC','LineStyle','--','HandleVisibility','off');
xlabel('Received Optical Power (dBm)'); xlabel('Received Optical Power (dBm)');
ylabel('Bit Error Rate (BER)'); ylabel('Bit Error Rate (BER)');

Binary file not shown.

Binary file not shown.