function varargout = get_trace(varargin)
% Use this function to read a curve from Tektronix 370 Curve Tracer.
%
% [V I] = get_trace() ;
%
% read the current trace with no changes in the settings, and return 2 vectors - X and Y.
%
% [V I] = get_trace('option1',[parameter(s)],'option2',[parameter(s)],...) ;
%
% enables the user to change options in the Curve Tracer. The options are:
% 'view',n - reads the n'th trace from the 370 memory. n is an
% integer between 1 and 16. For example:
% [V I] = get_trace('view',7) ; will read the trace
% stored in the 7th memory of the tracer.
% 'vert',s - Sets the vertical scale in A/div. See page 4-22
% in the 370 manual for valid scales. For example:
% [V I] = get_trace('vert',2.0e-3) ;
% will set the vertical scale to 2mA/div.
% 'vert','stpgen' - selects the Step Generator as the vertical source.
% 'hor','col',s - sets the horizontal sensitivity to s and the
% collector as the horizontal source (see page 4-24).
% For example:
% [V I] = get_trace('hor','col',0.5) ;
% will set the collector as the horiazontal source
% and the sensitivity to 0.5V/div.
% 'hor','base',s - Sets the Base as the horizontal source and the
% sensitivity to s, between 5e-2 and 2 [V/div].
% 'hor','stpgen' - Sets the Step Generator as the horizontal source.
% 'acq',param - Sets the Acquire mode. Param can be one of the following:
% 'normal' - for normal mode.
% 'ver' - for vertical envelope mode.
% 'hor' - for horizontal envelope mode.
% 4 - for 4 curves average.
% 32 - for 32 curves average.
% 'pkvolt',p - Sets the max peak volts to p in the range [16 400].
% High voltage range (2000V) is not supported.
% However you can set the range manually and then
% acquire the curve.
% 'pkpowert',p - Sets the peak power to p in the range [0.08 220].
% 'polarity',n - Sets the Collector Supply Polarity. n is an
% integer in the range [1 7], code:
% n = 1: +Leakage
% 2: +DC
% 3: +normal
% 4: AC
% 5: -normal
% 6: -DC
% 7: -Leakage
% 'var',v - Sets the Variable Collector Supply to v, v is
% between 0 and 100.
% 'step',n - Sets n as the number of steps. An integer [0 10].
% 'step','cur',di - Sets the step to current, each step di [AMPS].
% di in the range [5e-8 2e-1].
% 'step','volt',dv - Stes step to voltage, each step dv [VOLT]. dv
% in the range [0.05 2].
% 'invert',inv - set invert to inv ('on' or 'off')
%
% GPIB address asumed to be 7. GPIB address can be set on the back pannel of 370,
% as described on pages 4-1 and 4-2 in the 370 manual.
% Other options are not yet supported.
% Yuval Ben-Dov, 9/11/03 <email: y_bd@yahoo.com>
GPIB_ADDRESS = 7; % Modify this line to change the GPIB address
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Initializing GPIB: %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
warning off instrument:fscanf:unsuccessfulRead ;
t370=gpib('mcc',0,GPIB_ADDRESS); % Defining the GPIB object. 'mcc' GPIB board #0.
set(t370,'timeout',3,... % Setting timout of the connection (in seconds)
'InputBufferSize',5000); % and increasing input buffer size to read the whole curve.
try,
fopen(t370);
query(t370,'disp sto');
catch,
error(['Couldn''t open GPIB connection.'... % error message when GPIB couldn't be openned
' Check cables and try again.'...
'If problem persist restart Matlab or the computer.']);
end;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Extracting Curve Properties: %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% extracting varargin to set the wanted
% options on the 370. All options are set
% at this stage (directly sent to 370 via GPIB).
%
if (nargin>0), % if the function was called with curve parameters:
i=1;
while (i<=nargin),
switch lower(varargin{i}),
case ('view'), % set the display to view memory # n
n=varargin{i+1};
if (isnumeric(n)& mod(n,1)==0 & n>0 & n<17),
query(t370,['disp vie:' num2str(varargin{i+1})]);
i=i+2;
else,
fclose(t370);
error('view paramater must be an integer in the range [1 16].');
end;
case {'vertical','ver'}, % set vertical axis
s=varargin{i+1};
if (isnumeric(s) & s>1e-6 & s<=2), % collector, sensitivity s
query(t370,['ver col:' num2str(s)]);
i=i+2;
elseif (strcmp(s,'stpgen') | strcmp(s,'step')), % step generator as vertical source
query(t370,'ver ste');
i=i+2;
else, % error - wrong parameter
fclose(t370);
error('vert parameter must be a number in the range [1e-6 2] or''step''.');
end;
case {'horizontal','hor'}, % set horizontal axis
s=varargin{i+1};
switch lower(s) % different options for horizontal source:
case {'col','coll','collector','collect'}, % collector voltage
s=varargin{i+2};
if (isnumeric(s) & s>5e-2 & s<=500), % sensitivity s V/div
query(t370,['hor col:' num2str(s)]);
i=i+3;
else, % wrong sensitivity parameter
fclose(t370);
error(['Wrong input parameter. ''hor'',''col'''...
'range is [5e-2 5e+2] V/div.']);
end;
case {'stpgen','step'}, % step generator
query(t370,'hor ste');
i=i+2;
case ('base'), % Base Voltage
s=varargin{i+2};
if(isnumeric(s) & s>5e-2 & s<=2),
query(t370,['hor bas:' num2str(s)]);
i=i+3;
else, % wrong sensitivity parameter
fclose(t370);
error(['Wrong input parameter. ''hor'',''base'''...
'range is [0.05 2] V/div.']);
end;
otherwise, % Wrong parameters
fclose(t370);
error('Wrong ''hor'' parameter(s). Try ''help get_curve''.');
end;
case ('acq'), % sets acquire mode (normal / envelope / average)
switch lower(varargin{i+1}),
case {'nor','norm','normal'},
query(t370,'acq nor');
i=i+2;
case {'ver','vert','vertical'},
query(t370,'acq env:ver');
i=i+2;
case {'hor','horizontal'},
query(t370,'acq env:hor');
i=i+2;
case {4,'4'},
query(t370,'acq avg:4');
i=i+2;
pause(3);
case {32,'32'},
query(t370,'acq avg:32');
i=i+2;
pause(8);
otherwise,
fclose(t370);
error('Wrong ''acq'' parameter. Try ''help get_trace''.');
end;
case ('pkvolt'), % sets the collector supply peak voltage (in V)
s = varargin{i+1};
if (isnumeric(s) & s>=16 & s<=400),
query(t370,['pkv ' num2str(s)]);
i=i+2;
else,
fclose(t370);
error(' Wrong pkvolt parameter. Try ''help get_trace''.');
end;
case ('pkpower'), % sets the collector supply peak power (in W)
s = varargin{i+1};
if (isnumeric(s) & s>=0.08 & s<=220),
query(t370,['pkp ' num2str(s)]);
i=i+2;
else,
fclose(t370);
error(' Wrong pkpower parameter. Try ''help get_trace''.');
end;
case {'pol','polarity'}, % Setting Collector Supply Polarity
switch varargin{i+1},
case (1),
query(t370,'csp ple');
i=i+2;
case (2),
query(t370,'csp pdc');
i=i+2;
case (3),
query(t370,'csp pno');
i=i+2;
case (4),
query(t370,'csp ac');
i=i+2;
case (5),
query(t370,'csp nno');
i=i+2;
case (6),
query(t370,'csp ndc');
i=i+2;
case (7),
query(t370,'csp nle');
i=i+2;
otherwise,
fclose(t370);
error('Wrong polarity argument. Try ''help get_trace''.');
end;
case {'var','variable'}, % setting Variable Collector Supply
s = varargin{i+1};
if (isnumeric(s) & s>=0 & s<=100),
query(t370,['vcs ' num2str(s)]);
i=i+2;
else,
fclose(t370);
error('Wrong ''var'' argument. Try ''help get_trace''.');
end;
case ('step'), % Setting the step generator
switch varargin{i+1},
case {'current','curr','cur'}, %current
s=varargin{i+2};
if (isnumeric(s) & s>=5e-8 & s<= 0.2),
query(t370,['stp cur:' num2str(s)]);
i=i+3;
else,
fclose(t370);
error(['Wrong arguments for step generator. '...
'Current must be a number in the range [5e-8 2e-1].']);
end;
case {'v','volt','vol'}, %Voltage
s=varargin{i+2};
if (isnumeric(s) & s>=0.05 & s<= 2),
query(t370,['stp vol:' num2str(s)]);
i=i+3;
else,
fclose(t370);
error(['Wrong arguments for step generator. '...
'Voltage must be a number in the range [0.05 2].']);
end;
otherwise,
s=varargin{i+1};
if (isnumeric(s) & mod(s,1)==0 & s>=0 & s<=10),
query(t370,['stp num:' num2str(s)]);
i=i+2;
else,
fclose(t370);
error('Wrong Step arguments. Try ''help get_trace''.');
end;
end; %switch varargin{i+1},
case {'inv', 'invert'},
s=lower(varargin{i+1});
if (~strcmp(s,'on') & ~strcmp(s,'off')),
fclose(t370);
error('Wrong Invert Parameter. Should be ''ON'' or ''OFF''.');
end;
query(t370,['dis inv:' s]);
i=i+2;
otherwise,
fclose(t370);
error([ varargin{i} ': unrecognized input paramter.']);
end; %switch varargin{i}
end; % while (i<=nargin)
pause (1);
end; % if (nargin>0)
% Now, after changing the settings that we wanted
% (extracting varargin), we are ready to read the
% curve... first - the preamble data.
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Reading waveform preamble: %
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
S=query(t370,'wfm?'); % Reading the preamble string from 370.
s=lower(S); % Converting to lower case to avoid case mismatch.
vars={'xmult','xzero','xoff',... % These are the variables we are interested in.
'ymult','yzero','yoff'}; % both for X and Y. The data is read from the 370
% in x,y coordinates of the curve in pixels units
% from the CRT. The scaling is:
% X = xzero + xmult * (x(read) - xoff).
% For more information see page 4-48 in the manual.
p1=find(s==':');
p2=find(s==','); % looking for the ':' & ',' characters in the
% preamble string - the numbers are between these
% two characters. For example:
% '...XMULT:+2.0E-2,XZERO: 0,XOFF: 512,...'
%
for i=1:length(vars), % looking for the variables in the string
pp=findstr(s,vars{i}); % finding where the i'th variable is
pp1=min(find(p1>pp)); % find th next ':' symbol
pp2=min(find(p2>pp)); % find the next ','
tmp_str=s(p1(pp1)+1:p2(pp2)-1); % extract the number in between these two symbols
eval(['param.' vars{i}...
' =str2num(tmp_str);']); % param is a structure consist of these variables.
end;
% Now we have read all the information we need from
% the preamble vector and are ready to read the curve itself.
%
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% % Reading Curve: %
% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
s=query(t370,'wfm? nr.pt'); % Reading number of points
n=sscanf(s,'WFMPRE NR.PT:%d');
fprintf(t370,'cur?'); % asking for curve data
fscanf(t370,'uchar',22); % skipping the header
tmp = fread(t370,1,'char');
while (tmp ~= 37), % reading until a '%' is read (value 37)
tmp = fread(t370,1,'char');
end;
fread(t370,2,'char'); % skipping the number of points,
% now the pointer is on 1st x data
d=fread(t370,n*4,'char'); % Reading the curve data (x & y, 2 bytes each number);
fclose(t370); % done with the 370, can be closed.
% now we have to construct the x and y from this data. it is 2 byte each number, in
% a row of x1,y1, x2, y2, x3,....
d_odd = d(1:2:end); % these are the MSB
d_even = d(2:2:end); % and the LSB
d_real = d_odd*256+d_even; % MSB is multiplied by 256 (8bit)
dx=d_real(1:2:end); % x data are the odds,
dy=d_real(2:2:end); % and y are the evens.
% now scaling the reading based on the preamble data:
if (isempty(param.ymult)),
param.ymult = 1;
warning('y units are unknown!');
end;
if (isempty(param.xmult)),
param.xmult = 1;
warning('x units are unknown!');
end;
x = param.xzero + param.xmult*(dx - param.xoff); % see page 4-48 in the 370 manual
y = param.yzero + param.ymult*(dy - param.yoff); % "
varargout{1}=x;
varargout{2}=y;