| Line 509: |
Line 509: |
| | | | |
| | <nowiki> | | <nowiki> |
| − | % ===================================================================================================
| + | function handle = buttonbox(cmd,varargin) |
| − | function handle = serial_buttonbox_common(cmd,varargin)
| + | % to initialize connection: |
| − | %
| + | % define settings as structure with fields: |
| − | % NOTE: this is a functional example, please adapt code according to your needs.
| + | % bb.Device = 'COM3'; |
| − | %
| + | % bb.BaudRate = 115200; |
| − | % to initialize connection:
| + | % bb.DataBits = 8; |
| − | % handle = serial_buttonbox_common('open',se)
| + | % bb.StopBits = 1; |
| − | % settings (se):
| + | % bb.Parity = 'none'; |
| − | % define settings as a structure, i.e.:
| + | % handle = buttonbox('open',bb) |
| − | % se.Device = 'COM2';
| + | % |
| − | % se.BaudRate = 115200;
| + | % to run: |
| − | % se.DataBits = 8;
| + | % buttonbox('run',handle); |
| − | % se.StopBits = 1;
| + | % |
| − | % se.Parity = 0;
| + | % to close the connection: |
| − | % se.PTBPath = 'c:\toolboxes\PsychToolbox'
| + | % buttonbox('close',handle); |
| − | %
| + | |
| − | % to run:
| + | persistent old_hdl % keep handle to COM object persistent |
| − | % serial_buttonbox_common('run')
| + | |
| − | %
| + | % set defaults |
| − | % to close the connection:
| + | bb.Device = 'COM3'; |
| − | % serial_buttonbox_common('close',handle);
| + | bb.BaudRate = 115200; |
| − |
| + | bb.DataBits = 8; |
| − | persistent old_hdl | + | bb.StopBits = 1; |
| − |
| + | bb.Parity = 'none'; |
| − | % set defaults
| + | |
| − | se.Device = 'COM2';
| + | if nargin < 1 |
| − | se.BaudRate = 115200;
| + | cmd = 'open'; |
| − | se.DataBits = 8;
| + | end |
| − | se.StopBits = 1;
| + | if nargin > 1 |
| − | se.Parity = 0;
| + | % user overwrites default settings |
| − | se.PTBPath = 'c:\toolboxes\PsychToolbox';
| + | flds = fields(varargin{1}); |
| − |
| + | for n = 1 : numel(flds) |
| − | if nargin < 1
| + | bb.(flds{n}) = varargin{1}.(flds{n}); |
| − | cmd = 'open';
| + | end |
| − | end
| + | end |
| − | if nargin > 1
| + | |
| − | % user overwrites default settings
| + | |
| − | flds = fields(varargin{1});
| + | switch cmd |
| − | for n = 1 : numel(flds)
| + | case 'open' |
| − | se.(flds{n}) = varargin{1}.(flds{n});
| + | % get handle to serial device |
| − | end
| + | handle = open_buttonbox(bb); |
| − | end
| + | return |
| − |
| + | case 'close' |
| − |
| + | if nargin > 0 |
| − | switch cmd
| + | handle = varargin{1}; |
| − | case 'open'
| + | else |
| − | addpath(genpath(se.PTBPath));
| + | handle = old_hdl; |
| − | % get handle to serial device
| + | end |
| − | handle = open_buttonbox(se.Device);
| + | fclose(handle); |
| − | return
| + | return |
| − | case 'close'
| + | case 'run' |
| − | handle = varargin{1};
| + | % read incoming data |
| − | IOPort('close',handle);
| + | if isempty(old_hdl) |
| − | return
| + | help serial_buttonbox_common |
| − | case 'run'
| + | error('Buttonbox not yet initialized'); |
| − | % read incoming data
| + | end |
| − | if isempty(old_hdl)
| + | handle = old_hdl; |
| − | help serial_buttonbox_common
| + | otherwise |
| − | error('Buttonbox not yet initialized');
| + | fprintf('Unknown option %s\n',cmd); |
| − | end
| + | return |
| − | handle = old_hdl;
| + | end |
| − | otherwise
| + | |
| − | fprintf('Unknown option %s\n',cmd);
| + | % only gets here when cmd = 'run' |
| − | return
| + | % Initialize output figure |
| − | end
| + | win = list_output(' ',[]); |
| − |
| + | while 1 |
| − | % only gets here when cmd = 'run'
| + | % Exit if user closed output figure |
| − | while 1
| + | if ~ishandle(win) |
| − | % start polling for characters (indicating start of scan)
| + | return |
| − | navailable = IOPort('BytesAvailable', handle);
| + | end |
| − | if navailable
| + | % start polling for characters (indicating start of scan) |
| − | data = [];
| + | navailable = handle.BytesAvailable; |
| − | while navailable
| + | if navailable |
| − | % read incoming data
| + | data = []; |
| − | [newdata, ~, err] = IOPort('Read', handle, 0, navailable);
| + | while navailable |
| − | if ~isempty(err), disp(err); end
| + | % read incoming data |
| − | data = [data newdata];
| + | [newdata, cnt] = fread(handle, navailable); |
| − | %pause(0.001); % if possible just add a small pause to not claim entire core
| + | % concatenate possible new data |
| − | navailable = IOPort('BytesAvailable', handle);
| + | if cnt |
| − | end
| + | data = [data newdata(:)]; |
| − | if numel(data)>1
| + | end |
| − | fprintf('\nReceived characters: %d\n',numel(data));
| + | % check if any more data left |
| − | end
| + | navailable = handle.BytesAvailable; |
| − | for n = 1 : numel(data)
| + | end |
| − | % disp(char(data(n)));
| + | % output info about which button was pressed |
| − | fprintf('incoming: %d\t%s\n',data(n),char(data(n)));
| + | for n = 1 : numel(data) |
| − | end
| + | line = sprintf('incoming: %03d %s',data(n),char(data(n))); |
| − | end
| + | list_output(line,win); |
| − |
| + | end |
| − |
| + | end |
| − | end %while 1
| + | pause(0.01); |
| − |
| + | end %while 1 |
| − | function hdl = open_buttonbox(device)
| + | |
| − | % open handle to serial device (mini buttonbox)
| + | function hdl = open_buttonbox(device) |
| − | try
| + | % open handle to serial device (mini buttonbox) |
| − | hdl = IOPort('OpenSerialPort',device,['BaudRate=' num2str(se.BaudRate)]);
| + | try |
| − | catch
| + | hdl = serial(device.Device, 'Baudrate', device.BaudRate, 'DataBits', device.DataBits, 'StopBits', device.StopBits, 'Parity', device.Parity); |
| − | if ~isempty(old_hdl)
| + | fopen(hdl); |
| − | IOPort('close',old_hdl);
| + | catch |
| − | end
| + | if ~isempty(old_hdl) |
| − | hdl = IOPort('OpenSerialPort',device,['BaudRate=' num2str(se.BaudRate)]);
| + | fclose(old_hdl); |
| − | end
| + | delete(old_hdl); |
| − | old_hdl = hdl;
| + | end |
| − |
| + | hdl = serial(device.Device, 'Baudrate', device.BaudRate, 'DataBits', device.DataBits, 'StopBits', device.StopBits, 'Parity', device.Parity); |
| − | fprintf('Wait for device buttonbox....\n');
| + | fopen(hdl); |
| − | tic
| + | end |
| − | while ~IOPort('BytesAvailable', hdl) && toc<10
| + | old_hdl = hdl; |
| − | % wait for welcome message device
| + | |
| − | end
| + | fprintf('Wait for device buttonbox....\n'); |
| − | pause(0.5);
| + | tic |
| − |
| + | while hdl.BytesAvailable && toc<10 |
| − | % clear buffer
| + | navailable = bbox.BytesAvailable; |
| − | %IOPort('flush', hdl);
| + | % wait for welcome message device |
| − | IOPort('purge', hdl); | + | fread(hdl, navailable); |
| − | end
| + | end |
| − |
| + | pause(0.5); |
| − | end</nowiki>
| + | end |
| | + | |
| | + | function win = list_output(line,win) |
| | + | persistent ptr |
| | + | persistent lines |
| | + | persistent edt |
| | + | Maxlines = 40; |
| | + | |
| | + | if isempty(win) |
| | + | % initialize listbox output figure |
| | + | lines = cell(1,Maxlines); |
| | + | [lines(1:end)]=deal({''}); |
| | + | ptr=Maxlines; |
| | + | lines(ptr) = {'Buttonbox output:'}; |
| | + | idxs = mod(ptr:ptr+Maxlines-1,Maxlines)+1; |
| | + | |
| | + | win = figure(); |
| | + | % initialize figure to hold output text |
| | + | edt = uicontrol('Parent',win,'Style','ListBox','HorizontalAlignment','left', ... |
| | + | 'Max',Maxlines,'BackgroundColor',[1 1 1],'Visible','on','String',lines(idxs), ... |
| | + | 'FontSize',12,'Value',Maxlines); |
| | + | pos = get(win,'Position'); |
| | + | set(edt,'Position',[1 1 pos(3) pos(4)]); |
| | + | end |
| | + | ptr = mod(ptr,Maxlines)+1; % start |
| | + | lines{ptr} = line; |
| | + | idxs = mod(ptr:ptr+Maxlines-1,Maxlines)+1; |
| | + | set(edt,'String',lines(idxs),'Value',Maxlines); |
| | + | drawnow; |
| | + | end |
| | + | |
| | + | end |
| | + | </nowiki> |