diff --git a/@MyDpo/MyDpo.m b/@MyDpo/MyDpo.m index ff0c7db..3e799d6 100644 --- a/@MyDpo/MyDpo.m +++ b/@MyDpo/MyDpo.m @@ -1,110 +1,104 @@ % Class for controlling 4-channel Tektronix DPO scopes. % Tested with DPO4034, DPO3034 classdef MyDpo < MyTekScope methods (Access = public) function this = MyDpo(varargin) this@MyTekScope(varargin{:}); % 2e7 is the maximum trace size of DPO4034-3034 %(10 mln point of 2-byte integers) this.Device.InputBufferSize = 2.1e7; %byte this.knob_list = lower({'GPKNOB1','GPKNOB2','HORZPos', ... 'HORZScale, TRIGLevel','PANKNOB1','VERTPOS', ... 'VERTSCALE','ZOOM'}); end end methods (Access = protected) function createCommandList(this) addCommand(this, 'channel',':DATa:SOUrce', ... 'format', 'CH%i', ... 'info', 'Channel from which the trace is transferred', ... 'value_list', {1, 2, 3, 4}); addCommand(this, 'ctrl_channel', ':SELect:CONTROl', ... 'format', 'CH%i', ... 'info', 'Channel currently selected in the scope display', ... 'value_list', {1, 2, 3, 4}); addCommand(this, 'point_no', ':HORizontal:RECOrdlength', ... 'format', '%i', ... 'info', 'Numbers of points in the scope trace', ... 'value_list', {1000, 10000, 100000, 1000000, 10000000}); addCommand(this, 'time_scale', ':HORizontal:SCAle', ... 'format', '%e', ... - 'info', 'Time scale (s/div)', ... - 'default', 10E-3); + 'info', 'Time scale (s/div)'); addCommand(this, 'trig_lev', ':TRIGger:A:LEVel',... 'format', '%e', ... - 'info', '(V)', ... - 'default', 1); + 'info', '(V)'); addCommand(this, 'trig_slope', ':TRIGger:A:EDGE:SLOpe', ... 'format', '%s', ... 'value_list', {'RISe','FALL'}); addCommand(this, 'trig_source', ':TRIGger:A:EDGE:SOUrce', ... 'format', '%s', ... 'value_list', {'CH1','CH2','CH3','CH4', ... 'AUX','EXT','LINE'}); addCommand(this, 'trig_mode', ':TRIGger:A:MODe', ... 'format', '%s', ... 'value_list', {'AUTO', 'NORMal'}); addCommand(this, 'acq_state', ':ACQuire:STATE', ... 'format', '%b',... - 'info', 'State of data acquisition by the scope', ... - 'default', true); + 'info', 'State of data acquisition by the scope'); addCommand(this, 'acq_mode', ':ACQuire:MODe', ... 'format', '%s', ... 'info', ['Acquisition mode: sample, peak ' ... 'detect, high resolution, average or envelope'], ... 'value_list',{'SAMple', 'PEAKdetect', 'HIRes', ... 'AVErage', 'ENVelope'}); % Parametric commands for i = 1:this.channel_no i_str = num2str(i); addCommand(this,... ['cpl',i_str],[':CH',i_str,':COUP'], ... 'format', '%s', ... 'info', 'Channel coupling: AC, DC or GND', ... 'value_list', {'DC','AC','GND'}); % impedances, 1MOhm or 50 Ohm addCommand(this,... ['imp', i_str], [':CH', i_str, ':IMPedance'],... 'format', '%s', ... 'info', 'Channel impedance: 1 MOhm or 50 Ohm', ... 'value_list', {'MEG', 'FIFty'}); % Offset addCommand(this, ... ['offset',i_str], [':CH',i_str,':OFFSet'], ... 'format', '%e', ... - 'info', '(V)', ... - 'default', 0); + 'info', '(V)'); addCommand(this, ... ['scale',i_str], [':CH',i_str,':SCAle'], ... 'format', '%e', ... - 'info', 'Channel y scale (V/div)', ... - 'default', 1); + 'info', 'Channel y scale (V/div)'); addCommand(this,... ['enable',i_str], [':SEL:CH',i_str], ... 'format', '%b',... - 'info', 'Channel enabled', ... - 'default', true); + 'info', 'Channel enabled'); end end end end \ No newline at end of file diff --git a/@MyTds/MyTds.m b/@MyTds/MyTds.m index 22bf15f..3e91462 100644 --- a/@MyTds/MyTds.m +++ b/@MyTds/MyTds.m @@ -1,127 +1,115 @@ % Class for controlling 2-channel Tektronix TDS scopes. classdef MyTds < MyTekScope properties (Constant = true) point_no = 2500 % number of points is fixed for this device end methods (Access = public) function this = MyTds(varargin) this@MyTekScope(varargin{:}); this.channel_no = 2; this.knob_list = lower({'HORZSCALE', 'VERTSCALE1', ... 'VERTSCALE2'}); % 5e3 is the maximum trace size of TDS2022 %(2500 point of 2-byte integers) this.Comm.InputBufferSize = 1e4; %byte end % Emulates the physical knob turning, works with nturns=+-1 function turnKnob(this,knob,nturns) switch upper(knob) case 'HORZSCALE' % timebase is changed if nturns==-1 sc = this.time_scale*2; elseif nturns==1 sc = this.time_scale/2; else return end writeString(this, ... sprintf('HORizontal:MAIn:SCAle %i',sc)); case {'VERTSCALE1', 'VERTSCALE2'} % vertical scale is changed n_ch = sscanf(upper(knob), 'VERTSCALE%i'); tag = sprintf('scale%i', n_ch); if nturns==-1 sc = this.(tag)*2; elseif nturns==1 sc = this.(tag)/2; else return end writeString(this, sprintf('CH%i:SCAle %i',n_ch,sc)); end end end methods (Access = protected) function createCommandList(this) % channel from which the data is transferred addCommand(this,'channel',':DATa:SOUrce','default',1,... - 'fmt_spec','CH%i',... + 'format','CH%i',... 'info','Channel from which the data is transferred'); - % units and scale for x and y waveform data - addCommand(this,'unit_x',':WFMPre:XUNit','access','r',... - 'classes',{'char'}); - addCommand(this,'unit_y',':WFMPre:YUNit','access','r',... - 'classes',{'char'}); - addCommand(this,'step_y',':WFMPre:YMUlt','access','r',... - 'classes',{'numeric'}); - addCommand(this,'step_x',':WFMPre:XINcr','access','r',... - 'classes',{'numeric'}); - addCommand(this,'x_zero',':WFMPre:XZEro','access','r',... - 'classes',{'numeric'}); - % time scale in s per div addCommand(this, 'time_scale',':HORizontal:MAIn:SCAle',... 'default',10E-3,... - 'fmt_spec','%e',... + 'format','%e',... 'info','Time scale (s/division)'); % trigger level addCommand(this, 'trig_lev', ':TRIGger:MAIn:LEVel',... 'default',1,... - 'fmt_spec','%e'); + 'format','%e'); % trigger slope addCommand(this, 'trig_slope', ':TRIGger:MAIn:EDGE:SLOpe',... 'default', 'RISe', 'val_list',{'RISe','RIS','FALL'},... - 'fmt_spec','%s'); + 'format','%s'); % trigger source addCommand(this, 'trig_source', ':TRIGger:MAIn:EDGE:SOUrce',... 'default', 'AUX', 'val_list', {'CH1','CH2',... - 'EXT','EXT5','EXT10','AC LINE'}, 'fmt_spec','%s'); + 'EXT','EXT5','EXT10','AC LINE'}, 'format','%s'); % trigger mode addCommand(this, 'trig_mode', ':TRIGger:MAIn:MODe',... 'default', 'AUTO', 'val_list',{'AUTO','NORMal','NORM'},... - 'fmt_spec','%s'); + 'format','%s'); % state of the data acquisition by the scope addCommand(this, 'acq_state', ':ACQuire:STATE',... - 'default',true, 'fmt_spec','%b',... + 'default',true, 'format','%b',... 'info','State of data acquisition by the scope'); % Parametric commands for i = 1:this.N_CHANNELS i_str = num2str(i); % coupling, AC, DC or GND addCommand(this,... ['cpl',i_str],[':CH',i_str,':COUP'],... 'default','DC', 'val_list', {'AC','DC','GND'},... - 'fmt_spec','%s',... + 'format','%s',... 'info','Channel coupling: AC, DC or GND'); % scale, V/Div addCommand(this,... ['scale',i_str],[':CH',i_str,':SCAle'],'default',1,... - 'fmt_spec','%e',... + 'format','%e',... 'info','Channel y scale (V/division)'); % channel enabled addCommand(this,... ['enable',i_str],[':SEL:CH',i_str],'default',true,... - 'fmt_spec','%b',... + 'format','%b',... 'info','Channel enabled'); end end end end \ No newline at end of file diff --git a/@MyTekScope/MyTekScope.m b/@MyTekScope/MyTekScope.m index 2d3142c..afbeafa 100644 --- a/@MyTekScope/MyTekScope.m +++ b/@MyTekScope/MyTekScope.m @@ -1,107 +1,109 @@ +% Generic class for controlling Tektronix scopes + classdef MyTekScope < MyScpiInstrument & MyDataSource & MyCommCont properties (GetAccess = public, SetAccess={?MyClassParser,?MyTekScope}) % number of channels channel_no = 4 % List of the physical knobs, which can be rotated programmatically knob_list = {} end methods (Access = public) function this = MyTekScope(varargin) this@MyCommCont(varargin{:}); this.Comm.InputBufferSize = 4.1e7; % byte this.Trace.name_x = 'Time'; this.Trace.name_y = 'Voltage'; end function readTrace(this) % Read raw y data y_data = readY(this); % Read units, offsets and steps for the scales parms = queryStrings(this, ... ':WFMOutpre:XUNit?', ... ':WFMOutpre:YUNit?', ... ':WFMOutpre:XINcr?', ... ':WFMOutpre:YMUlt?', ... ':WFMOutpre:XZEro?', ... ':WFMOutpre:YZEro?', ... ':WFMOutpre:YOFf?'); num_params = str2doubleHedged(parms); [unit_x, unit_y, step_x, step_y, x_zero, ... y_zero, y_offset] = num_params{:}; % Calculating the y data y = (y_data-y_offset)*step_y+y_zero; n_points = length(y); % Calculating the x data x = linspace(x_zero, x_zero + step_x*(n_points-1), n_points); this.Trace.x = x; this.Trace.y = y; % Discard "" when assiging the Trace labels this.Trace.unit_x = unit_x(2:end-1); this.Trace.unit_y = unit_y(2:end-1); triggerNewData(this); end function acquireContinuous(this) writeStrings(this, ... ':ACQuire:STOPAfter RUNSTop', ... ':ACQuire:STATE ON'); end function acquireSingle(this) writeStrings(this, ... ':ACQuire:STOPAfter SEQuence', ... ':ACQuire:STATE ON'); end function turnKnob(this, knob, nturns) is_knob_valid = ismember(lower(knob), lower(this.knob_list)); assert(is_knob_valid, ['Knob must be a member of the ' ... 'scope knob list: ', newline, var2str(this.knob_list)]) writeString(this, sprintf(':FPAnel:TURN %s,%i', knob, nturns)); end end methods (Access = protected) % The default version of this method works for DPO3034-4034 scopes function y_data = readY(this) % Configure data transfer: binary format and two bytes per % point. Then query the trace. this.Comm.ByteOrder = 'bigEndian'; writeStrings(this, ... ':DATA:ENCDG RPBinary', ... ':DATA:WIDTH 2', ... ':DATA:STARt 1', ... sprintf(':DATA:STOP %i', this.point_no), ... ':CURVE?'); y_data = double(binblockread(this.Comm, 'int16')); end end methods function set.knob_list(this, val) assert(iscellstr(val), ['Value must be a cell array of ' ... 'character strings.']) %#ok this.knob_list = val; end end end