diff --git a/@MyDataSource/MyDataSource.m b/@MyDataSource/MyDataSource.m index 9109cd4..1b8eba6 100644 --- a/@MyDataSource/MyDataSource.m +++ b/@MyDataSource/MyDataSource.m @@ -1,50 +1,50 @@ -% Class that contains functionality of transferring trace to Collector and +% Class that contains functionality of transferring a trace to Collector and % then to Daq classdef MyDataSource < handle properties (Access = public) % An object derived from MyTrace Trace end events NewData end methods (Access = public) function this = MyDataSource() this.Trace = MyTrace(); end % Trigger event signaling the acquisition of a new trace. % Any properties of MyNewDataEvent can be set by indicating the % corresponding name-value pars in varargin. For the list of % options see the definition of MyNewDataEvent. function triggerNewData(this, varargin) EventData = MyNewDataEvent(varargin{:}); % Pass trace by value to make sure that it is not modified % before being transferred if isempty(EventData.traces) % EventData.Trace can be set either automaticallt here or % explicitly as a name-value pair supplied to the function. EventData.traces = {copy(this.Trace)}; end notify(this, 'NewData', EventData); end end methods function set.Trace(this, Val) assert(isa(Val, 'MyTrace'), ['Trace must be a derivative ' ... 'of MyTrace class.']) this.Trace = Val; end end end diff --git a/GUIs/GuiTekRsaFvt.mlapp b/GUIs/GuiTekRsaFvt.mlapp new file mode 100644 index 0000000..fec7160 Binary files /dev/null and b/GUIs/GuiTekRsaFvt.mlapp differ diff --git a/Instrument classes/@MyTekRsa/MyTekRsa.m b/Instrument classes/@MyTekRsa/MyTekRsa.m index 6bca004..72585d1 100644 --- a/Instrument classes/@MyTekRsa/MyTekRsa.m +++ b/Instrument classes/@MyTekRsa/MyTekRsa.m @@ -1,200 +1,200 @@ % Class for controlling Tektronix RSA5103 and RSA5106 spectrum analyzers classdef MyTekRsa < MyScpiInstrument & MyDataSource & MyCommCont ... & MyGuiCont properties (SetAccess = protected, GetAccess = public) acq_trace % The number of last read trace end methods (Access = public) function this = MyTekRsa(varargin) P = MyClassParser(this); processInputs(P, this, varargin{:}); this.Trace.unit_x = 'Hz'; this.Trace.unit_y = '$\mathrm{V}^2/\mathrm{Hz}$'; this.Trace.name_y = 'Power'; this.Trace.name_x = 'Frequency'; % Create communication object connect(this); % Set up the list of communication commands createCommandList(this); end function str = idn(this) str = idn@MyInstrument(this); % The instrument needs to be in DPX Spectrum mode res = queryString(this, ':DISPlay:WINDow:ACTive:MEASurement?'); assert(contains(lower(res), {'dpsa', 'dpx'}), ... 'The spectrum analyzer must be in DPX Spectrum mode.'); end end methods (Access = protected) function createCommandList(this) % We define commands for both the nominal and actual resolution % bandwidths as these two are useful in different % circumstances. The nominal one unlike the actual one takes % effect immediately after it is set to a new value, whereas % the actual one is the true rbw if the device does not follow % the nominal one (usually if the nominal rbw is is too small). addCommand(this, 'rbw', ':DPX:BANDwidth:RESolution', ... 'format', '%e', ... 'info', 'Nominal resolution bandwidth (Hz)'); addCommand(this, 'rbw_act', ':DPX:BANDwidth:ACTual', ... 'format', '%e', ... 'access', 'r', ... 'info', 'Actual resolution bandwidth (Hz)'); addCommand(this, 'auto_rbw', ':DPX:BAND:RES:AUTO', ... 'format', '%b'); addCommand(this, 'span', ':DPX:FREQ:SPAN', ... 'format', '%e', ... 'info', '(Hz)'); addCommand(this, 'start_freq', ':DPX:FREQ:STAR',... 'format', '%e', ... 'info', '(Hz)'); addCommand(this, 'stop_freq', ':DPX:FREQ:STOP',... 'format', '%e', ... 'info', '(Hz)'); addCommand(this, 'cent_freq', ':DPX:FREQ:CENT',... 'format', '%e', ... 'info', '(Hz)'); % Continuous triggering addCommand(this, 'init_cont', ':INIT:CONT', ... 'format', '%b',... 'info', 'Continuous triggering on/off'); % Number of points in trace addCommand(this, 'point_no', ':DPSA:POIN:COUN', ... 'format', 'P%i', ... 'value_list', {801, 2401, 4001, 10401}); % Reference level (dB) addCommand(this, 'ref_level',':INPut:RLEVel', ... 'format', '%e',... 'info', '(dB)'); % Display scale per division (dBm/div) addCommand(this, 'disp_y_scale', ':DISPlay:DPX:Y:PDIVision',... 'format', '%e', ... 'info', '(dBm/div)'); % Display vertical offset (dBm) addCommand(this, 'disp_y_offset', ':DISPLAY:DPX:Y:OFFSET', ... 'format', '%e', ... 'info', '(dBm)'); - + % Parametric commands for i = 1:3 i_str = num2str(i); % Display trace addCommand(this, ['disp_trace',i_str], ... [':TRAC',i_str,':DPX'], ... 'format', '%b', ... 'info', 'on/off'); % Trace Detection addCommand(this, ['det_trace',i_str],... [':TRAC',i_str,':DPX:DETection'],... 'format', '%s', ... 'value_list', {'AVERage', 'NEGative', 'POSitive'}); % Trace Function addCommand(this, ['func_trace',i_str], ... [':TRAC',i_str,':DPX:FUNCtion'], ... 'format', '%s', ... 'value_list', {'AVERage', 'HOLD', 'NORMal'}); % Number of averages addCommand(this, ['average_no',i_str], ... [':TRAC',i_str,':DPX:AVER:COUN'], ... 'format', '%i'); % Count completed averages addCommand(this, ['cnt_trace',i_str], ... [':TRACe',i_str,':DPX:COUNt:ENABle'], ... 'format', '%b', ... 'info', 'Count completed averages'); end end end methods (Access = public) function readTrace(this, varargin) if ~isempty(varargin) n_trace = varargin{1}; else n_trace = this.acq_trace; end % Ensure that device parameters, especially those that will be % later used for the calculation of frequency axis, are up to % date sync(this); writeString(this, sprintf('fetch:dpsa:res:trace%i?', n_trace)); data = binblockread(this.Comm, 'float'); % Calculate the frequency axis this.Trace.x = linspace(this.start_freq, this.stop_freq,... this.point_no); % Calculates the power spectrum from the data, which is in dBm. % Output is in V^2/Hz this.Trace.y = (10.^(data/10))/this.rbw_act*50*0.001; this.acq_trace = n_trace; % Trigger acquired data event triggerNewData(this); end % Abort data acquisition function abortAcq(this) writeString(this, ':ABORt'); end % Initiate data acquisition function initAcq(this) writeString(this, ':INIT'); end % Wait for the current operation to be completed function val = opc(this) val = queryString(this, '*OPC?'); end % Extend readSettings function function Mdt = readSettings(this) %Call parent class method and then append parameters Mdt = readSettings@MyScpiInstrument(this); %Hdr should contain single field addParam(Mdt, 'acq_trace', this.acq_trace, ... 'comment', 'The number of last read trace'); end end methods function set.acq_trace(this, val) assert((val==1 || val==2 || val==3), ... 'Acquisition trace number must be 1, 2 or 3.'); this.acq_trace = val; end end end diff --git a/Instrument classes/@MyTekRsaFvt/MyTekRsaFvt.m b/Instrument classes/@MyTekRsaFvt/MyTekRsaFvt.m new file mode 100644 index 0000000..4e8ea1d --- /dev/null +++ b/Instrument classes/@MyTekRsaFvt/MyTekRsaFvt.m @@ -0,0 +1,112 @@ +% Class for controlling Tektronix RSA5103 and RSA5106 spectrum analyzers + +classdef MyTekRsaFvt < MyScpiInstrument & MyDataSource & MyCommCont ... + & MyGuiCont + + methods (Access = public) + function this = MyTekRsaFvt(varargin) + P = MyClassParser(this); + processInputs(P, this, varargin{:}); + + this.Trace.unit_x = 's'; + this.Trace.unit_y = 'Hz'; + this.Trace.name_y = 'Frequency'; + this.Trace.name_x = 'Time'; + + % Create communication object + connect(this); + + % Set up the list of communication commands + createCommandList(this); + end + + function str = idn(this) + str = idn@MyInstrument(this); + + % The instrument needs to be in DPX Spectrum mode + res = queryString(this, ':DISPlay:WINDow:ACTive:MEASurement?'); + assert(contains(lower(res), {'dpsa', 'dpx'}), ... + 'The spectrum analyzer must be in DPX Spectrum mode.'); + end + end + + methods (Access = protected) + function createCommandList(this) + % Frequency vs time measurement frequency (Hz) + addCommand(this, 'measuremnt_freq', ':MEAS:FREQ',... + 'format', '%e', ... + 'info', '(Hz)'); + + % Frequency vs time measurement bandwidth (Hz) + addCommand(this, 'measurement_BW', ':FVT:FREQ:SPAN',... + 'format', '%e', ... + 'info', '(Hz)'); + + % Frequency vs time display x extent (s) + addCommand(this, 'disp_x_length', ':ANAL:LENG',... + 'format', '%e', ... + 'info', '(s)'); + + % Frequency vs time display x offset (s) + addCommand(this, 'disp_x_start', ':ANAL:STAR',... + 'format', '%e', ... + 'info', '(s)'); + + % Frequency vs time display offset (Hz) + addCommand(this, 'disp_y_offset', ':DISP:FVT:Y:OFFS',... + 'format', '%e', ... + 'info', '(Hz)'); + + % Frequency vs time display scale (extent) (Hz) + addCommand(this, 'disp_y_scale', ':DISP:FVT:Y',... + 'format', '%e', ... + 'info', '(Hz)'); + end + end + + + methods (Access = public) + function readTrace(this, varargin) + % Ensure that device parameters, especially those that will be + % later used for the calculation of frequency axis, are up to + % date + sync(this); + + writeString(this, 'fetch:fvt?'); + data = binblockread(this.Comm, 'float'); + + % Calculate the time axis + this.Trace.x = linspace(this.disp_x_start, ... + this.disp_x_start + this.disp_x_length, length(data)); + + this.Trace.y = data; + + % Trigger acquired data event + triggerNewData(this); + end + + % Abort data acquisition + function abortAcq(this) + writeString(this, ':ABORt'); + end + + % Initiate data acquisition + function initAcq(this) + writeString(this, ':INIT'); + end + + % Wait for the current operation to be completed + function val = opc(this) + val = queryString(this, '*OPC?'); + end + + % Extend readSettings function + function Mdt = readSettings(this) + + %Call parent class method and then append parameters + Mdt = readSettings@MyScpiInstrument(this); + + end + end + +end