Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions +Base/pref.m
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
% help_text - provide longer text to describe what this pref does (think tooltip)
% readonly - boolean specifying if GUI control should be editable (e.g. "enabled")
% display_only - boolean specifying if saved as pref when module unloaded
% tag - any data type available for user to choose (similar to gobject UserData)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this necessary?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it can be useful to store any additional data to make it easier on callbacks. I would push to call it UserData instead since that is literally what @ponagehl2 compare it to.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the set methods should all be 'setNum'? Currently set == tag for each one. I don't really like this solution, especially because if you want to be pedantic, you would have to provide tags or a system to interpret tags for each function (clean, validate, etc). Perhaps a more elegant solution is to pass a cell array {'setNum', 'setPower'} and then have pref_handler parse and insert it upon function handle construction. I also don't think it's terrible to have a separate function for each one.

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t disagree, but having this option can be quite handy. Not the worst to have a single set method for many properties. Perhaps the usage of it can be improved in this context, but I do like the added freedom it gives developers.

% set*
% custom_validate*
% custom_clean*
Expand Down Expand Up @@ -74,6 +75,8 @@
custom_clean = {[], @(a)true};
% First things called before any validation
set = {[], @(a)true};
% Tag available to the user
tag = {[], @(a)true};
end

methods % May be overloaded by subclass pref
Expand Down
2 changes: 1 addition & 1 deletion +Modules/Source.m
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ function arm(obj)
end
function blackout(obj)
%this method should do whatever is necessary to completely
%block emissions from the source; for example, this may include
%block emissions from the source; for example, this may include
%powering off a source
warning('SOURCE:notimplemented','blackout method not implemented for %s',class(obj))
end
Expand Down
Binary file added .matlabprefs.mat.backup
Binary file not shown.
1 change: 1 addition & 0 deletions HelperFunctions/hwserver.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
obj.connection.Terminator = 'LF';
obj.connection.OutputBufferSize = 4096;
obj.connection.InputBufferSize = 4096;
obj.ping;
end
function delete(obj)
if strcmp(obj.connection.status,'open')
Expand Down
135 changes: 58 additions & 77 deletions Modules/+Sources/SuperK.m
Original file line number Diff line number Diff line change
@@ -1,31 +1,42 @@
classdef SuperK < Modules.Source
%superK used to control all aspects of the superK laser.
% SuperK used to control all aspects of the superK laser.
%
% The on/off state of laser is controlled by the PulseBlaster (loaded
% in set.ip). Note this state can switch to unknown if another
% module takes over the PulseBlaster program.
%
% Power to the laser can be controlled through the serial object
% - obj.serial.on()/off() - however, time consuming calls!
% The emission state of the laser is controlled by serial connection
%


properties
ip = 'Deprecated Use'; % IP of computer with and server
prefs = {'ip'};
properties(SetObservable,GetObservable)
prefs = {'Power','Pulse_Picker','Rep_Rate','Center_Wavelength',...
'Bandwidth','Attenuation','Host'};
show_prefs = {'Power','Pulse_Picker','Rep_Rate','Center_Wavelength',...
'Bandwidth','Attenuation','Host'};
Power = Prefs.Double('max',100,'min',0,'units','%','allow_nan',false,...
'tag','setPower');
Pulse_Picker = Prefs.Integer('max',40,'min',0,'help_text','Divider of max rep rate',...
'tag','setPulsePicker');
Rep_Rate = Prefs.Double('units','MHz','readonly',true,...
'tag','setRepRate');
Center_Wavelength = Prefs.Double('min',0,'units','nm',...
'tag','setWavelength');
Bandwidth = Prefs.Double('min',0,'units','nm',...
'tag','setBandwidth');
Attenuation = Prefs.Double('max',100,'min',0,'units','%',...
'tag','setND');
Host = Prefs.String('No Server','set','setHost');

end
properties(SetObservable,SetAccess=private)
source_on = false;
running % Boolean specifying if StaticLines program running
end
properties(SetAccess=private,Hidden)
listeners
status % Text object reflecting running
path_button
serial
comm = hwserver.empty
end
methods(Access=protected)
function obj = SuperK()
obj.loadPrefs;
obj.serial = Drivers.SuperK.instance(obj.ip);
end
end
methods(Static)
Expand All @@ -40,89 +51,59 @@
end
methods
function delete(obj)
delete(obj.listeners)
delete(obj.serial)
if obj.comm_isvalid
delete(obj.comm);
end
end
function setNum(obj,val,pref)
obj.serial.(pref.tag.set)(val);
end
function set.ip(obj,val)
function host = setHost(obj,val,pref)
err = [];
if obj.comm_isvalid
delete(obj.comm);
end
if isempty(val) || strcmp(val,'No Server')
obj.comm = hwserver.empty;
obj.Host = 'No Server';
host = obj.Host;
return
end
try
delete(obj.serial)
obj.serial = Drivers.SuperK.instance(val);
obj.ip = val;
obj.comm = Drivers.SuperK.instance(val);
obj.Host = val;
host = val;
catch err
delete(obj.listeners)
obj.ip = 'No Server';
obj.Host = 'No Server';
host = obj.Host;
end
if ~isempty(err)
rethrow(err)
end
end
function on(obj)
obj.serial.on();
obj.comm.on();
obj.source_on = true;
end
function off(obj)
obj.serial.off();
obj.comm.off();
obj.source_on = false;
end

% Settings and Callbacks
function settings(obj,panelH,~,~)
spacing = 1.5;
num_lines = 6;
line = 1;
uicontrol(panelH,'style','text','string','Power (%):','horizontalalignment','right',...
'units','characters','position',[0 spacing*(num_lines-line) 18 1.25]);
uicontrol(panelH,'style','edit','string',num2str(obj.serial.getPower),'tag','setPower',...
'units','characters','callback',@obj.setNum,...
'horizontalalignment','left','position',[19 spacing*(num_lines-line) 10 1.5]);
line = 2;
uicontrol(panelH,'style','text','string','Pulse Picker (int):','horizontalalignment','right',...
'units','characters','position',[0 spacing*(num_lines-line) 18 1.25]);
uicontrol(panelH,'style','edit','string',num2str(obj.serial.getPulsePicker),'tag','setPulsePicker',...
'units','characters','callback',@obj.setNum,...
'horizontalalignment','left','position',[19 spacing*(num_lines-line) 10 1.5]);
line = 3;
uicontrol(panelH,'style','text','string',strcat('Rep Rate (MHz): ',num2str(obj.serial.getRepRate())),'horizontalalignment','right',...
'units','characters','position',[0,spacing*(num_lines-line) 25 1.25]);
line = 4;
uicontrol(panelH,'style','text','string','Center Wavelength (nm):','horizontalalignment','right',...
'units','characters','position',[0 spacing*(num_lines-line) 18 1.25]);
uicontrol(panelH,'style','edit','string',num2str(obj.serial.getWavelength()),'tag','setWavelength',...
'units','characters','callback',@obj.setNum,...
'horizontalalignment','left','position',[19 spacing*(num_lines-line) 10 1.5]);
line = 5;
uicontrol(panelH,'style','text','string','Bandwidth (nm):','horizontalalignment','right',...
'units','characters','position',[0 spacing*(num_lines-line) 18 1.25]);
uicontrol(panelH,'style','edit','string',num2str(obj.serial.getBandwidth()),'tag','setBandwidth',...
'units','characters','callback',@obj.setNum,...
'horizontalalignment','left','position',[19 spacing*(num_lines-line) 10 1.5]);
line = 6;
uicontrol(panelH,'style','text','string','Attenuation (%)):','horizontalalignment','right',...
'units','characters','position',[0 spacing*(num_lines-line) 18 1.25]);
uicontrol(panelH,'style','edit','string',num2str(obj.serial.getND()),'tag','setND',...
'units','characters','callback',@obj.setNum,...
'horizontalalignment','left','position',[19 spacing*(num_lines-line) 10 1.5]);
end

function setNum(obj,hObj,~)
temp = get(hObj,'string');
temp = str2double(temp);
assert(~isnan(temp),'Must be a number!');
obj.serial.(get(hObj,'tag'))(temp);

function arm(obj)
% nothing needs to be done since SuperK just needs on/off methods
end

function ipCallback(obj,src,varargin)
err = [];
try
obj.ip = get(src,'string');
catch err
end
set(src,'string',obj.ip)
if ~isempty(err)
rethrow(err)
function val = get.comm(obj)
d = dbstack(1);
if ~strcmp(d(1).name,'SuperK.comm_isvalid') % avoid recursive call
assert(obj.comm_isvalid,'Not connected (set.host)');
end
val = obj.comm;
end

function val = comm_isvalid(obj) % get method allows direct access to comm
val = any(isvalid(obj.comm));
end
end
end