source: rtos_arduino/trunk/arduino_lib/libraries/Firmata/src/Firmata.cpp@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

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