@@ -23,6 +23,20 @@ extern "C" {
23
23
#include < stdlib.h>
24
24
}
25
25
26
+ // ******************************************************************************
27
+ // * Static Members
28
+ // ******************************************************************************
29
+ // make one instance for the user to use
30
+ FirmataClass Firmata;
31
+
32
+ void printVersion (void ) {
33
+ Firmata.printVersion ();
34
+ }
35
+
36
+ void printFirmwareVersion (void ) {
37
+ Firmata.printFirmwareVersion ();
38
+ }
39
+
26
40
// ******************************************************************************
27
41
// * Support Functions
28
42
// ******************************************************************************
@@ -66,7 +80,8 @@ FirmataClass::FirmataClass()
66
80
firmwareVersionCount = 0 ;
67
81
firmwareVersionVector = 0 ;
68
82
blinkVersionDisabled = false ;
69
- systemReset ();
83
+ parser.attach (REPORT_FIRMWARE, ::printFirmwareVersion);
84
+ parser.attach (REPORT_VERSION, ::printVersion);
70
85
}
71
86
72
87
// ******************************************************************************
@@ -228,54 +243,14 @@ int FirmataClass::available(void)
228
243
return FirmataStream->available ();
229
244
}
230
245
231
- /* *
232
- * Process incoming sysex messages. Handles REPORT_FIRMWARE and STRING_DATA internally.
233
- * Calls callback function for STRING_DATA and all other sysex messages.
234
- * @private
235
- */
236
- void FirmataClass::processSysexMessage (void )
237
- {
238
- switch (storedInputData[0 ]) { // first byte in buffer is command
239
- case REPORT_FIRMWARE:
240
- printFirmwareVersion ();
241
- break ;
242
- case STRING_DATA:
243
- if (currentStringCallback) {
244
- byte bufferLength = (sysexBytesRead - 1 ) / 2 ;
245
- byte i = 1 ;
246
- byte j = 0 ;
247
- while (j < bufferLength) {
248
- // The string length will only be at most half the size of the
249
- // stored input buffer so we can decode the string within the buffer.
250
- storedInputData[j] = storedInputData[i];
251
- i++;
252
- storedInputData[j] += (storedInputData[i] << 7 );
253
- i++;
254
- j++;
255
- }
256
- // Make sure string is null terminated. This may be the case for data
257
- // coming from client libraries in languages that don't null terminate
258
- // strings.
259
- if (storedInputData[j - 1 ] != ' \0 ' ) {
260
- storedInputData[j] = ' \0 ' ;
261
- }
262
- (*currentStringCallback)((char *)&storedInputData[0 ]);
263
- }
264
- break ;
265
- default :
266
- if (currentSysexCallback)
267
- (*currentSysexCallback)(storedInputData[0 ], sysexBytesRead - 1 , storedInputData + 1 );
268
- }
269
- }
270
-
271
246
/* *
272
247
* Read a single int from the input stream. If the value is not = -1, pass it on to parse(byte)
273
248
*/
274
249
void FirmataClass::processInput (void )
275
250
{
276
251
int inputData = FirmataStream->read (); // this is 'int' to handle -1 when no data
277
252
if (inputData != -1 ) {
278
- parse (inputData);
253
+ parser. parse (inputData);
279
254
}
280
255
}
281
256
@@ -285,99 +260,15 @@ void FirmataClass::processInput(void)
285
260
*/
286
261
void FirmataClass::parse (byte inputData)
287
262
{
288
- int command;
289
-
290
- if (parsingSysex) {
291
- if (inputData == END_SYSEX) {
292
- // stop sysex byte
293
- parsingSysex = false ;
294
- // fire off handler function
295
- processSysexMessage ();
296
- } else {
297
- // normal data byte - add to buffer
298
- storedInputData[sysexBytesRead] = inputData;
299
- sysexBytesRead++;
300
- }
301
- } else if ( (waitForData > 0 ) && (inputData < 128 ) ) {
302
- waitForData--;
303
- storedInputData[waitForData] = inputData;
304
- if ( (waitForData == 0 ) && executeMultiByteCommand ) { // got the whole message
305
- switch (executeMultiByteCommand) {
306
- case ANALOG_MESSAGE:
307
- if (currentAnalogCallback) {
308
- (*currentAnalogCallback)(multiByteChannel,
309
- (storedInputData[0 ] << 7 )
310
- + storedInputData[1 ]);
311
- }
312
- break ;
313
- case DIGITAL_MESSAGE:
314
- if (currentDigitalCallback) {
315
- (*currentDigitalCallback)(multiByteChannel,
316
- (storedInputData[0 ] << 7 )
317
- + storedInputData[1 ]);
318
- }
319
- break ;
320
- case SET_PIN_MODE:
321
- if (currentPinModeCallback)
322
- (*currentPinModeCallback)(storedInputData[1 ], storedInputData[0 ]);
323
- break ;
324
- case SET_DIGITAL_PIN_VALUE:
325
- if (currentPinValueCallback)
326
- (*currentPinValueCallback)(storedInputData[1 ], storedInputData[0 ]);
327
- break ;
328
- case REPORT_ANALOG:
329
- if (currentReportAnalogCallback)
330
- (*currentReportAnalogCallback)(multiByteChannel, storedInputData[0 ]);
331
- break ;
332
- case REPORT_DIGITAL:
333
- if (currentReportDigitalCallback)
334
- (*currentReportDigitalCallback)(multiByteChannel, storedInputData[0 ]);
335
- break ;
336
- }
337
- executeMultiByteCommand = 0 ;
338
- }
339
- } else {
340
- // remove channel info from command byte if less than 0xF0
341
- if (inputData < 0xF0 ) {
342
- command = inputData & 0xF0 ;
343
- multiByteChannel = inputData & 0x0F ;
344
- } else {
345
- command = inputData;
346
- // commands in the 0xF* range don't use channel data
347
- }
348
- switch (command) {
349
- case ANALOG_MESSAGE:
350
- case DIGITAL_MESSAGE:
351
- case SET_PIN_MODE:
352
- case SET_DIGITAL_PIN_VALUE:
353
- waitForData = 2 ; // two data bytes needed
354
- executeMultiByteCommand = command;
355
- break ;
356
- case REPORT_ANALOG:
357
- case REPORT_DIGITAL:
358
- waitForData = 1 ; // one data byte needed
359
- executeMultiByteCommand = command;
360
- break ;
361
- case START_SYSEX:
362
- parsingSysex = true ;
363
- sysexBytesRead = 0 ;
364
- break ;
365
- case SYSTEM_RESET:
366
- systemReset ();
367
- break ;
368
- case REPORT_VERSION:
369
- Firmata.printVersion ();
370
- break ;
371
- }
372
- }
263
+ parser.parse (inputData);
373
264
}
374
265
375
266
/* *
376
267
* @return Returns true if the parser is actively parsing data.
377
268
*/
378
269
boolean FirmataClass::isParsingMessage (void )
379
270
{
380
- return (waitForData > 0 || parsingSysex );
271
+ return parser. isParsingMessage ( );
381
272
}
382
273
383
274
// ------------------------------------------------------------------------------
@@ -495,66 +386,49 @@ void FirmataClass::write(byte c)
495
386
* @param command The ID of the command to attach a callback function to.
496
387
* @param newFunction A reference to the callback function to attach.
497
388
*/
498
- void FirmataClass::attach (byte command, callbackFunction newFunction)
389
+ void FirmataClass::attach (uint8_t command, callbackFunction newFunction)
499
390
{
500
- switch (command) {
501
- case ANALOG_MESSAGE: currentAnalogCallback = newFunction; break ;
502
- case DIGITAL_MESSAGE: currentDigitalCallback = newFunction; break ;
503
- case REPORT_ANALOG: currentReportAnalogCallback = newFunction; break ;
504
- case REPORT_DIGITAL: currentReportDigitalCallback = newFunction; break ;
505
- case SET_PIN_MODE: currentPinModeCallback = newFunction; break ;
506
- case SET_DIGITAL_PIN_VALUE: currentPinValueCallback = newFunction; break ;
507
- }
391
+ parser.attach (command, (callbackFunction)newFunction);
508
392
}
509
393
510
394
/* *
511
395
* Attach a callback function for the SYSTEM_RESET command.
512
396
* @param command Must be set to SYSTEM_RESET or it will be ignored.
513
397
* @param newFunction A reference to the system reset callback function to attach.
514
398
*/
515
- void FirmataClass::attach (byte command, systemResetCallbackFunction newFunction)
399
+ void FirmataClass::attach (uint8_t command, systemCallbackFunction newFunction)
516
400
{
517
- switch (command) {
518
- case SYSTEM_RESET: currentSystemResetCallback = newFunction; break ;
519
- }
401
+ parser.attach (command, (systemCallbackFunction)newFunction);
520
402
}
521
403
522
404
/* *
523
405
* Attach a callback function for the STRING_DATA command.
524
406
* @param command Must be set to STRING_DATA or it will be ignored.
525
407
* @param newFunction A reference to the string callback function to attach.
526
408
*/
527
- void FirmataClass::attach (byte command, stringCallbackFunction newFunction)
409
+ void FirmataClass::attach (uint8_t command, stringCallbackFunction newFunction)
528
410
{
529
- switch (command) {
530
- case STRING_DATA: currentStringCallback = newFunction; break ;
531
- }
411
+ parser.attach (command, (stringCallbackFunction)newFunction);
532
412
}
533
413
534
414
/* *
535
415
* Attach a generic sysex callback function to sysex command.
536
416
* @param command The ID of the command to attach a callback function to.
537
417
* @param newFunction A reference to the sysex callback function to attach.
538
418
*/
539
- void FirmataClass::attach (byte command, sysexCallbackFunction newFunction)
419
+ void FirmataClass::attach (uint8_t command, sysexCallbackFunction newFunction)
540
420
{
541
- currentSysexCallback = newFunction;
421
+ parser. attach (command, (sysexCallbackFunction) newFunction) ;
542
422
}
543
423
544
424
/* *
545
425
* Detach a callback function for a specified command (such as SYSTEM_RESET, STRING_DATA,
546
426
* ANALOG_MESSAGE, DIGITAL_MESSAGE, etc).
547
427
* @param command The ID of the command to detatch the callback function from.
548
428
*/
549
- void FirmataClass::detach (byte command)
429
+ void FirmataClass::detach (uint8_t command)
550
430
{
551
- switch (command) {
552
- case SYSTEM_RESET: currentSystemResetCallback = NULL ; break ;
553
- case STRING_DATA: currentStringCallback = NULL ; break ;
554
- case START_SYSEX: currentSysexCallback = NULL ; break ;
555
- default :
556
- attach (command, (callbackFunction)NULL );
557
- }
431
+ parser.detach (command);
558
432
}
559
433
560
434
/* *
@@ -623,29 +497,6 @@ void FirmataClass::setPinState(byte pin, int state)
623
497
// * Private Methods
624
498
// ******************************************************************************
625
499
626
- /* *
627
- * Resets the system state upon a SYSTEM_RESET message from the host software.
628
- * @private
629
- */
630
- void FirmataClass::systemReset (void )
631
- {
632
- byte i;
633
-
634
- waitForData = 0 ; // this flag says the next serial input will be data
635
- executeMultiByteCommand = 0 ; // execute this after getting multi-byte data
636
- multiByteChannel = 0 ; // channel data for multiByteCommands
637
-
638
- for (i = 0 ; i < MAX_DATA_BYTES; i++) {
639
- storedInputData[i] = 0 ;
640
- }
641
-
642
- parsingSysex = false ;
643
- sysexBytesRead = 0 ;
644
-
645
- if (currentSystemResetCallback)
646
- (*currentSystemResetCallback)();
647
- }
648
-
649
500
/* *
650
501
* Flashing the pin for the version number
651
502
* @private
@@ -665,5 +516,3 @@ void FirmataClass::strobeBlinkPin(byte pin, int count, int onInterval, int offIn
665
516
}
666
517
}
667
518
668
- // make one instance for the user to use
669
- FirmataClass Firmata;
0 commit comments