Project

General

Profile

Statistics
| Branch: | Revision:

root / arduino-1.0 / libraries / Firmata / Firmata.cpp @ 58d82c77

History | View | Annotate | Download (12.7 KB)

1 58d82c77 Tom Mullins
/*
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