@@ -23,6 +23,20 @@ extern "C" {
2323#include < stdlib.h>
2424}
2525
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+
2640// ******************************************************************************
2741// * Support Functions
2842// ******************************************************************************
@@ -66,7 +80,8 @@ FirmataClass::FirmataClass()
6680 firmwareVersionCount = 0 ;
6781 firmwareVersionVector = 0 ;
6882 blinkVersionDisabled = false ;
69- systemReset ();
83+ parser.attach (REPORT_FIRMWARE, ::printFirmwareVersion);
84+ parser.attach (REPORT_VERSION, ::printVersion);
7085}
7186
7287// ******************************************************************************
@@ -228,54 +243,14 @@ int FirmataClass::available(void)
228243 return FirmataStream->available ();
229244}
230245
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-
271246/* *
272247 * Read a single int from the input stream. If the value is not = -1, pass it on to parse(byte)
273248 */
274249void FirmataClass::processInput (void )
275250{
276251 int inputData = FirmataStream->read (); // this is 'int' to handle -1 when no data
277252 if (inputData != -1 ) {
278- parse (inputData);
253+ parser. parse (inputData);
279254 }
280255}
281256
@@ -285,99 +260,15 @@ void FirmataClass::processInput(void)
285260 */
286261void FirmataClass::parse (byte inputData)
287262{
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);
373264}
374265
375266/* *
376267 * @return Returns true if the parser is actively parsing data.
377268 */
378269boolean FirmataClass::isParsingMessage (void )
379270{
380- return (waitForData > 0 || parsingSysex );
271+ return parser. isParsingMessage ( );
381272}
382273
383274// ------------------------------------------------------------------------------
@@ -495,66 +386,49 @@ void FirmataClass::write(byte c)
495386 * @param command The ID of the command to attach a callback function to.
496387 * @param newFunction A reference to the callback function to attach.
497388 */
498- void FirmataClass::attach (byte command, callbackFunction newFunction)
389+ void FirmataClass::attach (uint8_t command, callbackFunction newFunction)
499390{
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);
508392}
509393
510394/* *
511395 * Attach a callback function for the SYSTEM_RESET command.
512396 * @param command Must be set to SYSTEM_RESET or it will be ignored.
513397 * @param newFunction A reference to the system reset callback function to attach.
514398 */
515- void FirmataClass::attach (byte command, systemResetCallbackFunction newFunction)
399+ void FirmataClass::attach (uint8_t command, systemCallbackFunction newFunction)
516400{
517- switch (command) {
518- case SYSTEM_RESET: currentSystemResetCallback = newFunction; break ;
519- }
401+ parser.attach (command, (systemCallbackFunction)newFunction);
520402}
521403
522404/* *
523405 * Attach a callback function for the STRING_DATA command.
524406 * @param command Must be set to STRING_DATA or it will be ignored.
525407 * @param newFunction A reference to the string callback function to attach.
526408 */
527- void FirmataClass::attach (byte command, stringCallbackFunction newFunction)
409+ void FirmataClass::attach (uint8_t command, stringCallbackFunction newFunction)
528410{
529- switch (command) {
530- case STRING_DATA: currentStringCallback = newFunction; break ;
531- }
411+ parser.attach (command, (stringCallbackFunction)newFunction);
532412}
533413
534414/* *
535415 * Attach a generic sysex callback function to sysex command.
536416 * @param command The ID of the command to attach a callback function to.
537417 * @param newFunction A reference to the sysex callback function to attach.
538418 */
539- void FirmataClass::attach (byte command, sysexCallbackFunction newFunction)
419+ void FirmataClass::attach (uint8_t command, sysexCallbackFunction newFunction)
540420{
541- currentSysexCallback = newFunction;
421+ parser. attach (command, (sysexCallbackFunction) newFunction) ;
542422}
543423
544424/* *
545425 * Detach a callback function for a specified command (such as SYSTEM_RESET, STRING_DATA,
546426 * ANALOG_MESSAGE, DIGITAL_MESSAGE, etc).
547427 * @param command The ID of the command to detatch the callback function from.
548428 */
549- void FirmataClass::detach (byte command)
429+ void FirmataClass::detach (uint8_t command)
550430{
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);
558432}
559433
560434/* *
@@ -623,29 +497,6 @@ void FirmataClass::setPinState(byte pin, int state)
623497// * Private Methods
624498// ******************************************************************************
625499
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-
649500/* *
650501 * Flashing the pin for the version number
651502 * @private
@@ -665,5 +516,3 @@ void FirmataClass::strobeBlinkPin(byte pin, int count, int onInterval, int offIn
665516 }
666517}
667518
668- // make one instance for the user to use
669- FirmataClass Firmata;
0 commit comments