root / arduino-1.0 / libraries / Firmata / Firmata.cpp @ 58d82c77
History | View | Annotate | Download (12.7 KB)
1 |
/*
|
---|---|
2 |
Firmata.cpp - Firmata library
|
3 |
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
|
4 |
|
5 |
This library is free software; you can redistribute it and/or
|
6 |
modify it under the terms of the GNU Lesser General Public
|
7 |
License as published by the Free Software Foundation; either
|
8 |
version 2.1 of the License, or (at your option) any later version.
|
9 |
|
10 |
See file LICENSE.txt for further informations on licensing terms.
|
11 |
*/
|
12 |
|
13 |
//******************************************************************************
|
14 |
//* Includes
|
15 |
//******************************************************************************
|
16 |
|
17 |
#include "Firmata.h" |
18 |
#include "HardwareSerial.h" |
19 |
|
20 |
extern "C" { |
21 |
#include <string.h> |
22 |
#include <stdlib.h> |
23 |
} |
24 |
|
25 |
//******************************************************************************
|
26 |
//* Support Functions
|
27 |
//******************************************************************************
|
28 |
|
29 |
void FirmataClass::sendValueAsTwo7bitBytes(int value) |
30 |
{ |
31 |
FirmataSerial.write(value & B01111111); // LSB
|
32 |
FirmataSerial.write(value >> 7 & B01111111); // MSB |
33 |
} |
34 |
|
35 |
void FirmataClass::startSysex(void) |
36 |
{ |
37 |
FirmataSerial.write(START_SYSEX); |
38 |
} |
39 |
|
40 |
void FirmataClass::endSysex(void) |
41 |
{ |
42 |
FirmataSerial.write(END_SYSEX); |
43 |
} |
44 |
|
45 |
//******************************************************************************
|
46 |
//* Constructors
|
47 |
//******************************************************************************
|
48 |
|
49 |
FirmataClass::FirmataClass(Stream &s) : FirmataSerial(s) |
50 |
{ |
51 |
firmwareVersionCount = 0;
|
52 |
systemReset(); |
53 |
} |
54 |
|
55 |
//******************************************************************************
|
56 |
//* Public Methods
|
57 |
//******************************************************************************
|
58 |
|
59 |
/* begin method for overriding default serial bitrate */
|
60 |
void FirmataClass::begin(void) |
61 |
{ |
62 |
begin(57600);
|
63 |
} |
64 |
|
65 |
/* begin method for overriding default serial bitrate */
|
66 |
void FirmataClass::begin(long speed) |
67 |
{ |
68 |
Serial.begin(speed); |
69 |
FirmataSerial = Serial; |
70 |
blinkVersion(); |
71 |
printVersion(); |
72 |
printFirmwareVersion(); |
73 |
} |
74 |
|
75 |
void FirmataClass::begin(Stream &s)
|
76 |
{ |
77 |
FirmataSerial = s; |
78 |
systemReset(); |
79 |
printVersion(); |
80 |
printFirmwareVersion(); |
81 |
} |
82 |
|
83 |
// output the protocol version message to the serial port
|
84 |
void FirmataClass::printVersion(void) { |
85 |
FirmataSerial.write(REPORT_VERSION); |
86 |
FirmataSerial.write(FIRMATA_MAJOR_VERSION); |
87 |
FirmataSerial.write(FIRMATA_MINOR_VERSION); |
88 |
} |
89 |
|
90 |
void FirmataClass::blinkVersion(void) |
91 |
{ |
92 |
// flash the pin with the protocol version
|
93 |
pinMode(VERSION_BLINK_PIN,OUTPUT); |
94 |
pin13strobe(FIRMATA_MAJOR_VERSION, 40, 210); |
95 |
delay(250);
|
96 |
pin13strobe(FIRMATA_MINOR_VERSION, 40, 210); |
97 |
delay(125);
|
98 |
} |
99 |
|
100 |
void FirmataClass::printFirmwareVersion(void) |
101 |
{ |
102 |
byte i; |
103 |
|
104 |
if(firmwareVersionCount) { // make sure that the name has been set before reporting |
105 |
startSysex(); |
106 |
FirmataSerial.write(REPORT_FIRMWARE); |
107 |
FirmataSerial.write(firmwareVersionVector[0]); // major version number |
108 |
FirmataSerial.write(firmwareVersionVector[1]); // minor version number |
109 |
for(i=2; i<firmwareVersionCount; ++i) { |
110 |
sendValueAsTwo7bitBytes(firmwareVersionVector[i]); |
111 |
} |
112 |
endSysex(); |
113 |
} |
114 |
} |
115 |
|
116 |
void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte minor) |
117 |
{ |
118 |
const char *filename; |
119 |
char *extension;
|
120 |
|
121 |
// parse out ".cpp" and "applet/" that comes from using __FILE__
|
122 |
extension = strstr(name, ".cpp");
|
123 |
filename = strrchr(name, '/') + 1; //points to slash, +1 gets to start of filename |
124 |
// add two bytes for version numbers
|
125 |
if(extension && filename) {
|
126 |
firmwareVersionCount = extension - filename + 2;
|
127 |
} else {
|
128 |
firmwareVersionCount = strlen(name) + 2;
|
129 |
filename = name; |
130 |
} |
131 |
firmwareVersionVector = (byte *) malloc(firmwareVersionCount); |
132 |
firmwareVersionVector[firmwareVersionCount] = 0;
|
133 |
firmwareVersionVector[0] = major;
|
134 |
firmwareVersionVector[1] = minor;
|
135 |
strncpy((char*)firmwareVersionVector + 2, filename, firmwareVersionCount - 2); |
136 |
// alas, no snprintf on Arduino
|
137 |
// snprintf(firmwareVersionVector, MAX_DATA_BYTES, "%c%c%s",
|
138 |
// (char)major, (char)minor, firmwareVersionVector);
|
139 |
} |
140 |
|
141 |
//------------------------------------------------------------------------------
|
142 |
// Serial Receive Handling
|
143 |
|
144 |
int FirmataClass::available(void) |
145 |
{ |
146 |
return FirmataSerial.available();
|
147 |
} |
148 |
|
149 |
|
150 |
void FirmataClass::processSysexMessage(void) |
151 |
{ |
152 |
switch(storedInputData[0]) { //first byte in buffer is command |
153 |
case REPORT_FIRMWARE:
|
154 |
printFirmwareVersion(); |
155 |
break;
|
156 |
case STRING_DATA:
|
157 |
if(currentStringCallback) {
|
158 |
byte bufferLength = (sysexBytesRead - 1) / 2; |
159 |
char *buffer = (char*)malloc(bufferLength * sizeof(char)); |
160 |
byte i = 1;
|
161 |
byte j = 0;
|
162 |
while(j < bufferLength) {
|
163 |
buffer[j] = (char)storedInputData[i];
|
164 |
i++; |
165 |
buffer[j] += (char)(storedInputData[i] << 7); |
166 |
i++; |
167 |
j++; |
168 |
} |
169 |
(*currentStringCallback)(buffer); |
170 |
} |
171 |
break;
|
172 |
default:
|
173 |
if(currentSysexCallback)
|
174 |
(*currentSysexCallback)(storedInputData[0], sysexBytesRead - 1, storedInputData + 1); |
175 |
} |
176 |
} |
177 |
|
178 |
void FirmataClass::processInput(void) |
179 |
{ |
180 |
int inputData = FirmataSerial.read(); // this is 'int' to handle -1 when no data |
181 |
int command;
|
182 |
|
183 |
// TODO make sure it handles -1 properly
|
184 |
|
185 |
if (parsingSysex) {
|
186 |
if(inputData == END_SYSEX) {
|
187 |
//stop sysex byte
|
188 |
parsingSysex = false;
|
189 |
//fire off handler function
|
190 |
processSysexMessage(); |
191 |
} else {
|
192 |
//normal data byte - add to buffer
|
193 |
storedInputData[sysexBytesRead] = inputData; |
194 |
sysexBytesRead++; |
195 |
} |
196 |
} else if( (waitForData > 0) && (inputData < 128) ) { |
197 |
waitForData--; |
198 |
storedInputData[waitForData] = inputData; |
199 |
if( (waitForData==0) && executeMultiByteCommand ) { // got the whole message |
200 |
switch(executeMultiByteCommand) {
|
201 |
case ANALOG_MESSAGE:
|
202 |
if(currentAnalogCallback) {
|
203 |
(*currentAnalogCallback)(multiByteChannel, |
204 |
(storedInputData[0] << 7) |
205 |
+ storedInputData[1]);
|
206 |
} |
207 |
break;
|
208 |
case DIGITAL_MESSAGE:
|
209 |
if(currentDigitalCallback) {
|
210 |
(*currentDigitalCallback)(multiByteChannel, |
211 |
(storedInputData[0] << 7) |
212 |
+ storedInputData[1]);
|
213 |
} |
214 |
break;
|
215 |
case SET_PIN_MODE:
|
216 |
if(currentPinModeCallback)
|
217 |
(*currentPinModeCallback)(storedInputData[1], storedInputData[0]); |
218 |
break;
|
219 |
case REPORT_ANALOG:
|
220 |
if(currentReportAnalogCallback)
|
221 |
(*currentReportAnalogCallback)(multiByteChannel,storedInputData[0]);
|
222 |
break;
|
223 |
case REPORT_DIGITAL:
|
224 |
if(currentReportDigitalCallback)
|
225 |
(*currentReportDigitalCallback)(multiByteChannel,storedInputData[0]);
|
226 |
break;
|
227 |
} |
228 |
executeMultiByteCommand = 0;
|
229 |
} |
230 |
} else {
|
231 |
// remove channel info from command byte if less than 0xF0
|
232 |
if(inputData < 0xF0) { |
233 |
command = inputData & 0xF0;
|
234 |
multiByteChannel = inputData & 0x0F;
|
235 |
} else {
|
236 |
command = inputData; |
237 |
// commands in the 0xF* range don't use channel data
|
238 |
} |
239 |
switch (command) {
|
240 |
case ANALOG_MESSAGE:
|
241 |
case DIGITAL_MESSAGE:
|
242 |
case SET_PIN_MODE:
|
243 |
waitForData = 2; // two data bytes needed |
244 |
executeMultiByteCommand = command; |
245 |
break;
|
246 |
case REPORT_ANALOG:
|
247 |
case REPORT_DIGITAL:
|
248 |
waitForData = 1; // two data bytes needed |
249 |
executeMultiByteCommand = command; |
250 |
break;
|
251 |
case START_SYSEX:
|
252 |
parsingSysex = true;
|
253 |
sysexBytesRead = 0;
|
254 |
break;
|
255 |
case SYSTEM_RESET:
|
256 |
systemReset(); |
257 |
break;
|
258 |
case REPORT_VERSION:
|
259 |
Firmata.printVersion(); |
260 |
break;
|
261 |
} |
262 |
} |
263 |
} |
264 |
|
265 |
//------------------------------------------------------------------------------
|
266 |
// Serial Send Handling
|
267 |
|
268 |
// send an analog message
|
269 |
void FirmataClass::sendAnalog(byte pin, int value) |
270 |
{ |
271 |
// pin can only be 0-15, so chop higher bits
|
272 |
FirmataSerial.write(ANALOG_MESSAGE | (pin & 0xF));
|
273 |
sendValueAsTwo7bitBytes(value); |
274 |
} |
275 |
|
276 |
// send a single digital pin in a digital message
|
277 |
void FirmataClass::sendDigital(byte pin, int value) |
278 |
{ |
279 |
/* TODO add single pin digital messages to the protocol, this needs to
|
280 |
* track the last digital data sent so that it can be sure to change just
|
281 |
* one bit in the packet. This is complicated by the fact that the
|
282 |
* numbering of the pins will probably differ on Arduino, Wiring, and
|
283 |
* other boards. The DIGITAL_MESSAGE sends 14 bits at a time, but it is
|
284 |
* probably easier to send 8 bit ports for any board with more than 14
|
285 |
* digital pins.
|
286 |
*/
|
287 |
|
288 |
// TODO: the digital message should not be sent on the serial port every
|
289 |
// time sendDigital() is called. Instead, it should add it to an int
|
290 |
// which will be sent on a schedule. If a pin changes more than once
|
291 |
// before the digital message is sent on the serial port, it should send a
|
292 |
// digital message for each change.
|
293 |
|
294 |
// if(value == 0)
|
295 |
// sendDigitalPortPair();
|
296 |
} |
297 |
|
298 |
|
299 |
// send 14-bits in a single digital message (protocol v1)
|
300 |
// send an 8-bit port in a single digital message (protocol v2)
|
301 |
void FirmataClass::sendDigitalPort(byte portNumber, int portData) |
302 |
{ |
303 |
FirmataSerial.write(DIGITAL_MESSAGE | (portNumber & 0xF));
|
304 |
FirmataSerial.write((byte)portData % 128); // Tx bits 0-6 |
305 |
FirmataSerial.write(portData >> 7); // Tx bits 7-13 |
306 |
} |
307 |
|
308 |
|
309 |
void FirmataClass::sendSysex(byte command, byte bytec, byte* bytev)
|
310 |
{ |
311 |
byte i; |
312 |
startSysex(); |
313 |
FirmataSerial.write(command); |
314 |
for(i=0; i<bytec; i++) { |
315 |
sendValueAsTwo7bitBytes(bytev[i]); |
316 |
} |
317 |
endSysex(); |
318 |
} |
319 |
|
320 |
void FirmataClass::sendString(byte command, const char* string) |
321 |
{ |
322 |
sendSysex(command, strlen(string), (byte *)string); |
323 |
} |
324 |
|
325 |
|
326 |
// send a string as the protocol string type
|
327 |
void FirmataClass::sendString(const char* string) |
328 |
{ |
329 |
sendString(STRING_DATA, string);
|
330 |
} |
331 |
|
332 |
|
333 |
// Internal Actions/////////////////////////////////////////////////////////////
|
334 |
|
335 |
// generic callbacks
|
336 |
void FirmataClass::attach(byte command, callbackFunction newFunction)
|
337 |
{ |
338 |
switch(command) {
|
339 |
case ANALOG_MESSAGE: currentAnalogCallback = newFunction; break; |
340 |
case DIGITAL_MESSAGE: currentDigitalCallback = newFunction; break; |
341 |
case REPORT_ANALOG: currentReportAnalogCallback = newFunction; break; |
342 |
case REPORT_DIGITAL: currentReportDigitalCallback = newFunction; break; |
343 |
case SET_PIN_MODE: currentPinModeCallback = newFunction; break; |
344 |
} |
345 |
} |
346 |
|
347 |
void FirmataClass::attach(byte command, systemResetCallbackFunction newFunction)
|
348 |
{ |
349 |
switch(command) {
|
350 |
case SYSTEM_RESET: currentSystemResetCallback = newFunction; break; |
351 |
} |
352 |
} |
353 |
|
354 |
void FirmataClass::attach(byte command, stringCallbackFunction newFunction)
|
355 |
{ |
356 |
switch(command) {
|
357 |
case STRING_DATA: currentStringCallback = newFunction; break; |
358 |
} |
359 |
} |
360 |
|
361 |
void FirmataClass::attach(byte command, sysexCallbackFunction newFunction)
|
362 |
{ |
363 |
currentSysexCallback = newFunction; |
364 |
} |
365 |
|
366 |
void FirmataClass::detach(byte command)
|
367 |
{ |
368 |
switch(command) {
|
369 |
case SYSTEM_RESET: currentSystemResetCallback = NULL; break; |
370 |
case STRING_DATA: currentStringCallback = NULL; break; |
371 |
case START_SYSEX: currentSysexCallback = NULL; break; |
372 |
default:
|
373 |
attach(command, (callbackFunction)NULL);
|
374 |
} |
375 |
} |
376 |
|
377 |
// sysex callbacks
|
378 |
/*
|
379 |
* this is too complicated for analogReceive, but maybe for Sysex?
|
380 |
void FirmataClass::attachSysex(sysexFunction newFunction)
|
381 |
{
|
382 |
byte i;
|
383 |
byte tmpCount = analogReceiveFunctionCount;
|
384 |
analogReceiveFunction* tmpArray = analogReceiveFunctionArray;
|
385 |
analogReceiveFunctionCount++;
|
386 |
analogReceiveFunctionArray = (analogReceiveFunction*) calloc(analogReceiveFunctionCount, sizeof(analogReceiveFunction));
|
387 |
for(i = 0; i < tmpCount; i++) {
|
388 |
analogReceiveFunctionArray[i] = tmpArray[i];
|
389 |
}
|
390 |
analogReceiveFunctionArray[tmpCount] = newFunction;
|
391 |
free(tmpArray);
|
392 |
}
|
393 |
*/
|
394 |
|
395 |
//******************************************************************************
|
396 |
//* Private Methods
|
397 |
//******************************************************************************
|
398 |
|
399 |
|
400 |
|
401 |
// resets the system state upon a SYSTEM_RESET message from the host software
|
402 |
void FirmataClass::systemReset(void) |
403 |
{ |
404 |
byte i; |
405 |
|
406 |
waitForData = 0; // this flag says the next serial input will be data |
407 |
executeMultiByteCommand = 0; // execute this after getting multi-byte data |
408 |
multiByteChannel = 0; // channel data for multiByteCommands |
409 |
|
410 |
|
411 |
for(i=0; i<MAX_DATA_BYTES; i++) { |
412 |
storedInputData[i] = 0;
|
413 |
} |
414 |
|
415 |
parsingSysex = false;
|
416 |
sysexBytesRead = 0;
|
417 |
|
418 |
if(currentSystemResetCallback)
|
419 |
(*currentSystemResetCallback)(); |
420 |
|
421 |
//flush(); //TODO uncomment when Firmata is a subclass of HardwareSerial
|
422 |
} |
423 |
|
424 |
|
425 |
|
426 |
// =============================================================================
|
427 |
// used for flashing the pin for the version number
|
428 |
void FirmataClass::pin13strobe(int count, int onInterval, int offInterval) |
429 |
{ |
430 |
byte i; |
431 |
pinMode(VERSION_BLINK_PIN, OUTPUT); |
432 |
for(i=0; i<count; i++) { |
433 |
delay(offInterval); |
434 |
digitalWrite(VERSION_BLINK_PIN, HIGH); |
435 |
delay(onInterval); |
436 |
digitalWrite(VERSION_BLINK_PIN, LOW); |
437 |
} |
438 |
} |
439 |
|
440 |
|
441 |
// make one instance for the user to use
|
442 |
FirmataClass Firmata(Serial); |
443 |
|
444 |
|