Merge branch 'main' of cau-git.rz.uni-kiel.de:nt/mitarbeiter/silas/imdd_simulation

# Conflicts:
#	Classes/01_transmit/ChannelFreqResp.m
#	projects/400G_FTN_setups/imdd_mpi_dsp.m
This commit is contained in:
sioe
2024-11-04 09:09:57 +01:00
225 changed files with 30011 additions and 155 deletions

View File

@@ -27,7 +27,7 @@ classdef Signal
[~,obj.gitSHA] = system('git rev-parse HEAD');
[~,obj.gitStatus] = system('git status --porcelain');
[~,obj.gitPatch] = system('git diff');
% [~,obj.gitPatch] = system('git diff');
%%% Stuff for Logbook %%%
SignalType = [];
@@ -510,7 +510,7 @@ classdef Signal
end
%%
function [obj,S] = tsynch(obj,options)
function [obj,S,isFlipped] = tsynch(obj,options)
% time sync and cut
arguments
obj Signal
@@ -525,14 +525,16 @@ classdef Signal
q = obj.fs/options.fs_ref;
b = options.reference.resample("fs_in",options.fs_ref,"fs_out",obj.fs).normalize("mode","oneone").signal;
max_occurences = floor(length(a)/length(b));
%estimate delay between signals
[co,lags] = xcorr(a,b);
[~,pos] = max(co);
[~,pos] = max(abs(co));
D = lags(pos);
%estimate start pos of signal
maxpeaknum = floor(length(a)/length(b));
[pks,pkpos] = findpeaks(co./max(co),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum);
[pks,pkpos] = findpeaks(abs(co./max(co)),'MinPeakDistance',length(b)/2,'MinPeakHeight',0.2,'NPeaks',maxpeaknum);
shifts = lags(pkpos);
%Cut occurences of ref signal from signal (only positive shifts)
@@ -543,9 +545,19 @@ classdef Signal
S{end+1,1} = sig;
end
%
isFlipped=0;
if all(sign(co(pkpos)))
isFlipped = 1;
end
%return/keep the sinal with the highest correlation (only within positive shifts)
[~,idx]=max(pks(shifts>0));
obj.signal = S{idx}.signal;
%put signal with highest corr. to first index in S array
swap = S{1};
S{1} = S{idx};
S{idx} = swap;
for c = 1:numel(shifts(shifts>0))
S{c}.logbook = [];

View File

@@ -77,9 +77,42 @@ classdef PAMsource
bitpattern=[];
if obj.useprbs
for i = 1:log2(obj.M)
[bitpattern(:,i),seed] = prbs(O,N,seed);
% for i = 1:log2(obj.M)
% [bitpattern(:,i),seed] = prbs(O,N,seed);
% end
%%%%% MOVE-IT PRMS %%%%
state = struct();
para = struct();
if obj.M == 6
para.bl = 2^(obj.order-2);
para.dimension = 5;
else
para.bl = 2^(obj.order-1);
para.dimension = log2(obj.M); %2.5bits/sym -> 2 bit/sym
end
para.rand = 0;
para.order = floor(obj.order / log2(obj.M));
para.skip =0;
para.bruijn = 0;
para.reset_prms = 0;
para.method = 1;
data_in = [];
global loop;
loop = 0;
[data_out,state_] = prms(data_in, state, para);
loop = 1;
[data_out,state_out] = prms(data_in, state_, para);
bitpattern = data_out';
%%%%% END MOVE-IT %%%%%%%
else
s = RandStream('twister','Seed',obj.randkey);
for i = 1:log2(obj.M)
@@ -88,7 +121,7 @@ classdef PAMsource
end
if obj.M == 6
bitpattern = reshape(bitpattern,[],1);
bitpattern = reshape(bitpattern',[],1);
bitpattern = bitpattern(1:end-mod(length(bitpattern),5));
end
@@ -108,7 +141,7 @@ classdef PAMsource
end
% figure(12);hold on;histogram(symbols.signal,'Normalization','probability');
if obj.mrds_code
symbols = MRDS_coding("blocklength",obj.mrds_blocklength).encode(symbols);
end
@@ -128,7 +161,7 @@ classdef PAMsource
%%%%% Re-sample to f DAC %%%%%%
digi_sig = digi_sig.resample("fs_in",digi_sig.fs,"fs_out",obj.fs_out,"n",10,"beta",5);
% digi_sig.spectrum("fignum",111,"displayname","after pulseforming");
% digi_sig.spectrum("fignum",111,"displayname","after pulseforming");
%%%%% Hard clip digital signal to PAM range before DAC %%%%%%
if obj.applyclipping

View File

@@ -125,6 +125,13 @@ classdef Duobinary
%make bipolar
data = (data-round(mean(data),1));
[unique_points, ~, idx] = unique(data);
counts = accumarray(idx, 1);
total_samples = numel(data);
probabilities = counts / total_samples;
mean_power = sum((unique_points .^ 2) .* probabilities);
scaling_factor = sqrt(mean_power);
if M == 4
data = data ./ sqrt(2.5); % 7-level constellation weighted with probability after DB code i.e. mean([-3 3 -2 -2 2 2 -1 -1 -1 1 1 1 0 0 0 0].^2) = 2.5 --> sqrt(2.5) == rms(constellation)
elseif M == 6
@@ -164,11 +171,11 @@ classdef Duobinary
elseif I == 11
%todo
data = data .* sqrt(5.8);
warning('Check if PAM16 implementation, mapping and scaling is correct!')
warning('Check db decode implementation, mapping and scaling is correct!')
elseif I == 15
data = data .* sqrt(10.5);
elseif I == 16
warning('Check if PAM16 implementation, mapping and scaling is correct!')
warning('Check db decode implementation, mapping and scaling is correct!')
end
data = round(data);

View File

@@ -1,4 +1,4 @@
classdef EQ
classdef EQ %< handle
%EQ Summary of this class goes here
% Detailed explanation goes here

View File

@@ -7,11 +7,12 @@ classdef Awg2Scope
Scope
mapping;
waitUntilClick
end
methods (Access=public)
function obj = Awg2Scope(Awg,Scope,mapping)
function obj = Awg2Scope(Awg,Scope,mapping,options)
%Simple class to call the Awg and Scope and map the signals
%accordingly in the correct formats with correct l
% ogbook
@@ -21,16 +22,19 @@ classdef Awg2Scope
Awg
Scope
mapping
options.waitUntilClick = 0;
end
obj.Awg = Awg;
obj.Scope = Scope;
obj.mapping = mapping; % AWG CH [1,2,3,4] -> Scope CH [0,0,0,1]
obj.waitUntilClick = options.waitUntilClick;
end
function [S1,S2,S3,S4] = process(obj,channels)
function [S1,S2,S3,S4] = process(obj,channels, options)
arguments
obj
@@ -41,15 +45,33 @@ classdef Awg2Scope
channels.signal4 Informationsignal = Informationsignal([])
% add new optional arguments here
options.waitUntilClick = obj.waitUntilClick;
end
%%% UPLOAD TO AWG %%%
[S1,S2,S3,S4]=obj.Awg.upload("signal1",channels.signal1,...
"signal2",channels.signal2,...
"signal3",channels.signal3,...
"signal4",channels.signal4...
);
%%% UPLOAD TO AWG %%%
scpe_sig_cell = obj.Scope.read();
%%% READ FROM SCOPE %%%
scpe_sig_cell = obj.Scope.read("waitUntilClick",options.waitUntilClick);
%%% READ FROM SCOPE %%%
% Map Scope measurement to output signal
% mapping index is the AWG chanel and mapping number is the

View File

@@ -176,7 +176,11 @@ classdef AwgKeysight
% The waveform granularity is e.g. 128. This means that the waveform length must be a multiple of this granularity. The minimum waveform length is 128 samples.
if rem(length(signal{s}),obj.waveformGranularity) ~= 0
signal{s} = [signal{s} signal{s}(:,1:(obj.waveformGranularity-rem(length(signal{s}),obj.waveformGranularity)))];
warning(['data should have a length multiple of ',num2str(obj.waveformGranularity),'!']);
debug = 0;
if debug
warning(['data should have a length multiple of ',num2str(obj.waveformGranularity),'!']);
end
end
% Digitally apply skews to the signals
@@ -237,7 +241,7 @@ classdef AwgKeysight
obj.writeNcheck(v,sprintf(':FREQuency:RASTer %.15g;', obj.fdac));
case awg_model.M8199B
obj.writeNcheck(v,':ABORt ''M2'''); %war auf M2, das wird wohl der CH sein oder?
obj.writeNcheck(v,':ABORt ''M2''');
obj.writeNcheck(v,sprintf(':FREQ ''M1.ClkGen'', %.15g;', obj.fdac));
end
@@ -301,6 +305,14 @@ classdef AwgKeysight
end
else
% If no signal defined, turn off channel
switch obj.model
case awg_model.M8199B
obj.writeNcheck(v, sprintf(':OUTP ''M2.DataOut%d'', OFF',chan));
end
end
end
@@ -313,8 +325,8 @@ classdef AwgKeysight
case awg_model.M8199B
% SET Ref clock out (which is conn. to scope) to 100 MHz
obj.writeNcheck(v, ':OUTPut:FREQuency ''M1.RefClkOut'',100000000');
% SET Ref clock out (which is conn. to scope) to 10 MHz
obj.writeNcheck(v, ':OUTPut:FREQuency ''M1.RefClkOut'',10000000');
% :OUTP:GLOB 'M1.System', OFF
obj.writeNcheck(v, ':OUTP:GLOB ''M1.System'', ON');

View File

@@ -51,90 +51,90 @@ classdef DC_supply < handle
success = [0,0];
try
% %connect to device
% if exist('v','var')
% %v = visadev("GPIB1::19::INSTR");
% v = obj.connectDevice();
% else
%
% end
% %connect to device
% if exist('v','var')
% %v = visadev("GPIB1::19::INSTR");
% v = obj.connectDevice();
% else
%
% end
v = visadev("GPIB1::19::INSTR");
v = visadev("GPIB1::19::INSTR");
debug = 0;
if debug
disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
end
debug = 0;
if debug
disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
end
cmd = 'INST:SEL?';
cmd = 'INST:SEL?';
writeline(v, cmd);
prev_selected_channel = readline(v);
for ch = 1:2
% choose channel
cmd = ['INST:SEL OUT',num2str(ch)];
writeline(v, cmd);
prev_selected_channel = readline(v);
for ch = 1:2
% get current voltage level
cmd = 'VOLT?';
writeline(v, cmd);
act_volt = str2num(readline(v));
% choose channel
cmd = ['INST:SEL OUT',num2str(ch)];
writeline(v, cmd);
% desired voltage (round to two digits after comma)
des_volt = round(options.voltage(ch),2);
cnt = 0;
while abs(act_volt-des_volt) > 0
selected_channel = ['OUT',num2str(ch)];
% get current voltage level
cmd = 'VOLT?';
writeline(v, cmd);
act_volt = str2num(readline(v));
% desired voltage (round to two digits after comma)
des_volt = round(options.voltage(ch),2);
% difference
diff_volt = act_volt-des_volt;
cnt = 0;
while abs(act_volt-des_volt) > 0
selected_channel = ['OUT',num2str(ch)];
% get current voltage level
cmd = 'VOLT?';
writeline(v, cmd);
act_volt = str2num(readline(v));
% difference
diff_volt = act_volt-des_volt;
% set new voltage
increment_voltage = -0.01* sign(diff_volt) ;
cmd = ['VOLT ',num2str(act_volt+increment_voltage)];
writeline(v, cmd);
cnt = cnt+1;
if mod(cnt,100) == 0
wait(1);
end
% get current voltage level
cmd = 'VOLT?';
writeline(v, cmd);
act_volt = str2num(readline(v));
% set new voltage
increment_voltage = -0.01* sign(diff_volt) ;
cmd = ['VOLT ',num2str(act_volt+increment_voltage)];
writeline(v, cmd);
cnt = cnt+1;
if mod(cnt,100) == 0
pause(1);
end
% check if voltage is set
if act_volt ~= des_volt
hMsgBox = msgbox('An error occurred in dc supply module. Check if voltage is set correctly.');
uiwait(hMsgBox);
else
success(ch) = 1;
end
% get current voltage level
cmd = 'VOLT?';
writeline(v, cmd);
act_volt = str2num(readline(v));
end
% choose channel
cmd = ['INST:SEL ',char(strtrim(prev_selected_channel))];
writeline(v, cmd);
% check if voltage is set
if act_volt ~= des_volt
hMsgBox = msgbox('An error occurred in dc supply module. Check if voltage is set correctly.');
uiwait(hMsgBox);
else
success(ch) = 1;
end
%disconnect
delete(v);
catch
end
% choose channel
cmd = ['INST:SEL ',char(strtrim(prev_selected_channel))];
writeline(v, cmd);
%disconnect
delete(v);
end
function [voltage,current] = readVals(obj)

View File

@@ -1,8 +1,14 @@
classdef Exfo_laser
classdef Exfo_laser < handle
properties(Access=private)
serialport_number
mainframe_channel
end
properties(Access=public)
wavelength
power
cur_state
cur_wavelength
cur_power
safety_mode
end
methods (Access=public)
@@ -11,8 +17,9 @@ classdef Exfo_laser
arguments
options.wavelength = 1310; %dbm
options.power = -10; %dbm
options.safety_mode = 1;
options.serialport_number = 'COM8';
options.mainframe_channel = 1;
end
%
@@ -23,52 +30,330 @@ classdef Exfo_laser
end
end
end
function success = set(obj,options)
arguments
obj
options.wavelength = obj.wavelength; %dbm
options.power = obj.power; %dbm
end
% Connect to the laser
o = serialport("COM8", 9600);
configureTerminator(o, "CR"); % Set the terminator to carriage return (CR)
o = serialport(obj.serialport_number, 9600);
configureTerminator(o, "CR", "CR"); % Set the terminator to carriage return (CR)
flush(o);
writeline(o, "*IDN?");
pause(1);
if o.NumBytesAvailable ~= 0
disp(['Laser Mainframe: ', readline(o)]);
answ = readline(o);
if obj.safety_mode
disp(['Yay! We can talk to Instrument: ',char(answ)]);
end
% Read states the first time
obj.cur_state = obj.getLaserStatus_(o,obj.mainframe_channel);
obj.cur_wavelength = obj.getLaserWavelength_(o,obj.mainframe_channel);
obj.cur_power = obj.getLaserPower_(o,obj.mainframe_channel);
clear o;
if obj.safety_mode
warning("Safety_mode ON: Display all information. Ask when switching laser. Turn safety_mode off in class instance or during initialization Exfo_laser(...,'safety_mode',0)");
else
error('No connection to the mainframe');
clear o;
warning("safety_mode OFF: EVERYTHING IS EXECUTED WITHOUT ASKING :-) BE SURE WHAT YOU DO");
end
end
function [isEnabled,power,lambda] = getLaserInfo(obj)
o = obj.connectLaser_();
isEnabled = obj.getLaserStatus_(o,obj.mainframe_channel);
power = obj.getLaserPower_(o,obj.mainframe_channel);
lambda = obj.getLaserWavelength_(o,obj.mainframe_channel);
end
function success = enableLaser(obj)
success = 0;
o = obj.connectLaser_();
if obj.safety_mode
% Prompt the user to enable the laser
choice = questdlg('Do you want to enable the laser?', ...
'Enable Laser', ...
'Yes', 'No', 'No');
else
choice = 'Yes';
end
% Handle the response
switch choice
case 'Yes'
% Enable the laser on channel 1
success = obj.enableLaser_(o,obj.mainframe_channel);
disp('Laser enabled.');
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains disabled.');
end
end
% Function to set the wavelength of the laser
function setLaserWavelength(~,serialObj, channel, wavelength)
command = ['CH', num2str(channel), ':L=', num2str(wavelength)];
writeline(serialObj, command);
pause(0.5); % Allow time for the wavelength to change
function success = disableLaser(obj)
success = 0;
o = obj.connectLaser_();
if obj.safety_mode
% Prompt the user to enable the laser
choice = questdlg('Do you want to disable the laser?', ...
'Enable Laser', ...
'Yes', 'No', 'No');
else
choice = 'Yes';
end
% Handle the response
switch choice
case 'Yes'
% Enable the laser on channel 1
success = obj.disableLaser_(o,obj.mainframe_channel);
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains enabled.');
end
end
function success = setPower(obj,desiredPower)
success = 0;
o = obj.connectLaser_();
if obj.safety_mode
% Prompt the user to enable the laser
choice = questdlg(['Do you want to set the laser to ', num2str(desiredPower) ,' dBm?'], ...
'SET POWER', ...
'Yes', 'No', 'No');
else
choice = 'Yes';
end
% Handle the response
switch choice
case 'Yes'
% Enable the laser on channel 1
success = obj.setLaserPower_(o,obj.mainframe_channel,desiredPower);
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains at power.');
end
end
function success = setWavelength(obj,desriedLambda)
success = 0;
o = obj.connectLaser_();
if obj.safety_mode
% Prompt the user to enable the laser
choice = questdlg(['Do you want to set the laser wavelength to ', num2str(desriedLambda) ,' nm?'], ...
'SET WAVELENGTH', ...
'Yes', 'No', 'No');
else
choice = 'Yes';
end
% Handle the response
switch choice
case 'Yes'
% Enable the laser on channel 1
success = obj.setLaserWavelength_(o,obj.mainframe_channel,desriedLambda);
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains at wavelength.');
end
end
end %public mehtods
methods (Access=private)
function serialobj = connectLaser_(obj)
% Connect to the laser
serialobj = serialport(obj.serialport_number, 9600);
configureTerminator(serialobj, "CR", "CR"); % Set the terminator to carriage return (CR)
flush(serialobj);
writeline(serialobj, "*IDN?");
answ = readline(serialobj);
if obj.safety_mode
disp(['Yay! We can talk to Instrument: ',char(answ)]);
end
end
% Function to GET the STATE of the laser
function isEnabled = getLaserStatus_(obj,serialObj, channel)
writeline(serialObj, ['CH', num2str(channel), ':ENABLE?']); % Query current wavelength
manual_flush = 1;
while manual_flush
response = readline(serialObj);
manual_flush = contains(response, {'OK'});
end
isEnabled = 0;
isEnabled = contains(response, {'ENABLED'});
isDisabled = 0;
isDisabled = contains(response, {'DISABLED'});
if isEnabled && ~isDisabled
obj.cur_state = isEnabled;
elseif ~isEnabled && isDisabled
obj.cur_state = isEnabled;
else
error(['Unknown Laser State ->', char(response)]);
end
if obj.safety_mode
if isEnabled
disp(['Laser ', num2str(channel) ,' is currently ON -> ', char(response)]);
elseif isDisabled
disp(['Laser ', num2str(channel) ,' is currently OFF ->', char(response)]);
else
error(['Unknown Laser State ->', char(response)]);
end
end
end
% Function to GET the wavelength of the laser
function current_wavelen = getLaserWavelength_(obj,serialObj, channel)
writeline(serialObj, ['CH', num2str(channel), ':L?']); % Query current wavelength
current_wavelen = readline(serialObj);
disp(['Current Wavelength: ', current_wavelen]);
response = readline(serialObj);
current_wavelen = str2double(regexp(response, '\d+\.\d+', 'match', 'once'));
if obj.safety_mode
disp(['Current Laser ', num2str(channel) ,' Wavelength: ', num2str(current_wavelen),' --> ',char(response)]);
end
obj.cur_wavelength = current_wavelen;
end
% Function to set the laser power
function setLaserPower(~,serialObj, channel, power_dBm)
command = ['CH', num2str(channel), ':P=', num2str(power_dBm)];
writeline(serialObj, command);
pause(0.2); % Allow time for power to adjust
% Function to GET the laser power
function powerValue = getLaserPower_(obj,serialObj, channel)
writeline(serialObj, ['CH', num2str(channel), ':P?']); % Query current power
current_power = readline(serialObj);
disp(['Current Power: ', current_power, ' dBm']);
response = readline(serialObj);
isDisabled = contains(response, 'Disabled');
if ~isDisabled
powerValue = str2double(regexp(response, '\d+\.\d+', 'match', 'once'));
else
powerValue = -200;
end
if obj.safety_mode
disp(['Current Laser ', num2str(channel) ,' Power: ', num2str(powerValue), ' dBm --> ',char(response)]);
end
obj.cur_power = powerValue;
end
% Function to enable the laser
function success = enableLaser_(obj,serialObj,channel)
success = 0;
isEnabled = obj.getLaserStatus_(serialObj,obj.mainframe_channel);
writeline(serialObj, ['CH',num2str(channel),':ENABLE']);
response = readline(serialObj);
isok = contains(response, {'OK'});
cnt=0;
while ~isEnabled || cnt>10
isEnabled = obj.getLaserStatus_(serialObj,obj.mainframe_channel);
pause(0.2);
cnt = cnt+1;
end
if ~isEnabled
error('Laser not enabled but command was send')
else
success = 1;
end
end
% Function to enable the laser
function success = disableLaser_(obj,serialObj,channel)
success = 0;
isEnabled = obj.getLaserStatus_(serialObj,obj.mainframe_channel);
writeline(serialObj, ['CH',num2str(channel),':DISABLE']);
response = readline(serialObj);
isok = contains(response, {'OK'});
cnt=0;
while isEnabled || cnt>10
isEnabled = obj.getLaserStatus_(serialObj,obj.mainframe_channel);
pause(0.2);
cnt = cnt+1;
end
if isEnabled
error('Laser not enabled but command was send')
else
success = 1;
end
end
% Function to SET the wavelength of the laser
function success = setLaserWavelength_(~,serialObj, channel, desiredWavelength_nm)
success = 0;
writeline(serialObj, ['CH',num2str(channel),':NM?']);
modeResponse = readline(serialObj);
isNMMode = contains(modeResponse, ['CH',num2str(channel),':1']);
if ~isNMMode
warning(['Laser is in GHz Mode, you requested to set Wavelength (nm) -> ',modeResponse])
return
end
command = ['CH', num2str(channel), ':L=', num2str(desiredWavelength_nm)];
writeline(serialObj, command);
pause(0.2);
response = readline(serialObj);
success = contains(response, 'OK');
end
% Function to SET the laser power
function success = setLaserPower_(~,serialObj, channel, desiredPower_dBm)
success = 0;
writeline(serialObj, ['CH',num2str(channel),':MW?']);
modeResponse = readline(serialObj);
isMWMode = contains(modeResponse, ['CH',num2str(channel),':1']);
if isMWMode
warning('Laser is in MW Mode, you requested to set dBm power')
return
end
command = ['CH', num2str(channel), ':P=', num2str(desiredPower_dBm)];
writeline(serialObj, command);
pause(0.2);
response = readline(serialObj);
success = contains(response, 'OK');
end
end
end
end

View File

@@ -53,8 +53,11 @@ classdef OptAtten < handle
try
%connect to device
v = visadev('TCPIP::134.245.243.248::INSTR');
debug = 0;
if debug
disp(['Connected to Instrument: ',char(v.Vendor),' ',char(v.Model),' SerNo:',char(v.SerialNumber)]);
@@ -193,8 +196,9 @@ classdef OptAtten < handle
differ = abs(state.outputpower(i)-options.value(i));
%create msgbox when necessary
if differ >= 2
hMsgBox = msgbox(['Output Power at attenuator slot ' num2str(2) ' differs by 2dB or more!']);
uiwait(hMsgBox);
warning(['Output Power at attenuator slot ' num2str(2) ' differs by ', num2str(differ), 'or more!'])
% hMsgBox = msgbox(['Output Power at attenuator slot ' num2str(2) ' differs by 2dB or more!']);
% uiwait(hMsgBox);
end
end
end
@@ -212,7 +216,7 @@ classdef OptAtten < handle
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
@@ -257,11 +261,6 @@ classdef OptAtten < handle
answer = sscanf(line,'%f');
obj.power_state(cnt) = answer;
writeline(v, [':READ' num2str(s) ':POW?']);
line = readline(v);
answer = sscanf(line,'%f');
obj.power_state(cnt) = answer;
writeline(v, [':INP' num2str(s) ':ATT?']);
line = readline(v);
answer = sscanf(line,'%f');
@@ -272,7 +271,7 @@ classdef OptAtten < handle
answer = sscanf(line,'%f');
obj.wavelength_state(cnt) = answer;
writeline(v, [':INP' num2str(s) ':WAV?']);
writeline(v, [':INP' num2str(s) ':ATT:SPE?']);
line = readline(v);
answer = sscanf(line,'%f');
obj.speed_state(cnt) = answer;
@@ -293,6 +292,25 @@ classdef OptAtten < handle
end
end
function [p1,p2,p3,p4]=readPower(obj)
v = visadev('TCPIP::134.245.243.248::INSTR');
cnt = 1;
for s = 1:2:7
writeline(v, [':READ' num2str(s) ':POW?']);
line = readline(v);
answer = sscanf(line,'%f');
obj.power_state(cnt) = answer;
cnt = cnt+1;
end
p1 = obj.power_state(1);
p2 = obj.power_state(2);
p3 = obj.power_state(3);
p4 = obj.power_state(4);
end
end
end

View File

@@ -12,6 +12,8 @@ classdef ScopeKeysight
interpolate
recordLen
IPaddress
waitUntilClick
end
methods (Access=public)
@@ -30,6 +32,7 @@ classdef ScopeKeysight
options.interpolate logical = 0;
options.recordLen double = 1000000;
options.IPaddress
options.waitUntilClick = 0;
end
%
@@ -55,6 +58,7 @@ classdef ScopeKeysight
arguments
obj
options.channel logical = obj.channel
options.waitUntilClick = obj.waitUntilClick;
end
%%%%%%%%%%%%%%%%%%%%%%%%
@@ -67,8 +71,8 @@ classdef ScopeKeysight
v=visadev('TCPIP0::keysight.tf.uni-kiel.de::inst0::INSTR');% TCPIP0::127.0.0.1::inst0::INSTR
case scope_model.UXR1102A
v=visadev('TCPIP0::testscope.tf.uni-kiel.de::inst0::INSTR');% TCPIP0::127.0.0.1::inst0::INSTR
case scope_model.UXR1104A
v=visadev('TCPIP0::134.245.243.223::inst0::INSTR');
case scope_model.UXR1104B
v=visadev('TCPIP0::134.245.243.239::inst0::INSTR');
end
else
try
@@ -87,11 +91,11 @@ classdef ScopeKeysight
% Check if Scope is ready to go
opdone = 0;
acqdone = 0;
procdone = 0;
procdone = 1;
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');
%procdone = sscanf(obj.writeReceiveCheck(v,'pder?'), '%f');
pause(0.005);
end
armed = sscanf(obj.writeReceiveCheck(v,'aer?'), '%f');
@@ -111,7 +115,7 @@ classdef ScopeKeysight
end
else
obj.writeNcheck(v,':ACQuire:REDGe 0');
obj.writeNcheck(v,':ACQuire:SRATe %u',double(obj.fadc).*1e9);
obj.writeNcheck(v,sprintf(':ACQuire:SRATe %u',double(obj.fadc).*1e9));
end
%
@@ -119,21 +123,55 @@ classdef ScopeKeysight
obj.writeNcheck(v,sprintf(':CHANnel%u:DISPlay ON',n));% display captured data trace
end
set(v,'Timeout',150);
if obj.autoScale
obj.writeNcheck(v,':AUTOscale');
for n = 1:4
range = str2double(obj.writeReceiveCheck(v,sprintf(':CHANnel%u:RANGe?',n)));
obj.writeNcheck(v,sprintf(':CHANnel%u:RANGe %.3f',n,range/1.2));
%use this to finetune autoscaling - VERY helpful
% higher value leads to higher scaling
fintunefactor = 1.5; % within [1,...,2]
obj.writeNcheck(v,sprintf(':CHANnel%u:RANGe %.3f',n,range/fintunefactor));
end
else
obj.writeNcheck(v,':SINGLE');
%obj.writeNcheck(v,':SINGLE');
end
% After Autoscale, let the user adjust the scope scaling...
% "options.waitUntilClick" was a shit name but now this is it :-)
if options.waitUntilClick
if 0
% Create a dialog box with the desired text
d = dialog('Name', 'Scale Scope then press continue', 'Position', [300, 300, 300, 180]);
% Add a text label with the instruction
uicontrol('Parent', d, ...
'Style', 'text', ...
'Position', [20, 100, 260, 40], ...
'String', 'Please adjust scope scaling now, then press continue', ...
'HorizontalAlignment', 'center');
% Add a button to close the dialog and resume execution
uicontrol('Parent', d, ...
'Style', 'pushbutton', ...
'Position', [100, 40, 100, 40], ...
'String', 'Continue', ...
'Callback', 'uiresume(gcbf); delete(gcbf)');
% Pause execution until the dialog box is closed
uiwait(d);
else
holdAndShowValue
end
end
if obj.extRef
switch obj.model
case scope_model.DSAZ634A
obj.writeNcheck(v,':TIMebase:REFClock HFR');
case scope_model.UXR1102A || scope_model.UXR1104A
case scope_model.UXR1102A || scope_model.UXR1104B
obj.writeNcheck(v,':TIMebase:REFClock 1');
end

309
Classes/05_Lab/Thor_PDFA.m Normal file
View File

@@ -0,0 +1,309 @@
classdef Thor_PDFA < handle
properties(Access= public)
serialport_number
safety_mode
statusInfo
StatusRegisterValue
Interlock
TEC0_temp
TEC1_temp
Temp_stable
Temp_fault
LASER
LOS_Status
PumpLevel
end
methods (Access=public)
function obj = Thor_PDFA(options)
arguments
options.serialport_number = 'COM12'
options.safety_mode = 1;
end
%
fn = fieldnames(options);
for n = 1:numel(fn)
try
obj.(fn{n}) = options.(fn{n});
end
end
end
function o = connectSerial(obj)
% Connect to the PDFA
o = serialport(obj.serialport_number, 9600);
configureTerminator(o, "CR", "CR"); % Set the terminator to carriage return (CR)
flush(o);
end
function getStatus(obj)
o = obj.connectSerial();
obj.getStatus_(o);
if obj.safety_mode
obj
end
end
function enablePDFA(obj)
o = obj.connectSerial();
if obj.safety_mode
% Prompt the user to enable
choice = questdlg('Do you want to enable the PDFA?', ...
'TURN ON PUMP', ...
'PUMP IT!', 'No', 'No');
else
choice = 'PUMP IT!';
end
% Handle the response
switch choice
case 'PUMP IT!'
% Enable the pump
success = obj.enablePump_(o);
disp('PDFA enabled.');
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains disabled.');
end
end
function disablePDFA(obj)
o = obj.connectSerial();
if obj.safety_mode
% Prompt the user to disable
choice = questdlg('Do you want to disable the PDFA?', ...
'TURN OFF PUMP', ...
'Turn off', 'No', 'No');
else
choice = 'Turn off';
end
% Handle the response
switch choice
case 'Turn off'
% Enable
success = obj.disablePump_(o);
disp('PDFA enabled.');
case 'No'
% Abort the operation
disp('Operation aborted. Laser remains disabled.');
end
end
function success = setPumpLevel(obj,desiredPump)
success = 0;
o = obj.connectSerial();
obj.setPumpLevel_(o,desiredPump);
end
function cleanedResponse = cleanResponse(~,responseToClean)
cleanedResponse = regexprep(responseToClean, '\x1B\[[0-9;]*[a-zA-Z]', '');
end
end
methods(Access= private)
function pumpLevel = readPumpLevel(obj,serialObj)
writeline(serialObj, "gloc");
pause(0.05);
response = read(serialObj,serialObj.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
currentPercentage = regexp(cleanedResponse, '([0-9]+\.[0-9]+)%', 'tokens', 'once');
obj.PumpLevel = str2double(currentPercentage{1});
pumpLevel = obj.PumpLevel;
end
function getStatus_(obj,o)
writeline(o, "stat");
pause(0.5);
response = read(o,o.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
% Parse and convert values
% Convert Status Register Value (hexadecimal to decimal)
statusValueHex = regexp(cleanedResponse, 'Status Register Value = (0x[0-9A-F]+)', 'tokens', 'once');
obj.StatusRegisterValue = hex2dec(statusValueHex{1});
% Convert Interlock status to logical (Closed = true, Open = false)
interlockStatus = regexp(cleanedResponse, 'Interlock\s*:\s*(\w+)', 'tokens', 'once');
obj.Interlock = strcmp(interlockStatus{1}, 'Closed');
% Convert TEC0 and TEC1 temp to logical (Good = true, Fault = false)
tec0Temp = regexp(cleanedResponse, 'TEC0 temp\s*:\s*(\w+)', 'tokens', 'once');
obj.TEC0_temp = strcmp(tec0Temp{1}, 'Good');
tec1Temp = regexp(cleanedResponse, 'TEC1 temp\s*:\s*(\w+)', 'tokens', 'once');
obj.TEC1_temp = strcmp(tec1Temp{1}, 'Good');
% Convert Temp stable status to logical (Stable = true, Unstable = false)
tempStable = regexp(cleanedResponse, 'Temp stable\s*:\s*(\w+)', 'tokens', 'once');
obj.Temp_stable = strcmp(tempStable{1}, 'Stable');
% Convert Temp fault status to logical (No Fault = false, Fault = true)
tempFault = regexp(cleanedResponse, 'Temp fault\s*:\s*(\w+)', 'tokens', 'once');
obj.Temp_fault = strcmp(tempFault{1}, 'Fault');
% Convert LASER status to logical (OFF = false, ON = true)
laserStatus = regexp(cleanedResponse, 'LASER\s*:\s*(\w+)', 'tokens', 'once');
obj.LASER = strcmp(laserStatus{1}, 'ON');
% Convert LOS Status to logical (Good = true, Faulty = false)
losStatus = regexp(cleanedResponse, 'LOS Status\s*:\s*(\w+)', 'tokens', 'once');
obj.LOS_Status = strcmp(losStatus{1}, 'Good');
writeline(o, "gloc");
pause(0.5);
response = read(o,o.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
% Use a regular expression to extract the operating current value in percentage
currentPercentage = regexp(cleanedResponse, '([0-9]+\.[0-9]+)%', 'tokens', 'once');
% Convert the extracted percentage to a numeric value
obj.PumpLevel = str2double(currentPercentage{1});
end
function success = enablePump_(obj,o)
success = 0;
curPump = obj.readPumpLevel(o);
if curPump ~= 0
cnt = 0;
pumpSetToZero = 0;
while ~pumpSetToZero
pumpZero = 0;
pumpSetToZero = obj.setPumpLevel_(o,pumpZero);
cnt = cnt+1;
end
end
% set pump on
writeline(o, 'le');
pause(0.5);
response = read(o,o.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
isEnabled = contains(cleanedResponse, {'ENABLE LASER'});
pause(5);
obj.getStatus_(o);
if isEnabled && obj.LASER
success = 1;
else
error('Could not enable the pump....');
end
end
function success = disablePump_(obj,o)
success = 0;
curPump = obj.readPumpLevel(o);
if curPump ~= 0
cnt = 0;
pumpSetToZero = 0;
while ~pumpSetToZero
pumpZero = 0;
pumpSetToZero = obj.setPumpLevel_(o,pumpZero);
cnt = cnt+1;
end
end
% set pump on
writeline(o, 'ld');
pause(0.5);
response = read(o,o.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
isDisabled = contains(cleanedResponse, {'DISABLE LASER'});
pause(5);
obj.getStatus_(o);
if isDisabled && ~obj.LASER
success = 1;
else
error('Could not disable the pump....');
end
end
function success = setPumpLevel_(obj,o,desiredPump)
success = 0;
curPump = obj.readPumpLevel(o);
while abs(curPump-desiredPump) > 0
% difference
diff_pump = curPump-desiredPump;
% set new pump
increment_pump = -1 * sign(diff_pump) ;
% set new incr. pump
writeline(o, ['sloc ',num2str(curPump+increment_pump)]);
if increment_pump < 0
pause(0.1);
else
pause(0.3);
end
response = read(o,o.NumBytesAvailable,"char");
cleanedResponse = obj.cleanResponse(response);
curPump = str2double(regexp(cleanedResponse, '([0-9]+\.[0-9]+)%', 'tokens', 'once'));
end
curPump = obj.readPumpLevel(o);
if obj.PumpLevel == desiredPump
success = 1;
else
warning('Pump nicht richtig?')
end
end
end
end

View File

@@ -125,23 +125,49 @@ classdef DataStorage < handle
lin_idx = obj.getIndicesByPhys(varargin);
errcnt = 0;
for i=1:numel(lin_idx)
try
tmp = obj.sto.(storageVarName){lin_idx(i)};
if ~isempty(tmp)
if isa(tmp,'Signal')
if isa(tmp,'Signal') || isa(tmp,'struct') || isa(tmp,'Exfo_laser') || isa(tmp,'DC_supply')
if i == 1
value = {};
end
value{i} = tmp ;
elseif isa(tmp,'cell')
if isa(tmp{1},'Signal')
if i == 1
value = {};
end
value{i} = tmp{1} ;
else
value{i} = tmp{1} ;
end
else
value(i,:) = tmp ;
try
value(i,:) = tmp ;
catch
% value(i,:) = tmp(1:size(value,2)) ;
if size(value,2) < size(tmp,2)
diff = size(tmp,2) - size(value,2);
value(:,end+1:end+diff) = NaN(size(value,1),diff);
value(i,:) = tmp ;
elseif size(value,2) > size(tmp,2)
diff = size(value,2) - size(tmp,2);
tmp(:,end+1:end+diff) = NaN(1,diff);
value(i,:) = tmp ;
end
end
end
else
errcnt = errcnt+1;
@@ -166,9 +192,7 @@ classdef DataStorage < handle
% warning([num2str(errcnt),' requested datapoint(s) not in warehouse.']);
end
catch
error('Error in Datastorage: Something happened while looking up in warehouse.')
end
end
else
error('Wrong Request using ExampleWarehouse.getStoValue(*parameter set*). Give me all the Parameters! Please!')