Skip to content

Commit

Permalink
Merge pull request #345 from zfields/core
Browse files Browse the repository at this point in the history
Core
  • Loading branch information
soundanalogous committed Feb 22, 2017
2 parents ae028fb + 29b4399 commit 2bd457a
Show file tree
Hide file tree
Showing 6 changed files with 385 additions and 91 deletions.
89 changes: 73 additions & 16 deletions Firmata.cpp
Expand Up @@ -29,13 +29,16 @@ extern "C" {
// make one instance for the user to use
FirmataClass Firmata;

void printVersion (void) {
Firmata.printVersion();
}

void printFirmwareVersion (void) {
Firmata.printFirmwareVersion();
}
/* callback functions */
callbackFunction FirmataClass::currentAnalogCallback = (callbackFunction)NULL;
callbackFunction FirmataClass::currentDigitalCallback = (callbackFunction)NULL;
callbackFunction FirmataClass::currentPinModeCallback = (callbackFunction)NULL;
callbackFunction FirmataClass::currentPinValueCallback = (callbackFunction)NULL;
callbackFunction FirmataClass::currentReportAnalogCallback = (callbackFunction)NULL;
callbackFunction FirmataClass::currentReportDigitalCallback = (callbackFunction)NULL;
stringCallbackFunction FirmataClass::currentStringCallback = (stringCallbackFunction)NULL;
sysexCallbackFunction FirmataClass::currentSysexCallback = (sysexCallbackFunction)NULL;
systemCallbackFunction FirmataClass::currentSystemResetCallback = (systemCallbackFunction)NULL;

//******************************************************************************
//* Support Functions
Expand Down Expand Up @@ -81,8 +84,19 @@ FirmataClass::FirmataClass()
firmwareVersionCount = 0;
firmwareVersionVector = 0;
blinkVersionDisabled = false;
parser.attach(REPORT_FIRMWARE, ::printFirmwareVersion);
parser.attach(REPORT_VERSION, ::printVersion);

// Establish callback translation to parser callbacks
parser.attach(ANALOG_MESSAGE, (FirmataParser::callbackFunction)staticAnalogCallback, (void *)NULL);
parser.attach(DIGITAL_MESSAGE, (FirmataParser::callbackFunction)staticDigitalCallback, (void *)NULL);
parser.attach(REPORT_ANALOG, (FirmataParser::callbackFunction)staticReportAnalogCallback, (void *)NULL);
parser.attach(REPORT_DIGITAL, (FirmataParser::callbackFunction)staticReportDigitalCallback, (void *)NULL);
parser.attach(SET_PIN_MODE, (FirmataParser::callbackFunction)staticPinModeCallback, (void *)NULL);
parser.attach(SET_DIGITAL_PIN_VALUE, (FirmataParser::callbackFunction)staticPinValueCallback, (void *)NULL);
parser.attach(STRING_DATA, (FirmataParser::stringCallbackFunction)staticStringCallback, (void *)NULL);
parser.attach(START_SYSEX, (FirmataParser::sysexCallbackFunction)staticSysexCallback, (void *)NULL);
parser.attach(REPORT_FIRMWARE, (FirmataParser::systemCallbackFunction)staticReportFirmwareCallback, this);
parser.attach(REPORT_VERSION, (FirmataParser::systemCallbackFunction)staticReportVersionCallback, this);
parser.attach(SYSTEM_RESET, (FirmataParser::systemCallbackFunction)staticSystemResetCallback, (void *)NULL);
}

//******************************************************************************
Expand Down Expand Up @@ -296,6 +310,8 @@ void FirmataClass::sendAnalog(byte pin, int value)
*/
void FirmataClass::sendDigital(byte pin, int value)
{
(void)pin;
(void)value;
/* TODO add single pin digital messages to the protocol, this needs to
* track the last digital data sent so that it can be sure to change just
* one bit in the packet. This is complicated by the fact that the
Expand Down Expand Up @@ -376,9 +392,28 @@ void FirmataClass::write(byte c)
* @param command The ID of the command to attach a callback function to.
* @param newFunction A reference to the callback function to attach.
*/
void FirmataClass::attach(uint8_t command, callbackFunction newFunction)
{
parser.attach(command, (callbackFunction)newFunction);
void FirmataClass::attach(uint8_t command, ::callbackFunction newFunction)
{
switch (command) {
case ANALOG_MESSAGE:
currentAnalogCallback = newFunction;
break;
case DIGITAL_MESSAGE:
currentDigitalCallback = newFunction;
break;
case REPORT_ANALOG:
currentReportAnalogCallback = newFunction;
break;
case REPORT_DIGITAL:
currentReportDigitalCallback = newFunction;
break;
case SET_PIN_MODE:
currentPinModeCallback = newFunction;
break;
case SET_DIGITAL_PIN_VALUE:
currentPinValueCallback = newFunction;
break;
}
}

/**
Expand All @@ -388,7 +423,11 @@ void FirmataClass::attach(uint8_t command, callbackFunction newFunction)
*/
void FirmataClass::attach(uint8_t command, systemCallbackFunction newFunction)
{
parser.attach(command, (systemCallbackFunction)newFunction);
switch (command) {
case SYSTEM_RESET:
currentSystemResetCallback = newFunction;
break;
}
}

/**
Expand All @@ -398,7 +437,11 @@ void FirmataClass::attach(uint8_t command, systemCallbackFunction newFunction)
*/
void FirmataClass::attach(uint8_t command, stringCallbackFunction newFunction)
{
parser.attach(command, (stringCallbackFunction)newFunction);
switch (command) {
case STRING_DATA:
currentStringCallback = newFunction;
break;
}
}

/**
Expand All @@ -408,7 +451,8 @@ void FirmataClass::attach(uint8_t command, stringCallbackFunction newFunction)
*/
void FirmataClass::attach(uint8_t command, sysexCallbackFunction newFunction)
{
parser.attach(command, (sysexCallbackFunction)newFunction);
(void)command;
currentSysexCallback = newFunction;
}

/**
Expand All @@ -418,7 +462,20 @@ void FirmataClass::attach(uint8_t command, sysexCallbackFunction newFunction)
*/
void FirmataClass::detach(uint8_t command)
{
parser.detach(command);
switch (command) {
case SYSTEM_RESET:
attach(command, (systemCallbackFunction)NULL);
break;
case STRING_DATA:
attach(command, (stringCallbackFunction)NULL);
break;
case START_SYSEX:
attach(command, (sysexCallbackFunction)NULL);
break;
default:
attach(command, (callbackFunction)NULL);
break;
}
}

/**
Expand Down
49 changes: 45 additions & 4 deletions Firmata.h
Expand Up @@ -48,27 +48,40 @@
#define ENCODER 0x09 // same as PIN_MODE_ENCODER
#define IGNORE 0x7F // same as PIN_MODE_IGNORE

extern "C" {
// callback function types
typedef void (*callbackFunction)(uint8_t, int);
typedef void (*systemCallbackFunction)(void);
typedef void (*stringCallbackFunction)(char *);
typedef void (*sysexCallbackFunction)(uint8_t command, uint8_t argc, uint8_t *argv);
}

// TODO make it a subclass of a generic Serial/Stream base class
class FirmataClass
{
public:
FirmataClass();

/* Arduino constructors */
void begin();
void begin(long);
void begin(Stream &s);

/* querying functions */
void printVersion(void);
void blinkVersion(void);
void printFirmwareVersion(void);

//void setFirmwareVersion(byte major, byte minor); // see macro below
void setFirmwareNameAndVersion(const char *name, byte major, byte minor);
void disableBlinkVersion();

/* serial receive handling */
int available(void);
void processInput(void);
void parse(unsigned char value);
boolean isParsingMessage(void);

/* serial send handling */
void sendAnalog(byte pin, int value);
void sendDigital(byte pin, int value); // TODO implement this
Expand All @@ -77,16 +90,18 @@ class FirmataClass
void sendString(byte command, const char *string);
void sendSysex(byte command, byte bytec, byte *bytev);
void write(byte c);

/* attach & detach callback functions to messages */
void attach(uint8_t command, callbackFunction newFunction);
void attach(uint8_t command, systemCallbackFunction newFunction);
void attach(uint8_t command, stringCallbackFunction newFunction);
void attach(uint8_t command, sysexCallbackFunction newFunction);
void attach(uint8_t command, ::callbackFunction newFunction);
void attach(uint8_t command, ::systemCallbackFunction newFunction);
void attach(uint8_t command, ::stringCallbackFunction newFunction);
void attach(uint8_t command, ::sysexCallbackFunction newFunction);
void detach(uint8_t command);

/* access pin state and config */
byte getPinMode(byte pin);
void setPinMode(byte pin, byte config);

/* access pin state */
int getPinState(byte pin);
void setPinState(byte pin, int state);
Expand All @@ -101,9 +116,11 @@ class FirmataClass
FirmataMarshaller marshaller;
FirmataParser parser;
Stream *FirmataStream;

/* firmware name and version */
byte firmwareVersionCount;
byte *firmwareVersionVector;

/* pin configuration */
byte pinConfig[TOTAL_PINS];
int pinState[TOTAL_PINS];
Expand All @@ -113,6 +130,30 @@ class FirmataClass
/* private methods ------------------------------ */
void strobeBlinkPin(byte pin, int count, int onInterval, int offInterval);
friend void FirmataMarshaller::sendValueAsTwo7bitBytes(uint16_t value) const;

/* callback functions */
static callbackFunction currentAnalogCallback;
static callbackFunction currentDigitalCallback;
static callbackFunction currentPinModeCallback;
static callbackFunction currentPinValueCallback;
static callbackFunction currentReportAnalogCallback;
static callbackFunction currentReportDigitalCallback;
static stringCallbackFunction currentStringCallback;
static sysexCallbackFunction currentSysexCallback;
static systemCallbackFunction currentSystemResetCallback;

/* static callbacks */
inline static void staticAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentAnalogCallback ) { currentAnalogCallback(command,(int)value); } }
inline static void staticDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentDigitalCallback ) { currentDigitalCallback(command, (int)value); } }
inline static void staticPinModeCallback (void *, uint8_t command, uint16_t value) { if ( currentPinModeCallback ) { currentPinModeCallback(command, (int)value); } }
inline static void staticPinValueCallback (void *, uint8_t command, uint16_t value) { if ( currentPinValueCallback ) { currentPinValueCallback(command, (int)value); } }
inline static void staticReportAnalogCallback (void *, uint8_t command, uint16_t value) { if ( currentReportAnalogCallback ) { currentReportAnalogCallback(command, (int)value); } }
inline static void staticReportDigitalCallback (void *, uint8_t command, uint16_t value) { if ( currentReportDigitalCallback ) { currentReportDigitalCallback(command, (int)value); } }
inline static void staticStringCallback (void *, char * c_str) { if ( currentStringCallback ) { currentStringCallback(c_str); } }
inline static void staticSysexCallback (void *, uint8_t command, size_t argc, uint8_t *argv) { if ( currentSysexCallback ) { currentSysexCallback(command, (uint8_t)argc, argv); } }
inline static void staticReportFirmwareCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printFirmwareVersion(); } }
inline static void staticReportVersionCallback (void * context) { if ( context ) { ((FirmataClass *)context)->printVersion(); } }
inline static void staticSystemResetCallback (void *) { if ( currentSystemResetCallback ) { currentSystemResetCallback(); } }
};

extern FirmataClass Firmata;
Expand Down

0 comments on commit 2bd457a

Please sign in to comment.