Skip to content

Commit 4a5dbba

Browse files
Merge pull request #268 from firmata/serial-feature-class
Serial feature class
2 parents 3d27326 + f5baf14 commit 4a5dbba

File tree

13 files changed

+1527
-773
lines changed

13 files changed

+1527
-773
lines changed

Firmata.cpp

Lines changed: 216 additions & 24 deletions
Large diffs are not rendered by default.

Firmata.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ class FirmataClass
142142
/* serial receive handling */
143143
int available(void);
144144
void processInput(void);
145+
void parse(unsigned char value);
146+
boolean isParsingMessage(void);
145147
/* serial send handling */
146148
void sendAnalog(byte pin, int value);
147149
void sendDigital(byte pin, int value); // TODO implement this
@@ -157,6 +159,13 @@ class FirmataClass
157159
void attach(byte command, sysexCallbackFunction newFunction);
158160
void detach(byte command);
159161

162+
/* access pin state and config */
163+
byte getPinMode(byte pin);
164+
void setPinMode(byte pin, byte config);
165+
/* access pin state */
166+
int getPinState(byte pin);
167+
void setPinState(byte pin, int state);
168+
160169
/* utility methods */
161170
void sendValueAsTwo7bitBytes(int value);
162171
void startSysex(void);
@@ -175,6 +184,10 @@ class FirmataClass
175184
/* sysex */
176185
boolean parsingSysex;
177186
int sysexBytesRead;
187+
/* pin configuration */
188+
byte pinConfig[TOTAL_PINS];
189+
int pinState[TOTAL_PINS];
190+
178191
/* callback functions */
179192
callbackFunction currentAnalogCallback;
180193
callbackFunction currentDigitalCallback;

examples/StandardFirmata/StandardFirmata.ino

Lines changed: 56 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
1212
Copyright (C) 2010-2011 Paul Stoffregen. All rights reserved.
1313
Copyright (C) 2009 Shigeru Kobayashi. All rights reserved.
14-
Copyright (C) 2009-2015 Jeff Hoefs. All rights reserved.
14+
Copyright (C) 2009-2016 Jeff Hoefs. All rights reserved.
1515
1616
This library is free software; you can redistribute it and/or
1717
modify it under the terms of the GNU Lesser General Public
@@ -20,7 +20,7 @@
2020
2121
See file LICENSE.txt for further informations on licensing terms.
2222
23-
Last updated by Jeff Hoefs: December 26th, 2015
23+
Last updated by Jeff Hoefs: January 10th, 2016
2424
*/
2525

2626
#include <Servo.h>
@@ -47,6 +47,10 @@
4747
* GLOBAL VARIABLES
4848
*============================================================================*/
4949

50+
#ifdef FIRMATA_SERIAL_FEATURE
51+
SerialFirmata serialFeature;
52+
#endif
53+
5054
/* analog inputs */
5155
int analogInputsToReport = 0; // bitwise array to store pin reporting
5256

@@ -55,9 +59,7 @@ byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
5559
byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
5660

5761
/* pins configuration */
58-
byte pinConfig[TOTAL_PINS]; // configuration of every pin
5962
byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
60-
int pinState[TOTAL_PINS]; // any value that has been written
6163

6264
/* timer variables */
6365
unsigned long currentMillis; // store the current value from millis()
@@ -89,6 +91,7 @@ byte servoCount = 0;
8991

9092
boolean isResetting = false;
9193

94+
9295
/* utility functions */
9396
void wireWrite(byte data)
9497
{
@@ -230,10 +233,10 @@ void checkDigitalInputs(void)
230233
*/
231234
void setPinModeCallback(byte pin, int mode)
232235
{
233-
if (pinConfig[pin] == PIN_MODE_IGNORE)
236+
if (Firmata.getPinMode(pin) == PIN_MODE_IGNORE)
234237
return;
235238

236-
if (pinConfig[pin] == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
239+
if (Firmata.getPinMode(pin) == PIN_MODE_I2C && isI2CEnabled && mode != PIN_MODE_I2C) {
237240
// disable i2c so pins can be used for other functions
238241
// the following if statements should reconfigure the pins properly
239242
disableI2CPins();
@@ -253,7 +256,7 @@ void setPinModeCallback(byte pin, int mode)
253256
portConfigInputs[pin / 8] &= ~(1 << (pin & 7));
254257
}
255258
}
256-
pinState[pin] = 0;
259+
Firmata.setPinState(pin, 0);
257260
switch (mode) {
258261
case PIN_MODE_ANALOG:
259262
if (IS_PIN_ANALOG(pin)) {
@@ -264,7 +267,7 @@ void setPinModeCallback(byte pin, int mode)
264267
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
265268
#endif
266269
}
267-
pinConfig[pin] = PIN_MODE_ANALOG;
270+
Firmata.setPinMode(pin, PIN_MODE_ANALOG);
268271
}
269272
break;
270273
case INPUT:
@@ -274,33 +277,33 @@ void setPinModeCallback(byte pin, int mode)
274277
// deprecated since Arduino 1.0.1 - TODO: drop support in Firmata 2.6
275278
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
276279
#endif
277-
pinConfig[pin] = INPUT;
280+
Firmata.setPinMode(pin, INPUT);
278281
}
279282
break;
280283
case PIN_MODE_PULLUP:
281284
if (IS_PIN_DIGITAL(pin)) {
282285
pinMode(PIN_TO_DIGITAL(pin), INPUT_PULLUP);
283-
pinConfig[pin] = PIN_MODE_PULLUP;
284-
pinState[pin] = 1;
286+
Firmata.setPinMode(pin, PIN_MODE_PULLUP);
287+
Firmata.setPinState(pin, 1);
285288
}
286289
break;
287290
case OUTPUT:
288291
if (IS_PIN_DIGITAL(pin)) {
289292
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
290293
pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
291-
pinConfig[pin] = OUTPUT;
294+
Firmata.setPinMode(pin, OUTPUT);
292295
}
293296
break;
294297
case PIN_MODE_PWM:
295298
if (IS_PIN_PWM(pin)) {
296299
pinMode(PIN_TO_PWM(pin), OUTPUT);
297300
analogWrite(PIN_TO_PWM(pin), 0);
298-
pinConfig[pin] = PIN_MODE_PWM;
301+
Firmata.setPinMode(pin, PIN_MODE_PWM);
299302
}
300303
break;
301304
case PIN_MODE_SERVO:
302305
if (IS_PIN_DIGITAL(pin)) {
303-
pinConfig[pin] = PIN_MODE_SERVO;
306+
Firmata.setPinMode(pin, PIN_MODE_SERVO);
304307
if (servoPinMap[pin] == 255 || !servos[servoPinMap[pin]].attached()) {
305308
// pass -1 for min and max pulse values to use default values set
306309
// by Servo library
@@ -312,9 +315,14 @@ void setPinModeCallback(byte pin, int mode)
312315
if (IS_PIN_I2C(pin)) {
313316
// mark the pin as i2c
314317
// the user must call I2C_CONFIG to enable I2C for a device
315-
pinConfig[pin] = PIN_MODE_I2C;
318+
Firmata.setPinMode(pin, PIN_MODE_I2C);
316319
}
317320
break;
321+
case PIN_MODE_SERIAL:
322+
#ifdef FIRMATA_SERIAL_FEATURE
323+
serialFeature.handlePinMode(pin, PIN_MODE_SERIAL);
324+
#endif
325+
break;
318326
default:
319327
Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
320328
}
@@ -330,8 +338,8 @@ void setPinModeCallback(byte pin, int mode)
330338
void setPinValueCallback(byte pin, int value)
331339
{
332340
if (pin < TOTAL_PINS && IS_PIN_DIGITAL(pin)) {
333-
if (pinConfig[pin] == OUTPUT) {
334-
pinState[pin] = value;
341+
if (Firmata.getPinMode(pin) == OUTPUT) {
342+
Firmata.setPinState(pin, value);
335343
digitalWrite(PIN_TO_DIGITAL(pin), value);
336344
}
337345
}
@@ -340,16 +348,16 @@ void setPinValueCallback(byte pin, int value)
340348
void analogWriteCallback(byte pin, int value)
341349
{
342350
if (pin < TOTAL_PINS) {
343-
switch (pinConfig[pin]) {
351+
switch (Firmata.getPinMode(pin)) {
344352
case PIN_MODE_SERVO:
345353
if (IS_PIN_DIGITAL(pin))
346354
servos[servoPinMap[pin]].write(value);
347-
pinState[pin] = value;
355+
Firmata.setPinState(pin, value);
348356
break;
349357
case PIN_MODE_PWM:
350358
if (IS_PIN_PWM(pin))
351359
analogWrite(PIN_TO_PWM(pin), value);
352-
pinState[pin] = value;
360+
Firmata.setPinState(pin, value);
353361
break;
354362
}
355363
}
@@ -367,11 +375,11 @@ void digitalWriteCallback(byte port, int value)
367375
// do not disturb non-digital pins (eg, Rx & Tx)
368376
if (IS_PIN_DIGITAL(pin)) {
369377
// do not touch pins in PWM, ANALOG, SERVO or other modes
370-
if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
378+
if (Firmata.getPinMode(pin) == OUTPUT || Firmata.getPinMode(pin) == INPUT) {
371379
pinValue = ((byte)value & mask) ? 1 : 0;
372-
if (pinConfig[pin] == OUTPUT) {
380+
if (Firmata.getPinMode(pin) == OUTPUT) {
373381
pinWriteMask |= mask;
374-
} else if (pinConfig[pin] == INPUT && pinValue == 1 && pinState[pin] != 1) {
382+
} else if (Firmata.getPinMode(pin) == INPUT && pinValue == 1 && Firmata.getPinState(pin) != 1) {
375383
// only handle INPUT here for backwards compatibility
376384
#if ARDUINO > 100
377385
pinMode(pin, INPUT_PULLUP);
@@ -380,7 +388,7 @@ void digitalWriteCallback(byte port, int value)
380388
pinWriteMask |= mask;
381389
#endif
382390
}
383-
pinState[pin] = pinValue;
391+
Firmata.setPinState(pin, pinValue);
384392
}
385393
}
386394
mask = mask << 1;
@@ -617,6 +625,9 @@ void sysexCallback(byte command, byte argc, byte *argv)
617625
Firmata.write(PIN_MODE_I2C);
618626
Firmata.write(1); // TODO: could assign a number to map to SCL or SDA
619627
}
628+
#ifdef FIRMATA_SERIAL_FEATURE
629+
serialFeature.handleCapability(pin);
630+
#endif
620631
Firmata.write(127);
621632
}
622633
Firmata.write(END_SYSEX);
@@ -628,10 +639,10 @@ void sysexCallback(byte command, byte argc, byte *argv)
628639
Firmata.write(PIN_STATE_RESPONSE);
629640
Firmata.write(pin);
630641
if (pin < TOTAL_PINS) {
631-
Firmata.write((byte)pinConfig[pin]);
632-
Firmata.write((byte)pinState[pin] & 0x7F);
633-
if (pinState[pin] & 0xFF80) Firmata.write((byte)(pinState[pin] >> 7) & 0x7F);
634-
if (pinState[pin] & 0xC000) Firmata.write((byte)(pinState[pin] >> 14) & 0x7F);
642+
Firmata.write(Firmata.getPinMode(pin));
643+
Firmata.write((byte)Firmata.getPinState(pin) & 0x7F);
644+
if (Firmata.getPinState(pin) & 0xFF80) Firmata.write((byte)(Firmata.getPinState(pin) >> 7) & 0x7F);
645+
if (Firmata.getPinState(pin) & 0xC000) Firmata.write((byte)(Firmata.getPinState(pin) >> 14) & 0x7F);
635646
}
636647
Firmata.write(END_SYSEX);
637648
}
@@ -644,6 +655,12 @@ void sysexCallback(byte command, byte argc, byte *argv)
644655
}
645656
Firmata.write(END_SYSEX);
646657
break;
658+
659+
case SERIAL_MESSAGE:
660+
#ifdef FIRMATA_SERIAL_FEATURE
661+
serialFeature.handleSysex(command, argc, argv);
662+
#endif
663+
break;
647664
}
648665
}
649666

@@ -682,6 +699,10 @@ void systemResetCallback()
682699
// initialize a defalt state
683700
// TODO: option to load config from EEPROM instead of default
684701

702+
#ifdef FIRMATA_SERIAL_FEATURE
703+
serialFeature.reset();
704+
#endif
705+
685706
if (isI2CEnabled) {
686707
disableI2CPins();
687708
}
@@ -740,12 +761,13 @@ void setup()
740761
// Call begin(baud) on the alternate serial port and pass it to Firmata to begin like this:
741762
// Serial1.begin(57600);
742763
// Firmata.begin(Serial1);
743-
// then comment out or remove lines 701 - 704 below
764+
// However do not do this if you are using SERIAL_MESSAGE
744765

745766
Firmata.begin(57600);
746767
while (!Serial) {
747768
; // wait for serial port to connect. Needed for ATmega32u4-based boards and Arduino 101
748769
}
770+
749771
systemResetCallback(); // reset to default config
750772
}
751773

@@ -772,7 +794,7 @@ void loop()
772794
previousMillis += samplingInterval;
773795
/* ANALOGREAD - do all analogReads() at the configured sampling interval */
774796
for (pin = 0; pin < TOTAL_PINS; pin++) {
775-
if (IS_PIN_ANALOG(pin) && pinConfig[pin] == PIN_MODE_ANALOG) {
797+
if (IS_PIN_ANALOG(pin) && Firmata.getPinMode(pin) == PIN_MODE_ANALOG) {
776798
analogPin = PIN_TO_ANALOG(pin);
777799
if (analogInputsToReport & (1 << analogPin)) {
778800
Firmata.sendAnalog(analogPin, analogRead(analogPin));
@@ -786,4 +808,8 @@ void loop()
786808
}
787809
}
788810
}
811+
812+
#ifdef FIRMATA_SERIAL_FEATURE
813+
serialFeature.update();
814+
#endif
789815
}

0 commit comments

Comments
 (0)