-
Notifications
You must be signed in to change notification settings - Fork 1
/
Bitsi.m
258 lines (218 loc) · 8.22 KB
/
Bitsi.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
%
% %Constructor%
%
% Bitsi(comport)
%
% When creating a new 'bitsi' object, you can specify to which comport it
% is connected. On windows computers, this is usually something like
% 'com1'.
% When using an empty string for 'comport', the object will run in testing
% mode. In this case it's not required to have the BITSI physically
% connected to the computer. Responses will be read from the keyboard.
%
% *Methods*
% - sendTrigger(code)
% - getResponse(timeout, return_after_response)
% - clearResponses()
% - numberOfResponses()
% - close()
%
%
%
% *sendTrigger(code)*
% code - trigger code, allowed codes 1 - 255. This code is sent to the
% BITSI which will output it on it's parallel output port. The code will be
% reset after 10 miliseconds.
%
% * [response time] = getResponse(timeout, return_after_response)*
%
% This function will take maximally 'timeout' seconds to execute
% return_after_response - allowed values: true or false
%
% False:
% If return_after_response equals false, getResponse will wait for a fixed
% duration (timeout) and record the first response during the wait. The
% first response and it's timeout will be returned after the specified
% timeout.
%
% < timeout >
% +-----------------+
% | A |
% --+ | +----------------
%
%
%
% True:
% This method will return as soon as there is a response. Both
% the response and the timestamp of the response will be returned.
% If 'timeout' seconds have been expired without a response, a response
% of 0 will be returned.
%
% < timeout >
% +-----------+
% | A|
% --+ |+----------------
%
%
%
% *Example*
%
% b = Bitsi('com1');
%
% b.sendTrigger(20);
%
% ... do more stuff here
%
% [r t] = b.getResponse(10, false);
%
% b.close();
%
%
% If the constructor is called with an empty com port string, no serial connection will be
% established. The serial commands will be echo'd to stdout:
%
% b = Bitsi('')
% ...
%
%
classdef Bitsi
properties (SetAccess = public)
serobj;
debugmode = false;
end
methods
function B = Bitsi(comport)
if (strcmp(comport, ''))
fprintf('Bitsi: No Com port given, running in testing mode...\n')
B.debugmode = true;
KbName('UnifyKeyNames');
end
if (not(B.debugmode))
%delete(instrfind);
B.serobj = serial(comport);
% serial port configuration
set(B.serobj, 'Baudrate', 115200);
set(B.serobj, 'Parity', 'none');
set(B.serobj, 'Databits', 8); % number of data bits
set(B.serobj, 'StopBits', 1); % number of stop bits
%set(B.serobj, 'Terminator', 'CR/LF'); % line ending character
% see also:
% http://www.mathworks.com/matlabcentral/newsreader/view_original/292759
%set(B.serobj, 'InputBufferSize', 1); % set read buffBuffer for read
set(B.serobj, 'FlowControl', 'none'); %
% open the serial port
fopen(B.serobj);
% since matlab pulls the DTR line, the arduino will reset
% so we have to wait for the initialization of the controller
oldState = pause('query');
pause on;
pause(2.5);
pause(oldState);
% read all bytes available at the serial port
status = '[nothing]';
if B.serobj.BytesAvailable > 0
status = fread(B.serobj, B.serobj.BytesAvailable);
end
fprintf('Bitsi says: %s', char(status));
fprintf('\n');
end
end
function sendTrigger(B,code)
% checking code range
if code > 255
fprintf('Bitsi: Error, code should not exeed 255\n');
return;
end
if code < 1
fprintf('Bitsi: Error, code should be bigger than 0\n');
return;
end
% fprintf('Bitsi: trigger code %f\n', code);
if ~B.debugmode
fwrite(B.serobj, code)
end
end
function x = numberOfResponses(B)
if (~B.debugmode)
x = B.serobj.BytesAvailable;
else
x = 0; % assume that in debugging no more responses left
end
end
function clearResponses(B)
if (~B.debugmode)
numberOfBytes = B.serobj.BytesAvailable;
if numberOfBytes > 0
fread(B.serobj, numberOfBytes);
end
end
end
function [response, timestamp]= getResponse(B,wait_time, return_after_response)
response = 0;
% start stopwatch
timeout = GetSecs + wait_time;
if (B.debugmode)
while GetSecs < timeout && ( ~return_after_response || response ==0)
% poll the state of the keyboard
[keyisdown, when, keyCode] = KbCheck;
% if there wasn't a response before and there is a
% keyboard press available
if response == 0 && keyisdown
timestamp = when;
response = find(keyCode);
% make sure to return just one keyCode
% but first dump it to console
if length(response) > 1
fprintf('Bitsi::getResponse() - More than one button pressed: ');
disp(response);
response = response(1);
end
%% DELETED TO WAIT FOR KEY RELEASE BY IH
%KbWait([],1); % wait explicitly for key to be released
%%
%added by Diego Lozano 26-May-2012 09:50:45
B.sendTrigger(response);
if return_after_response
break;
end
end
WaitSecs(0.001); % to avoid overloading system
end
% if no response yet after timeout
if (response == 0)
timestamp = GetSecs;
end
else % listening to actual Bitsi-box
% depending on 'return_after_response' this loop will run
% for timeout seconds or until a response is given
while GetSecs < timeout && ( ~return_after_response || response == 0)
% if there wasn't a response before and there is a
% serial character available
if response == 0 && B.serobj.BytesAvailable > 0
% capture the time and the response
timestamp = GetSecs;
response = fread(B.serobj, 1);
%added by Diego Lozano 26-May-2012 09:50:45
B.sendTrigger(response);
fprintf('Bitsi: response code %i\n', response);
end
end
% if no response yet after timeout
if (response == 0)
timestamp = GetSecs;
end
% In some other versions of Bitsi.m there is a
% clearResponses call here, I think this can get you into
% trouble in certain cases. Just make sure you call
% clearResponses yourself when needed.
end
end
% close
function close(B)
if (not(B.debugmode))
fclose(B.serobj);
delete(B.serobj);
end
end
end % methods
end % classdef