function [out,out1] = photon(varargin) % Virtual deviced driver for the Dactron Active-X API % This driver works with ID_ACQ the acquisition environment of SDT % % h=photon : opens the Active-X server and the GUI % % photon('plothammer',batch) % % Acquired frames are stored in variable BATCH in the % base MATLAB workspace. % % Warning : this is a prototype. Comments are welcome but SDTools % does not provide support for it. % % % Etienne Balmes 28/09/02, 22/10/02 % Copyright (c) 2002-2002 by SDtools % For revision info use photon('cvs') % Handle to find the server between calls gf=findall(0,'tag','SDTacq'); if isempty(gf) gf=id_acq('init'); end ga=findall(gf,'tag','PhotonServer'); if isempty(ga) if isunix warning('Photon Server is only available on windows');return; end ga=axes('parent',gf,'visible','off','tag','PhotonServer', ... 'DeleteFcn','photon(''close'');'); ua=[]; else ua=get(ga,'userdata'); end [ua,PH]=openPhoton(ga,ua); h=ua.photon; if nargin==0 out=PH;return; else [CAM,Cam]=comstr(varargin{1},1);carg=2; end sdtdef('diag',['photon(''' Cam ''')']) % Supported returns list of device capabilities - - - - - - - - - - - - - if comstr(Cam,'supported') for j1=1:20 if h.SystemReady; break; end; disp('Waiting for DSP boot');pause(10); end % wait for boot sup=struct('DataTypes',[]); sup.DataTypes=h.DataTypes; st=get(h.source,'types',1);st{end+1}='Channel 1';st{end+1}='Off'; sup.SourceTypes=st; % Signal processing availlable sup.BlockSizes=double(h.MeasSetup.BlocksizeRange); sup.FreqRanges=FreqRanges; st={}; for j1=1:length(sup.FreqRanges) st{j1}=sprintf('%.0f',sup.FreqRanges(j1,2)*450/1024); end sup.RangeLabel=st; sup.Windows=h.MeasSetup.Windows; sup.TriggerModes=h.ArmTrigger.TriggerModes; sup.ch={}; for j1=1:double(h.NumberOfInputs) r1=[]; r1.Ranges=cellstr(num2str(double(get(h.input,'EU',j1)))); st1=get(h.input,'couplings',j1);st1{end+1}='Off'; r1.Coup=st1; sup.ch{j1}=r1; end out=sup; % Current State - - - - - - - - - - - - - - - - - - - - - - - - - - - elseif comstr(Cam,'state') st={'DataType','DataType'}; out=[]; for j1=1:size(st,1) eval(sprintf('r1=PH.%s;',st{j1,1}),'r1=[];'); eval(sprintf('out.%s=r1;',st{j1,2}),''); end % Source state r1.type=get(PH.source,'type',1); if ~get(h.source,'enable',1) r1.type='Off';end r1.state=get(h.source,'state',1); if isempty(r1.state) r1.state='Stopped source';end switch lower(r1.type) case 'sine' r1.table={r1.state,'Sine',''; 'Frequency',num2str(get(h.source,'SineFreq',1)),'Hz'; 'Amplitude',get(h.source,'Amplitude',1),'V'}; otherwise r1.table={r1.state,'Not supported'}; end out.source={r1}; % Channel state out.ch={}; for j1=1:double(h.NumberOfInputs) r1=[]; r1.EU=get(h.input,'EU',j1); r1.EUScale=num2str(get(h.input,'EUScale',j1)); r1.range=get(h.input,'range',j1); if get(h.input,'enable',j1) r1.cond=get(h.input,'coupling',j1); else r1.cond='Off';end out.ch{j1}=r1; end % Signal processing info out.BlockSize=double(h.MeasSetup.Blocksize); r2=FreqRanges; [r1,i1]=min(abs(r2(:,1)-h.MeasSetup.Span)); out.Fsamp=r2(i1,2); out.window=h.MeasSetup.Window; st=h.ArmTrigger.TriggerModes; out.trigger=[double(h.ArmTrigger.TriggerChannel) ... find(strcmp(h.ArmTrigger.TriggerMode,st)) h.ArmTrigger.TriggerLevel ... h.ArmTrigger.TriggerDelay]; st={'PreInit','InitDone','Settling','PreArm','PreTrigger', ... 'WaitTrigger','Processing','Transition'}; out.state=double(h.MeasState); out1=PH; % ----------------------------------------------------------------------- elseif comstr(Cam,'set') [CAM,Cam]=comstr(CAM,4); cur=varargin{carg};carg=carg+1; r1=varargin{carg};carg=carg+1; switch lower(r1{1}) case 'blocksize'; set(h.MeasSetup,'BlockSize',r1{2}); case 'channel'; if strcmp(r1{2},'coupling')&strcmpi(r1{4},'off') set(h.input,'enable',r1{3},0); else set(h.input,r1{2:end});set(h.input,'enable',r1{3},1); end case 'datatype'; set(h.datatype,r1{2}); case 'source'; switch r1{2} case 'disable'; set(h.Source,'enable',r1{3},0); case 'enable'; set(h.Source,'enable',r1{3},1); otherwise warning xxx %set(h.Source,'type',1,st1); end case 'span'; r2=FreqRanges; [r3,i1]=min(abs(r1{2}-r2(:,2)*450/1024)); set(h.MeasSetup,'Span',r2(i1,1)); case 'triggermode'; set(h.ArmTrigger,'TriggerMode',r1{2}); case 'triggerparam'; % level r2=get(h.ArmTrigger,'TriggerLevelRange'); r3=r1{2};if ischar(r3) r3=str2num(r3);end if r3>=r2(1) & r3<=r2(2) set(h.ArmTrigger,'TriggerLevel',r3); else warning('Out of range trigger level');end % delay r3=r1{3};if ischar(r3) r3=str2num(r3);end set(h.ArmTrigger,'TriggerDelay',r3/cur.Fsamp); case 'window'; set(h.MeasSetup,'Window',r1{2}); otherwise warning xxx end % ----------------------------------------------------------------------- % open elseif comstr(Cam,'open') [CAM,Cam]=comstr(CAM,6); % ----------------------------------------------------------------------- % Handling standard frame plots elseif comstr(Cam,'plot') [CAM,Cam]=comstr(CAM,5); if comstr(Cam,'hammer') ph_hammer(varargin{carg}); carg=carg+1; else error('Not a supported plot'); end % ----------------------------------------------------------------------- % start elseif comstr(Cam,'start') [CAM,Cam]=comstr(CAM,6); Info=varargin{carg};carg=carg+1; batch=varargin{carg};carg=carg+1; ga=findobj(gf,'type','axes','tag','acq_table'); ua=get(ga,'userdata'); uf=get(gf,'userdata'); if length(ua.table)<3 id_acq('acqrefresh');return;end % Init not done yet [cur,h]=feval(uf.driver,'state'); % xxx set(Info,'string','Starting ...','backgroundcolor','red'); if h.MeasState==0 invoke(h,'open'); end % Deal with need to start source - - - - - - - - - - - - - - - - - - - i1=strmatch('source',lower(ua.table(:,1))); if ~any(strncmp(lower(ua.table{i1,2}),{'off','cha'},3)) % start source if ~isempty(findstr(get(h.Source,'state',1),'idle')) invoke(h.Source,'start'); end j1=1; while strcmp(get(h.source,'state',1),'Source idle') & j1<10 j1=j1+1;pause(1);drawnow; set(Info,'string','Starting source ...'); end if strcmp(get(h.source,'state',1),'Source idle') error('Failed to start source'); end else % deal with trigger channel enable set(h.Input,'enable',h.ArmTrigger.TriggerChannel,1); end % end of source strating % Start acquisition invoke(h,'stop'); invoke(h,'start'); set(h.ArmTrigger,'ArmMode','Auto'); invoke(h,'ReadDone'); % Wait for acquisition to be ready id_acq('acqrefresh'); Stop=findall(gf,'tag','stop'); set(Stop,'backgroundcolor','r','userdata',0) set(findall(gf,'tag','start'),'backgroundcolor',backcol) drawnow %Initialize a few things if strcmpi(h.DataType,'time') batch.type='time'; else batch.type='freq';end i0=strmatch('Channel',ua.table(:,1));i0=i0(1); batch.ch=[]; for j1=1:length(cur.ch) i1=strmatch(sprintf('Channel %i',j1),ua.table(:,1))-i0; if strcmpi(cur.ch{j1}.cond,'Off') set(h.Input,'enable',j1,0); else batch.ch(end+1)=i1; set(h.Input,'enable',j1,1); end end assignin('base','batch',batch) % This is the acquisition loop - - - - - - - - - - - - - - - - - - - - - - while length(batch.frame)<=batch.MaxFrame & ~get(Stop,'userdata') if strcmp(h.State,'Ready for Start') set(Info,'string','Waiting for start ...','backgroundcolor','red'); elseif ~h.DataAvailable switch double(h.MeasState) case {7}; set(Info,'string','Acquiring'); case {5,6}; set(Info,'string','Waiting for trigger ...','backgroundcolor','green'); end else % No data available switch double(h.MeasState) case {3} set(Info,'string','Initializing filters ...','backgroundcolor','yellow'); %case {4} % set(Info,'string','Ready for Arm'); case {5,6}; set(Info,'string','Waiting for trigger ...','backgroundcolor','yellow'); case 8 set(Info,'string','Transition ...'); %case 7 % set(Info,'string','Acquiring'); otherwise % Read data get_frame(h,Info,gf,ua); invoke(h,'ReadDone'); set(findall(gf,'tag','next'),'backgroundcolor',[1 .5 0],'userdata',0) % Reset for trigger end % MeasState end % DataAvailable drawnow;id_acq; batch=evalin('base','batch'); end % end of acquisition loop if h.MeasState>2 id_acq('stop');end set(Info,'backgroundcolor',backcol); % ----------------------------------------------------------------------- % stop elseif comstr(Cam,'stop') [CAM,Cam]=comstr(CAM,6); try invoke(PH,'Stop'); invoke(PH.Source,'Stop'); out='Stopped acquisition'; catch out='Stop failed'; end % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- % next elseif comstr(Cam,'next') [CAM,Cam]=comstr(CAM,5); % Init for all acq commands h=ua.photon; ga=findobj(gf,'type','axes','tag','next_table'); if ~isempty(ga) ua=get(ga,'userdata');else ua=[];end if isempty(Cam) % 'Next' - - - - - - - - - - - - - - - - - batch=evalin('base','batch'); if ~isfield(batch,'save') warning('No data to save in current batch'); return; end global IIw IIxf IIxe IIxh i2=[]; i1=strmatch('H1',batch.save(1:2:end))*2; if ~isempty(i1) r2=batch.save{i1}; IIxf(1:size(r2,1),end+[1:size(r2,2)])=r2; i2=size(IIxf,2); end i1=strmatch('H2',batch.save(1:2:end))*2; if ~isempty(i1) r2=batch.save{i1}; IIxe(1:size(r2,1),end+[1:size(r2,2)])=r2;i2=size(IIxe,2); end i1=strmatch('COH',batch.save(1:2:end))*2; if ~isempty(i1) r2=batch.save{i1}; IIxh(1:size(r2,1),end+[1:size(r2,2)])=r2;i2=size(IIxh,2); end i1=strmatch('f',batch.save(1:2:end))*2; if ~isempty(i1) r2=batch.save{i1}; IIw=r2(:); end if ~isempty(i2) iicom(sprintf('ch %i',i2));end batch.save={}; batch.frame=0; assignin('base','batch',batch); elseif comstr(Cam,'channel') % 'NextChannel' - - - - - - - - - - - - - - - - - warning('Nothing done currently') elseif comstr(Cam,'check') % 'NextCheck' - - - - - - - - - - - - - - - - - - uo=varargin{carg};carg=carg+1; st=lower(ua.table{uo.index(1),1}); if h.MeasState>1 warndlg('Stop acquisition before modifying parameters','Photon'); elseif comstr(st,'channel') % Deal with channel properties end % of command handling photon('nextrefresh'); elseif comstr(Cam,'refresh') % 'NextRefresh' - - - - - - - - - - - - - - - - %if isempty(ua) ga=[];ua.EditFcn={''}; ua.table={}; ua.RefreshFcn='photon(''nextrefresh'',ga);'; %end j2=1; global IIxf ua.table={sprintf('%i %i',size(IIxf)),'Reset'}; ua.EditFcn{1,2}='photon(''NextReset'');'; ua.Level=[1 1]; ua.CheckFcn='photon(''nextcheck'',uo)'; h=findall(gf,'tag','channel') st=cellstr(num2str([1:size(IIxf,2)]')) set(h,'string',st); if ~isempty(ga) set(ga,'userdata',ua); cingui('tablerefresh',ga); else cingui('tableinit',ua,'next_table',gf); end %h.MeasSetup.BlockSizeRange %ua.photon.MeasSetup.OverlapRange %ua.photon.MeasSetup.Spans elseif comstr(Cam,'reset') % 'NextReSet' - - - - - - - - - - - - - - - - IIw=[]; IIxf=[]; IIxe=[]; IIxh=[]; disp('Resetting iiplot data'); else % end % of next commands % ----------------------------------------------------------------------- % close elseif comstr(Cam,'close') |comstr(Cam,'quit') [CAM,Cam]=comstr(CAM,6); h1=warndlg(sprintf('Closing down the Active Photon Server'),'PHOTON'); drawnow; try if ~isempty(h) invoke(h,'Close'); release(h); % delete ? end ua.photon=[]; end if ~isempty(ua.photon) lasterr warning('There were problems closing the Photon Server'); end set(ga,'userdata',ua); delete(h1);delete(gf); % ----------------------------------------------------------------------- elseif comstr(Cam,'save'); [CAM,Cam]=comstr(CAM,5); if comstr(Cam,'setup') [fname, wd] = uiputfile('*.cfg', 'Save Measurement setup as'); if ischar(fname) fname=fullfile(wd,fname); [wd,fname]=fileparts(fname);fname=fullfile(wd,[fname '.cfg']); invoke(PH,'SaveSetup',fname); sdtw('_IsGui','Save setup in %s',fname); end else sdtw('Save%s unknow',CAM);end % ----------------------------------------------------------------------- elseif comstr(Cam,'load'); [CAM,Cam]=comstr(CAM,5); if comstr(Cam,'setup') [fname, wd] = uigetfile('*.cfg', 'Load Measurement setup'); if ischar(fname) fname=fullfile(wd,fname); [wd,fname]=fileparts(fname);fname=fullfile(wd,[fname '.cfg']); invoke(PH,'LoadSetup',fname); sdtw('_IsGui','Loaded setup in %s',fname); end else sdtw('Save%s unknow',CAM);end % ----------------------------------------------------------------------- elseif comstr(Cam,'cvs') out='$Revision: 1.7 $ $Date: 2004/08/16 13:36:25 $'; % ----------------------------------------------------------------------- else error('Unknown command');end % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- function get_frame(h,Info,gf,ua) batch=evalin('base','batch'); r1=[]; DataType=h.DataType; IsRetained=''; r2=struct('X',[],'Y',[],'Overflow',[]); low=[]; high=[]; for j2=batch.ch(:)' if isempty(batch.t) % read time and/or freq if strcmp(batch.type,'time') batch.t=double(get(h,'xdata',j2)); batch.f=1/diff(batch.t(1:2))*[0:length(batch.t)-1]/length(batch.t); else batch.f=double(get(h,'xdata',j2)); batch.t=0; end end y=double(get(h,'ydata',j2)); if strcmp(DataType,'Time'); else y=[1 i]*reshape(y,2,length(y)/2); end r1=[r1 y(:)]; % Over/Underflow behaviour - - - - - - - - - - - - - - - - - - - - - - if strcmp(get(h.Input,'RangeStatus',j2),'E_RANGE_OVER') r2=get(h.Input,'Ranges',j2); r3=get(h.Input,'Range',j2); if max(y)r3) high(end+1)=j2; % impossibility of range change else high(end+1)=j2; end end % Over/underflow end % loop on channels st1='('; if ~isempty(high) st1=[st1 'over:' sprintf('%i ',high)]; end if ~isempty(low) st1=[st1 'low:' sprintf('%i ',low)]; end if length(st1)==1 st1=''; else st1=[st1 ')'];end r2.X=batch.t(:); r2.Y=r1; r2.OverFlow=st1; batch.frame{end+1}=r2; assignin('base','batch',batch); id_acq('FramePlot'); % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- function ContextMenus(gf); menu=uicontextmenu('parent',gf, ... 'callback','photon(''nextchcontext'');', ... 'tag','ch_context','HandleVisibility','callback'); uimenu(menu,'label','Remove selected channels', ... 'callback','photon(''nextchrm'');','visible','on') set(findall(gf,'tag','channel'),'uicontextmenu',menu) menu=uicontextmenu('parent',gf, ... 'callback','photon(''framecontext'');', ... 'tag','frame_context','HandleVisibility','callback'); uimenu(menu,'label','Remove selected frame(s)', ... 'callback','photon(''framerm'');','visible','on') set(findall(gf,'tag','frame'),'uicontextmenu',menu) % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- % ----------------------------------------------------------------------- function [ua,PH]=openPhoton(ga,ua); %try if ~isfield(ua,'photon')|isempty(ua.photon) %ua.photon=actxserver('API.MeasEngine'); ua.photon=actxserver('ME4R.MeasEngine'); invoke(ua.photon,'Open'); end %catch % ua.photon=[]; %warndlg('Could not open Photon server'); %end set(ga,'userdata',ua) PH = ua.photon; % Resource fiel VpuRes.dll is not found VPUDLL will not work properly if 1==2 h=actxserver('ME4R.MeasEngine'); invoke(h,'open'); invoke(h,'start'); y=get(h,'ydata',1) end function out=backcol out=get(0,'defaultuicontrolbackgroundcolor'); % ----------------------------------------------------------------------- function out=FreqRanges if 1==2 r1=h.MeasSetup.Spans;r1=r1(:); for j1=1:size(r1,1); set(h.MeasSetup,'Blocksize',1024); set(h.MeasSetup,'span',r1(j1,1)); r3=logspace(-2,1,512); for j2=1:length(r3) set(h.ArmTrigger,'TriggerDelay',r3(j2)/r1(j1)); r2=h.ArmTrigger.TriggerDelay; if r2; if j2==1 error('Not valid');end; break;end end r1(j1,2)=1/r2; end fprintf('out=[\n'); fprintf('%10.4f %10.4f;\n',r1') fprintf('];'); else out=[ 15.0000 40.0000; 20.0000 46.8750; 30.0000 80.0000; 36.0000 93.7500; 62.0000 160.0000; 75.0000 187.5000; 125.0000 320.0000; 150.0000 375.0000; 250.0000 640.0000; 300.0000 750.0000; 500.0000 1280.0000; 600.0000 1500.0000; 1000.0000 2560.0000; 1200.0000 3000.0000; 2000.0000 5120.0000; 2400.0000 6000.0000; 4000.0000 10240.0000; 4680.0000 12000.0000; 8000.0000 20480.0000; 9500.0000 24000.0000; 16000.0000 40960.0000; 18750.0000 40960.0000; ]; end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% if 1==2 [cur,h]=feval('photon','state'); % xxx sup=photon('supported'); r1=[15 40 20 4.6875e+001 9500 24000 ] r1(:,2)./r1(:,1) end