function varargout = fg_cmd(cmd) % % This is a convenience/neatness wrapper for running the % HP 33120A Function Generator from Matlab's ICT % (Instrument Control Toolbox) over GPIB (HPIB, IEEE-488). % % The input argument may be any of several types: % * numeric input is assumed to be a vector of data for sending % as a waveform; it is sent in binary form for best speed % * a string may be one of the special strings !!CONNECT!! or % !!DISCONNECT!!, to connect to the instrument to or disconnect % it from the global handle ih.fg (instrument handle, function % generator); otherwise, a string is a command % * cell input is assumed to be a list of commands % % If a command contains a question mark, then a (single-line) will % be read from the instrument will be attempted, and the result stored % in an output cell arrary or string. % % Instrument errors are checked and displayed after the command has completed. % % Nathaniel, 2010-02-17. % % global variable (to avoid having to provide the instrument % handle as an argument) containing the field .fg for the % function-generator global ih; % checking if isempty(cmd), error('expected a single non-empty string argument'); end if nargout>1, error('only zero or one output arguments are used'); end out = cell(size(cmd)); % define the special command strings !!CONNECT!! or !!DISCONNECT!! % to manage the instrument's connection and not actually send the % command string to the instrument if ischar(cmd) && ~isempty(regexp(cmd, '^!!CONNECT!!$')), fgen = 'GPIB0::10::INSTR'; fprintf('\nOpening connection to Function Generator (HP33120A) on %s\n', fgen); ih.fg = visa('ni', fgen); set(ih.fg, 'TimeOut', 3.0, ... 'ByteOrder', 'BigEndian', ... 'InputBufferSize', 2^16, ... 'OutputBufferSize', 2^16, ... 'RecordDetail', 'verbose', ... 'RecordName', 'comms_log_funcgen.txt'); fopen(ih.fg); record(ih.fg, 'on'); fgen_idn = query(ih.fg,'*IDN?\n', '%s\n'); fgen_idn = regexprep(fgen_idn, '[\r\n]', ''); fprintf('IDN response: "%s"\n\n', fgen_idn); fprintf(ih.fg, '%s\n', '*RST'); fprintf(ih.fg, '%s\n', '*CLS'); fprintf(ih.fg, '%s\n', 'OUTPUT:LOAD INF'); fprintf(ih.fg, '%s\n', 'OUTPUT:SYNC ON'); fprintf(ih.fg, '%s\n', 'VOLT:UNIT VPP'); elseif ischar(cmd) && ~isempty(regexp(cmd, '^!!DISCONNECT!!$')), if isfield(ih, 'fg'), fclose(ih.fg); delete(ih.fg); ih = rmfield(ih, 'fg'); else warning('instrument apparently not open: ignoring'); end return; % avoid running error check on closed instrument elseif isnumeric(cmd), % waveform data s = reshape(cmd, 1, []); if length(s)<8, error('waveform data must be >= 8 points long'); elseif length(s)>16000, error('waveform data must be <=16000 points long'); end nnn = sprintf('%d', 2*length(s)); % number of bytes in data (as text) N = sprintf('%d', length(nnn)); % number of characters in 'nnn' binhead = double(['DATA:DAC VOLATILE, #',N,nnn]); % make the header bindata = zeros(1,2*length(s)); % array for the data bytes s_max = max(abs(s)); for ni = 1:length(s), % convert to range of 12bit signed integer: -2048 < si < +2048 si = round(2046*s(ni)/s_max); % if negative, convert to the positive integer with same bit-pattern % (remember: for "2's complement" numbers, this can be done by % inverting each bit and then adding 1 to the result) if si<0, si = double( uint16(1) + bitxor(uint16(abs(si)),uint16(2^16)) ); end % now it's an integer 0<=si<=4096: split it into high byte and low byte bindata(2*ni-1) = (si - mod(si,256))/256; bindata(2*ni) = mod(si,256); end % write it all in one go: header then data % (temporarily increase timeout for this) to_o = get(ih.fg, 'Timeout'); set(ih.fg, 'Timeout', 30); try started = clock; fwrite(ih.fg, [binhead,bindata], 'uint8'); fprintf('transferred %d-point waveform in %.2fs\n', ... length(s), etime(clock,started)); catch fprintf('something bad happened when writing the waveform:\n'); lasterr end set(ih.fg, 'Timeout', to_o); elseif iscell(cmd) || ischar(cmd), % plain commands if ischar(cmd), % single string --> cell (consistency) cmd = { cmd }; charout = 1; else charout = 0; end for n=1:numel(cmd), c = cmd{n}; if ~ischar(c), warning('command %d is not a string: skipping', n); continue; end % write the command fprintf(ih.fg, '%s\n', c); if ~isempty(regexp(c, '\?')), out{n} = regexprep(fgetl(ih.fg), '\r', ''); if charout, % if character (single-command) input, give char out too out = out{1}; end end end if nargout>0, % provide the output if asked varargout{1} = out; end else error('input argument not of accepted type (numeric, string or cell)'); end % ask for, and display, any error state in the function generator for n=1:20, nexterr = query(ih.fg, 'SYSTEM:ERROR?', '%s\n'); if regexp(nexterr, '^\+0,'), break; end fprintf('after command "%s":\n\tfuncgen error: %s\n', c, nexterr); end