Commit 9ebbee66 authored by Mueller-Trapet's avatar Mueller-Trapet

added GUI with channel selection for NI cards

parent 98570654
......@@ -93,6 +93,14 @@ classdef itaMSTFni < itaMSTF
addlistener(this,'outputChannels','PostSet',@this.init);
end
function this = edit(this)
% edit - Start GUI.
%
% This function calls the itaMSTFni GUI.
this = ita_mstfni_gui(this);
end
function init(this,varargin)
% init - Initialize the itaMSTFni class object.
% call the parent init function first
......@@ -102,6 +110,18 @@ classdef itaMSTFni < itaMSTF
this.niSession = init_NI_card(this);
end
function checkready(this)
%check if the instance is ready for measurement run and ask for
%missing entries
if isempty(this.inputChannels) || isempty(this.outputChannels)
this.edit;
end
% has the NI session been initialized
if isempty(this.niSession.Channels)
this.init;
end
end
function MS = calibrationMS(this)
% call the parent function
MS = calibrationMS@itaMSTF(this);
......
function varargout = ita_channelselect_gui_ni( varargin )
% Show gui to select channels for input and output (NI hardware)
%
% Syntax: [in_ch out_ch] = ita_channelselect_gui_ni()
% [in_ch out_ch] = ita_channelselect_gui_ni(in_ch_preselct, out_ch_preselect)
%
% <ITA-Toolbox>
% This file is part of the ITA-Toolbox. Some rights reserved.
% You can find the license for this m-file in the license.txt file in the ITA-Toolbox folder.
% </ITA-Toolbox>
% Author: Markus Mueller-Trapet -- Email: markus.mueller-trapet@nrc.ca
% Created: 10-May-2017
%% Get maximum input and output channels
% Initialization
[inputChannels,outputChannels] = ita_get_ni_deviceinfo();
out = numel(outputChannels.name);
out = max(out,0); %Filter '-1' in case that no device is selected
in = numel(inputChannels.name);
in = max(in,0); %Filter '-1' in case that no device is selected
if nargin == 0
varargin{1} = 1:in; varargin{2} = 1:out;
end
sArgs = struct('pos1_a','int','pos2_b','int','onlyinput','false','onlyoutput','false');
[in_ch,out_ch,sArgs] = ita_parse_arguments(sArgs,varargin);
if sArgs.onlyinput
out = 0;
elseif sArgs.onlyoutput
in = 0;
end
%% Draw - 8 channels in a row
if ~mod(out,8)
out_height = out/8;
else
out_height = (out - mod(out,8))/8 + 1;
end
if ~mod(in,8)
in_height = in/8;
else
in_height = (in - mod(in,8))/8 + 1;
end
%figure
height = (2 + in_height + 1 + out_height + 1) * 40;
ch_width = 70;
width = (8+3)*(ch_width - 15);
persistent hFig
if ~isempty(hFig) && ishandle(hFig) && strcmpi(get(hFig,'Name'),'PortAudio IO Channels')
close(hFig)
end
hFig = figure('Name','PortAudio IO Channels',...
'Position',[300 200 width height],...
'MenuBar','none', ...
'Toolbar','none', ...
'HandleVisibility','on',...
'NumberTitle','off', ...
'Color', [0.8 0.8 0.8]);
%ITA toolbox logo with grey background
a_im = importdata(which('ita_toolbox_logo.png'));
image(a_im);axis off
set(gca,'Units','pixel', 'Position', [20 20 200 35]); %TODO: later set correctly the position
%% Headline Texts
if in
uicontrol(...
'Parent', hFig,...
'Position',[20 (1+out_height+1+in_height+1)*40-20 200 20],...
'HorizontalAlignment','left',...
'String','Input Channels',...
'FontSize',13,...
'FontWeight','bold',...
'Style', 'text',...
'ForegroundColor', [0 0 0],...
'BackgroundColor', [0.8 0.8 0.8]);
end
if out
uicontrol(...
'Parent', hFig,...
'Position',[20 (1+out_height+1)*40-20 200 20],...
'HorizontalAlignment','left',...
'String','Output Channels',...
'FontSize',13,...
'FontWeight','bold',...
'Style', 'text',...
'ForegroundColor', [0 0 0],...
'BackgroundColor', [0.8 0.8 0.8]);
end
%% Input Channels
for jdx = 1:in
uicontrol(...
'Parent', hFig,...
'Position',[20+(mod(jdx-1,8))*ch_width (1+out_height+1+in_height-(jdx-mod(jdx-1,8)+1)/8)*40+2 30 15],...
'HorizontalAlignment','right',...
'String', ['Ch' num2str(jdx)],...
'Style', 'text',...
'ForegroundColor', [1 .1 .1],...
'BackgroundColor', [0.8 0.8 0.8]);
end
if isempty(in_ch)
in_ch = 1:in;
end
for jdx = 1:in
h(jdx).in = uicontrol(...
'Parent', hFig,...
'Position',[50 + (mod(jdx-1,8))*ch_width (1+out_height+1+in_height-(jdx-mod(jdx-1,8)+1)/8)*40-5 20 30],...
'Style', 'checkbox',...
'Value',ismember(jdx,in_ch),...
'ForegroundColor', [0 0 .7],...
'BackgroundColor', [0.8 0.8 0.8]);
end
%% Output Channels
for jdx = 1:out
uicontrol(...
'Parent', hFig,...
'Position',[20+(mod(jdx-1,8))*ch_width (1+out_height-(jdx-mod(jdx-1,8)+1)/8)*40+2 30 15],...
'HorizontalAlignment','right',...
'String', ['Ch' num2str(jdx)],...
'Style', 'text',...
'ForegroundColor', [.1 0.6 .1],...
'BackgroundColor', [0.8 0.8 0.8]);
end
if isempty(out_ch)
out_ch = 1:out;
end
for jdx = 1:out
h(jdx).out = uicontrol(...
'Parent', hFig,...
'Position',[50+(mod(jdx-1,8))*ch_width (1+out_height-(jdx-mod(jdx-1,8)+1)/8)*40-5 20 30],...
'Style', 'checkbox',...
'Value',ismember(jdx,out_ch),...
'ForegroundColor', [0 0 .7],...
'BackgroundColor', [0.8 0.8 0.8]);
end
%% Buttons
% Cancel Button
uicontrol(...
'Parent', hFig, ...
'Position',[330 20 80 30],...
'String', 'Cancel',...
'Style', 'pushbutton',...
'Callback', @CancelButtonCallback,...
'BackgroundColor', [0.7 0.7 0.7]);
% Ok Button
uicontrol(...
'Parent', hFig, ...
'Position',[430 20 80 30],...
'String', 'OK',...
'Style', 'pushbutton',...
'Callback', @OkayButtonCallback,...
'BackgroundColor', [0.7 0.7 0.7]);
uiwait(hFig);
%% Callbacks
function CancelButtonCallback(hObject,eventdata) %#ok<INUSD>
uiresume(gcf);
close(hFig)
%choose output arguments
if sArgs.onlyinput
varargout{1} = in_ch;
elseif sArgs.onlyoutput
varargout{1} = out_ch;
else
varargout{1} = in_ch;
varargout{2} = out_ch;
end
return;
end
function OkayButtonCallback(hObject,eventdata) %#ok<INUSD>
in_ch = [];
for jdx2 = 1:in
if get(h(jdx2).in,'Value') == get(h(jdx2).in,'Max')
in_ch = [in_ch jdx2]; %#ok<*AGROW>
end
end
out_ch = [];
for jdx2 = 1:out
if get(h(jdx2).out,'Value') == get(h(jdx2).out,'Max')
out_ch = [out_ch jdx2];
end
end
uiresume(gcf);
close(hFig)
%choose output arguments
if sArgs.onlyinput
varargout{1} = in_ch;
elseif sArgs.onlyoutput
varargout{1} = out_ch;
else
varargout{1} = in_ch;
varargout{2} = out_ch;
end
return;
end
end
function varargout = ita_mstfni_gui(varargin)
%ITA_MSTFNI_GUI - Edit a measurement setup for transfer functions (NI hardware)
% <ITA-Toolbox>
% This file is part of the application Measurement for the ITA-Toolbox. All rights reserved.
% You can find the license for this m-file in the application folder.
% </ITA-Toolbox>
% Author: Markus Mueller-Trapet -- Email: markus.mueller-trapet@nrc.ca
% Created: 10-May-2017
pList = [];
argList = [];
%GUI Init
if nargin == 1
MS = varargin{1};
else
MS = itaMSTFni;
end
ele = numel(pList)+1;
pList{ele}.datatype = 'line';
ele = numel(pList)+1;
pList{ele}.datatype = 'text';
pList{ele}.description = 'Basic settings';
pList{ele}.color = 'black';
ele = numel(pList)+1;
pList{ele}.description = 'Preferences';
pList{ele}.helptext = 'Call ita_preferences()';
pList{ele}.datatype = 'simple_button';
pList{ele}.default = '';
pList{ele}.callback = 'ita_preferences();';
ele = numel(pList)+1;
pList{ele}.description = 'Input Channels';
pList{ele}.helptext = 'Vector with the input channel numbers. The order specified here is respected!';
pList{ele}.datatype = 'int_result_button';
pList{ele}.default = MS.inputChannels;
if isempty(pList{ele}.default)
pList{ele}.default = 1;
end
pList{ele}.callback = 'ita_channelselect_gui_ni([$$],[],''onlyinput'')';
argList = [argList {'inputChannels'}];
ele = numel(pList)+1;
pList{ele}.description = 'Output Channels';
pList{ele}.helptext = 'Vector with the output channel numbers. The order specified here is respected!';
pList{ele}.datatype = 'int_result_button';
pList{ele}.default = MS.outputChannels;
if isempty(pList{ele}.default)
pList{ele}.default = 1;
end
pList{ele}.callback = 'ita_channelselect_gui_ni([],[$$],''onlyoutput'')';
argList = [argList {'outputChannels'}];
ele = numel(pList)+1;
pList{ele}.datatype = 'line';
ele = numel(pList)+1;
pList{ele}.datatype = 'text';
pList{ele}.description = 'Signal Specifications';
ele = numel(pList)+1;
pList{ele}.description = 'FFT Degree';
pList{ele}.helptext = 'Length of the signal (2^fft_degree samples)';
pList{ele}.datatype = 'int';
pList{ele}.default = MS.fftDegree;
argList = [argList {'fftDegree'}];
ele = numel(pList)+1;
pList{ele}.description = 'Frequency Limits [Hz]';
pList{ele}.helptext = 'The sweep will start at low frequency and rise up to high frequency';
pList{ele}.datatype = 'int';
pList{ele}.default = MS.freqRange;
argList = [argList {'freqRange'}];
ele = numel(pList)+1;
pList{ele}.description = 'Signal Type';
pList{ele}.helptext = 'Exponential/logarithmic sweeps and linear sweeps can be choosen.)';
pList{ele}.datatype = 'char_popup';
pList{ele}.default = MS.type;
pList{ele}.list = 'exp|lin|noise';
argList = [argList {'type'}];
ele = numel(pList)+1;
pList{ele}.description = 'Stop Margin [s]';
pList{ele}.helptext = 'This is the time of silence in the end of the sweep. It should be longer than the reverberation time at the highest frequency.';
pList{ele}.datatype = 'int';
pList{ele}.default = MS.stopMargin;
argList = [argList {'stopMargin'}];
ele = numel(pList)+1;
pList{ele}.description = 'Output Amplification [dBFS]';
pList{ele}.helptext = 'Attenuate your sweep by this value in dB Full Scale. Compensation will follow, we will take care of this.';
pList{ele}.datatype = 'char';
pList{ele}.default = MS.outputamplification;
argList = [argList {'outputamplification'}];
ele = numel(pList)+1;
pList{ele}.description = 'Comment';
pList{ele}.helptext = 'Give your child a name';
pList{ele}.datatype = 'char_long';
pList{ele}.default = MS.comment;
argList = [argList {'comment'}];
ele = numel(pList)+1;
pList{ele}.datatype = 'line';
ele = numel(pList)+1;
pList{ele}.datatype = 'text';
pList{ele}.description = 'Advanced settings';
pList{ele}.color = 'red';
ele = numel(pList)+1;
pList{ele}.description = 'Pause before measurements';
pList{ele}.helptext = 'Time in seconds the routine waits before each measurement';
pList{ele}.datatype = 'int';
pList{ele}.default = MS.pause;
argList = [argList {'pause'}];
ele = numel(pList)+1;
pList{ele}.description = 'Number of Averages';
pList{ele}.helptext = 'How many measurements should be averaged for the final results?';
pList{ele}.datatype = 'int';
pList{ele}.default = MS.averages;
argList = [argList {'averages'}];
ele = numel(pList)+1;
pList{ele}.description = 'Linear Deconvolution';
pList{ele}.helptext = 'Standard is cyclic deconvolution. To seperate distortion from the noise tail use linear deconvolution. Signal length is therefore doubled.';
pList{ele}.datatype = 'bool';
pList{ele}.default = MS.lineardeconvolution;
argList = [argList {'lineardeconvolution'}];
ele = numel(pList)+1;
pList{ele}.description = 'Output Equalization';
pList{ele}.helptext = 'Do a broadband output equalization (only with calibrated output measurement chain)';
pList{ele}.datatype = 'bool';
pList{ele}.default = MS.outputEqualization;
argList = [argList {'outputEqualization'}];
ele = numel(pList)+1;
pList{ele}.description = 'Measurement Chain';
pList{ele}.helptext = 'Whether to use the measurement chain functionality (calibration)';
pList{ele}.datatype = 'bool';
pList{ele}.default = MS.useMeasurementChain;
argList = [argList {'useMeasurementChain'}];
ele = numel(pList)+1;
pList{ele}.datatype = 'line';
%call gui
pList = ita_parametric_GUI(pList,[mfilename ' - Modify an itaMSTF']);
pause(0.02); %wait for GUI to close first
% Check output amplifiction
if isempty(pList) %user cancelled
varargout{1} = [];
return;
end
%% settings to MSTF
%reorder first, useMeasurementChain does not work otherwise
pList = [pList(end) pList(1:end-1)];
argList = [argList(end) argList(1:end-1)];
for idx = 1:numel(pList)
MS.(argList{idx}) = pList{idx};
end
varargout{1} = MS;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment