Skip to content

Commit 2bd457a

Browse files
Merge pull request firmata#345 from zfields/core
Core
2 parents ae028fb + 29b4399 commit 2bd457a

File tree

6 files changed

+385
-91
lines changed

6 files changed

+385
-91
lines changed

Firmata.cpp

Lines changed: 73 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@ extern "C" {
2929
// make one instance for the user to use
3030
FirmataClass Firmata;
3131

32-
void printVersion (void) {
33-
Firmata.printVersion();
34-
}
35-
36-
void printFirmwareVersion (void) {
37-
Firmata.printFirmwareVersion();
38-
}
32+
/* callback functions */
33+
callbackFunction FirmataClass::currentAnalogCallback = (callbackFunction)NULL;
34+
callbackFunction FirmataClass::currentDigitalCallback = (callbackFunction)NULL;
35+
callbackFunction FirmataClass::currentPinModeCallback = (callbackFunction)NULL;
36+
callbackFunction FirmataClass::currentPinValueCallback = (callbackFunction)NULL;
37+
callbackFunction FirmataClass::currentReportAnalogCallback = (callbackFunction)NULL;
38+
callbackFunction FirmataClass::currentReportDigitalCallback = (callbackFunction)NULL;
39+
stringCallbackFunction FirmataClass::currentStringCallback = (stringCallbackFunction)NULL;
40+
sysexCallbackFunction FirmataClass::currentSysexCallback = (sysexCallbackFunction)NULL;
41+
systemCallbackFunction FirmataClass::currentSystemResetCallback = (systemCallbackFunction)NULL;
3942

4043
//******************************************************************************
4144
//* Support Functions
@@ -81,8 +84,19 @@ FirmataClass::FirmataClass()
8184
firmwareVersionCount = 0;
8285
firmwareVersionVector = 0;
8386
blinkVersionDisabled = false;
84-
parser.attach(REPORT_FIRMWARE, ::printFirmwareVersion);
85-
parser.attach(REPORT_VERSION, ::printVersion);
87+
88+
// Establish callback translation to parser callbacks
89+
parser.attach(ANALOG_MESSAGE, (FirmataParser::callbackFunction)staticAnalogCallback, (void *)NULL);
90+
parser.attach(DIGITAL_MESSAGE, (FirmataParser::callbackFunction)staticDigitalCallback, (void *)NULL);
91+
parser.attach(REPORT_ANALOG, (FirmataParser::callbackFunction)staticReportAnalogCallback, (void *)NULL);
92+
parser.attach(REPORT_DIGITAL, (FirmataParser::callbackFunction)staticReportDigitalCallback, (void *)NULL);
93+
parser.attach(SET_PIN_MODE, (FirmataParser::callbackFunction)staticPinModeCallback, (void *)NULL);
94+
parser.attach(SET_DIGITAL_PIN_VALUE, (FirmataParser::callbackFunction)staticPinValueCallback, (void *)NULL);
95+
parser.attach(STRING_DATA, (FirmataParser::stringCallbackFunction)staticStringCallback, (void *)NULL);
96+
parser.attach(START_SYSEX, (FirmataParser::sysexCallbackFunction)staticSysexCallback, (void *)NULL);
97+
parser.attach(REPORT_FIRMWARE, (FirmataParser::systemCallbackFunction)staticReportFirmwareCallback, this);
98+
parser.attach(REPORT_VERSION, (FirmataParser::systemCallbackFunction)staticReportVersionCallback, this);
99+
parser.attach(SYSTEM_RESET, (FirmataParser::systemCallbackFunction)staticSystemResetCallback, (void *)NULL);
86100
}
87101

88102
//******************************************************************************
@@ -296,6 +310,8 @@ void FirmataClass::sendAnalog(byte pin, int value)
296310
*/
297311
void FirmataClass::sendDigital(byte pin, int value)
298312
{
313+
(void)pin;
314+
(void)value;
299315
/* TODO add single pin digital messages to the protocol, this needs to
300316
* track the last digital data sent so that it can be sure to change just
301317
* one bit in the packet. This is complicated by the fact that the
@@ -376,9 +392,28 @@ void FirmataClass::write(byte c)
376392
* @param command The ID of the command to attach a callback function to.
377393
* @param newFunction A reference to the callback function to attach.
378394
*/
379-
void FirmataClass::attach(uint8_t command, callbackFunction newFunction)
380-
{
381-
parser.attach(command, (callbackFunction)newFunction);
395+
void FirmataClass::attach(uint8_t command, ::callbackFunction newFunction)
396+
{
397+
switch (command) {
398+
case ANALOG_MESSAGE:
399+
currentAnalogCallback = newFunction;
400+
break;
401+
case DIGITAL_MESSAGE:
402+
currentDigitalCallback = newFunction;
403+
break;
404+
case REPORT_ANALOG:
405+
currentReportAnalogCallback = newFunction;
406+
break;
407+
case REPORT_DIGITAL:
408+
currentReportDigitalCallback = newFunction;
409+
break;
410+
case SET_PIN_MODE:
411+
currentPinModeCallback = newFunction;
412+
break;
413+
case SET_DIGITAL_PIN_VALUE:
414+
currentPinValueCallback = newFunction;
415+
break;
416+
}
382417
}
383418

384419
/**
@@ -388,7 +423,11 @@ void FirmataClass::attach(uint8_t command, callbackFunction newFunction)
388423
*/
389424
void FirmataClass::attach(uint8_t command, systemCallbackFunction newFunction)
390425
{
391-
parser.attach(command, (systemCallbackFunction)newFunction);
426+
switch (command) {
427+
case SYSTEM_RESET:
428+
currentSystemResetCallback = newFunction;
429+
break;
430+
}
392431
}
393432

394433
/**
@@ -398,7 +437,11 @@ void FirmataClass::attach(uint8_t command, systemCallbackFunction newFunction)
398437
*/
399438
void FirmataClass::attach(uint8_t command, stringCallbackFunction newFunction)
400439
{
401-
parser.attach(command, (stringCallbackFunction)newFunction);
440+
switch (command) {
441+
case STRING_DATA:
442+
currentStringCallback = newFunction;
443+
break;
444+
}
402445
}
403446

404447
/**
@@ -408,7 +451,8 @@ void FirmataClass::attach(uint8_t command, stringCallbackFunction newFunction)
408451
*/
409452
void FirmataClass::attach(uint8_t command, sysexCallbackFunction newFunction)
410453
{
411-
parser.attach(command, (sysexCallbackFunction)newFunction);
454+
(void)command;
455+
currentSysexCallback = newFunction;
412456
}
413457

414458
/**
@@ -418,7 +462,20 @@ void FirmataClass::attach(uint8_t command, sysexCallbackFunction newFunction)
418462
*/
419463
void FirmataClass::detach(uint8_t command)
420464
{
421-
parser.detach(command);
465+
switch (command) {
466+
case SYSTEM_RESET:
467+
attach(command, (systemCallbackFunction)NULL);
468+
break;
469+
case STRING_DATA:
470+
attach(command, (stringCallbackFunction)NULL);
471+
break;
472+
case START_SYSEX:
473+
attach(command, (sysexCallbackFunction)NULL);
474+
break;
475+
default:
476+
attach(command, (callbackFunction)NULL);
477+
break;
478+
}
422479
}
423480

424481
/**

Firmata.h

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,27 +48,40 @@
4848
#define ENCODER 0x09 // same as PIN_MODE_ENCODER
4949
#define IGNORE 0x7F // same as PIN_MODE_IGNORE
5050

51+
extern "C" {
52+
// callback function types
53+
typedef void (*callbackFunction)(uint8_t, int);
54+
typedef void (*systemCallbackFunction)(void);
55+
typedef void (*stringCallbackFunction)(char *);
56+
typedef void (*sysexCallbackFunction)(uint8_t command, uint8_t argc, uint8_t *argv);
57+
}
58+
5159
// TODO make it a subclass of a generic Serial/Stream base class
5260
class FirmataClass
5361
{
5462
public:
5563
FirmataClass();
64+
5665
/* Arduino constructors */
5766
void begin();
5867
void begin(long);
5968
void begin(Stream &s);
69+
6070
/* querying functions */
6171
void printVersion(void);
6272
void blinkVersion(void);
6373
void printFirmwareVersion(void);
74+
6475
//void setFirmwareVersion(byte major, byte minor); // see macro below
6576
void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
6677
void disableBlinkVersion();
78+
6779
/* serial receive handling */
6880
int available(void);
6981
void processInput(void);
7082
void parse(unsigned char value);
7183
boolean isParsingMessage(void);
84+
7285
/* serial send handling */
7386
void sendAnalog(byte pin, int value);
7487
void sendDigital(byte pin, int value); // TODO implement this
@@ -77,16 +90,18 @@ class FirmataClass
7790
void sendString(byte command, const char *string);
7891
void sendSysex(byte command, byte bytec, byte *bytev);
7992
void write(byte c);
93+
8094
/* attach & detach callback functions to messages */
81-
void attach(uint8_t command, callbackFunction newFunction);
82-
void attach(uint8_t command, systemCallbackFunction newFunction);
83-
void attach(uint8_t command, stringCallbackFunction newFunction);
84-
void attach(uint8_t command, sysexCallbackFunction newFunction);
95+
void attach(uint8_t command, ::callbackFunction newFunction);
96+
void attach(uint8_t command, ::systemCallbackFunction newFunction);
97+
void attach(uint8_t command, ::stringCallbackFunction newFunction);
98+
void attach(uint8_t command, ::sysexCallbackFunction newFunction);
8599
void detach(uint8_t command);
86100

87101
/* access pin state and config */
88102
byte getPinMode(byte pin);
89103
void setPinMode(byte pin, byte config);
104+
90105
/* access pin state */
91106
int getPinState(byte pin);
92107
void setPinState(byte pin, int state);
@@ -101,9 +116,11 @@ class FirmataClass
101116
FirmataMarshaller marshaller;
102117
FirmataParser parser;
103118
Stream *FirmataStream;
119+
104120
/* firmware name and version */
105121
byte firmwareVersionCount;
106122
byte *firmwareVersionVector;
123+
107124
/* pin configuration */
108125
byte pinConfig[TOTAL_PINS];
109126
int pinState[TOTAL_PINS];
@@ -113,6 +130,30 @@ class FirmataClass
113130
/* private methods ------------------------------ */
114131
void strobeBlinkPin(byte pin, int count, int onInterval, int offInterval);
115132
friend void FirmataMarshaller::sendValueAsTwo7bitBytes(uint16_t value) const;
133+
134+
/* callback functions */
135+
static callbackFunction currentAnalogCallback;
136+
static callbackFunction currentDigitalCallback;
137+
static callbackFunction currentPinModeCallback;
138+
static callbackFunction currentPinValueCallback;
139+
static callbackFunction currentReportAnalogCallback;
140+
static callbackFunction currentReportDigitalCallback;
141+
static stringCallbackFunction currentStringCallback;
142+
static sysexCallbackFunction currentSysexCallback;
143+
static systemCallbackFunction currentSystemResetCallback;
144+
145+
/* static callbacks */
146+
inline static void staticAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentAnalogCallback ) { currentAnalogCallback(command,(int)value); } }
147+
inline static void staticDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentDigitalCallback ) { currentDigitalCallback(command, (int)value); } }
148+
inline static void staticPinModeCallback (void *, uint8_t command, uint16_t value) { if ( currentPinModeCallback ) { currentPinModeCallback(command, (int)value); } }
149+
inline static void staticPinValueCallback (void *, uint8_t command, uint16_t value) { if ( currentPinValueCallback ) { currentPinValueCallback(command, (int)value); } }
150+
inline static void staticReportAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentReportAnalogCallback ) { currentReportAnalogCallback(command, (int)value); } }
151+
inline static void staticReportDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentReportDigitalCallback ) { currentReportDigitalCallback(command, (int)value); } }
152+
inline static void staticStringCallback (void *, char * c_str) { if ( currentStringCallback ) { currentStringCallback(c_str); } }
153+
inline static void staticSysexCallback (void *, uint8_t command, size_t argc, uint8_t *argv) { if ( currentSysexCallback ) { currentSysexCallback(command, (uint8_t)argc, argv); } }
154+
inline static void staticReportFirmwareCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printFirmwareVersion(); } }
155+
inline static void staticReportVersionCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printVersion(); } }
156+
inline static void staticSystemResetCallback (void *) { if ( currentSystemResetCallback ) { currentSystemResetCallback(); } }
116157
};
117158

118159
extern FirmataClass Firmata;

0 commit comments

Comments
 (0)