function varargout = tof(varargin)
% TOF demonstrates sound ranging (sonar) between PC
% speaker and microphone (up to 6m away).
%
% This demo requires:
% - Data Acquisition Toolbox,
% - Signal Processing Toolbox
% - Windows sound card
% - files: sonar_anal.m tof.fig tof.m (this file)
%
% How does it work?
% A pulse wave (chirp) is generated from the speaker,
% which travels through air at the speed of sound.
% At the same time the microphone records the received
% wave (plus possible reflections depending on room
% acoustics). The propagation time delay (sec) is
% measured and converted to distance (m).
% Copyright 2001-2010 The MathWorks, Inc.
% TOF Application M-file for tof.fig
% FIG = TOF launch tof GUI.
% TOF('callback_name', ...) invoke the named callback.
% Last Modified by GUIDE v2.0 18-Oct-2001 17:27:18
% Updated by R.Bemis July 5, 2007
% * Removed hard coded calibrations - less accurate, more robust
if nargin == 0 % LAUNCH GUI
fig = openfig(mfilename,'reuse');
% Use system color scheme for figure:
set(fig,'Color',get(0,'defaultUicontrolBackgroundColor'));
% Generate a structure of handles to pass to callbacks, and store it.
handles = guihandles(fig);
guidata(fig, handles);
%sonar_setup(handles,0.0087) % set up audio I/O
sonar_setup(handles,0) % set up audio I/O
if nargout > 0
varargout{1} = fig;
end
elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK
try
if (nargout)
[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
else
feval(varargin{:}); % FEVAL switchyard
end
catch
disp(lasterr);
end
end
%| ABOUT CALLBACKS:
%| GUIDE automatically appends subfunction prototypes to this file, and
%| sets objects' callback properties to call them through the FEVAL
%| switchyard above. This comment describes that mechanism.
%|
%| Each callback subfunction declaration has the following form:
%| <SUBFUNCTION_NAME>(H, EVENTDATA, HANDLES, VARARGIN)
%|
%| The subfunction name is composed using the object's Tag and the
%| callback type separated by '_', e.g. 'slider2_Callback',
%| 'figure1_CloseRequestFcn', 'axis1_ButtondownFcn'.
%|
%| H is the callback object's handle (obtained using GCBO).
%|
%| EVENTDATA is empty, but reserved for future use.
%|
%| HANDLES is a structure containing handles of components in GUI using
%| tags as fieldnames, e.g. handles.figure1, handles.slider2. This
%| structure is created at GUI startup using GUIHANDLES and stored in
%| the figure's application data using GUIDATA. A copy of the structure
%| is passed to each callback. You can store additional information in
%| this structure at GUI startup, and you can change the structure
%| during callbacks. Call guidata(h, handles) after changing your
%| copy to replace the stored original so that subsequent callbacks see
%| the updates. Type "help guihandles" and "help guidata" for more
%| information.
%|
%| VARARGIN contains any extra arguments you have passed to the
%| callback. Specify the extra arguments by editing the callback
%| property in the inspector. By default, GUIDE sets the property to:
%| <MFILENAME>('<SUBFUNCTION_NAME>', gcbo, [], guidata(gcbo))
%| Add any extra arguments after the last argument, before the final
%| closing parenthesis.
% --------------------------------------------------------------------
function varargout = Single_Callback(h, eventdata, handles, varargin)
set(handles.Repeat,'enable','off') % disable Repeat button
sonar_once(handles.figure1) % take one measurement
% --------------------------------------------------------------------
function varargout = Repeat_Callback(h, eventdata, handles, varargin)
set(h,'enable','off') % disable Repeat button
set(handles.Single,'enable','off') % disbale Single button
set(handles.Stop,'enable','on') % enable Stop button
sonar_run(handles.figure1) % measure repeatedly
% --------------------------------------------------------------------
function varargout = Stop_Callback(h, eventdata, handles, varargin)
set(h,'enable','off') % disable Stop button
set(handles.Repeat,'enable','on') % enable Repeat button
set(handles.Single,'enable','on') % enable Single button
sonar_stop(handles.figure1) % stop repeats
% --------------------------------------------------------------------
function sonar_setup(handles,cal_dist)
fig = handles.figure1; % figure handle
if nargin<2
cal_dist = 0;
end
% physics
c = 330; % speed of sound (m/sec)
d = 50; % max distance (m)
Td = d/c; % max return time (sec)
pw = 0.01; % pulse width (sec)
Tmax = Td+pw; % total response time (sec)
% DAQ parameters
ai = analoginput('winsound'); % create AI object
addchannel(ai,1); % single channel (mono)
Fs = setverify(ai,'samplerate',44100); % sample rate (Hz)
N = 2^ceil(log2(Tmax*Fs)); % buffer size (samples)
ao = analogoutput('winsound'); % create AO object
addchannel(ao,1); % single channel (mono)
ao.SampleRate=Fs; % output Fs same as input
% excitation chirp
f0 = 4e3; % low freq (Hz)
f1 = 8e3; % high freq (Hz)
t = (0:(1/Fs):pw)'; % time index (sec)
n = length(t); % pulse length (samples)
pulse = chirp(t,f0,pw,f1); % chrip waveform (short)
pulse = pulse.*hanning(n); % pulse envelope
pad = zeros(N-n,1); % silence trailing chirp
x = [pulse; pad]; % excitation (zero padded)
% response waveform
ai.SamplesPerTrigger = N; % total samples to acquire
ai.TriggerDelayUnits = 'sec';
ai.TriggerDelay = cal_dist/c; % calibration lag (sec)
ai.SamplesAcquiredFcnCount = N;
ai.SamplesAcquiredFcn = ['sonar_anal(' num2str(fig) ')'];
% user data
ud.ai = ai; % audio input
ud.ao = ao; % audio output
ud.c = c; % wave speed in air
ud.x = x; % excitation waveform
ud.h = handles; % guide figure handles
set(fig,'userdata',ud) % store bundle with figure
% --------------------------------------------------------------------
function sonar_once(fig)
% user data
ud = get(fig,'userdata'); % user data fields
ai = ud.ai; % audio input
ao = ud.ao; % audio output
x = ud.x; % excitation chirp pulse
ai.samplesacquiredfcn = ''; % don't repeat measurement
putdata(ao,x) % arm audio output
start([ai ao]) % start measurement
sonar_anal(fig) % manually analyze data
% --------------------------------------------------------------------
function sonar_run(fig)
% user data
ud = get(fig,'userdata'); % user data fields
ai = ud.ai; % audio input
ao = ud.ao; % audio output
x = ud.x; % excitation chirp pulse
% callback function to analyze when done acquiring data
ai.samplesacquiredfcn = ['sonar_anal(' num2str(fig) ')'];
% NOTE: sonar_anal will rearm output and repeat measurement
putdata(ao,x) % arm audio output
start([ai ao]) % start measuring (will repeat)
% --------------------------------------------------------------------
function sonar_stop(fig)
% user data
ud = get(fig,'userdata'); % user data fields
ai = ud.ai; % audio input
ai.samplesacquiredfcn = ''; % stop repeating
% --------------------------------------------------------------------
function sonar_cleanup(fig)
% user data
ud = get(fig,'userdata'); % user data fields
ai = ud.ai; delete(ai) % remove audio input
ao = ud.ao; delete(ao) % remove audio output
% --------------------------------------------------------------------
function varargout = figure1_CloseRequestFcn(h, eventdata, handles, varargin)
sonar_stop(handles.figure1) % stops if still repeating
sonar_cleanup(handles.figure1) % remove audio objects
delete(handles.figure1) % remove figure window