diff --git a/Firmata.h b/Firmata.h index 80f37259..a7598e4b 100644 --- a/Firmata.h +++ b/Firmata.h @@ -42,6 +42,7 @@ // extended command set using sysex (0-127/0x00-0x7F) /* 0x00-0x0F reserved for user-defined commands */ #define ENCODER_DATA 0x61 // reply with encoders current positions +#define LED_STRIP_DATA 0x62 // control neo pixels #define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq #define STRING_DATA 0x71 // a string message with 14-bits per char #define STEPPER_DATA 0x72 // control a stepper motor @@ -80,8 +81,9 @@ #define ONEWIRE 0x07 // pin configured for 1-wire #define STEPPER 0x08 // pin configured for stepper motor #define ENCODER 0x09 // pin configured for encoders +#define LED_STRIP 0x0A // pin configured for led strips #define IGNORE 0x7F // pin configured to be ignored by digitalWrite and capabilityResponse -#define TOTAL_PIN_MODES 11 +#define TOTAL_PIN_MODES 12 extern "C" { // callback function types diff --git a/test/neopixel_test/neopixel_test.ino b/test/neopixel_test/neopixel_test.ino new file mode 100644 index 00000000..cb7e2cb7 --- /dev/null +++ b/test/neopixel_test/neopixel_test.ino @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include + +#include +FirmataExt firmataExt; + +#include "utility/neopixelFirmata.h" +NeopixelFirmata* neopixelFirmata = neopixelFirmataFactory(); + +/*============================================================================== + * FUNCTIONS + *============================================================================*/ + +void systemResetCallback() +{ + // initialize a defalt state + + // pins with analog capability default to analog input + // otherwise, pins default to digital output + for (byte i=0; i < TOTAL_PINS; i++) { + } + + firmataExt.reset(); +} + +/*============================================================================== + * SETUP() + *============================================================================*/ + +void setup() +{ + Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION); + firmataExt.addFeature(*neopixelFirmata); + Firmata.attach(SYSTEM_RESET, systemResetCallback); + + // start up the default Firmata using Serial interface: + Firmata.begin(57600); + systemResetCallback(); // reset to default config +} + +/*============================================================================== + * LOOP() + *============================================================================*/ +void loop() +{ + + while(Firmata.available()) { + Firmata.processInput(); + } + +} + diff --git a/utility/LedStripFirmata.cpp b/utility/LedStripFirmata.cpp new file mode 100644 index 00000000..0a681ba8 --- /dev/null +++ b/utility/LedStripFirmata.cpp @@ -0,0 +1,75 @@ +#include "LedStripFirmata.h" +// Choose one pixel subtype to include +#include "NeopixelFirmata.h" +// #include "Ws2801PixelFirmata.h" // Not completed yet + +void LedStripFirmata::handleCapability(byte pin) +{ + if (IS_PIN_DIGITAL(pin)) + { + Firmata.write(LED_STRIP); + Firmata.write(1); // Not sure if this is necessary + } +} + +boolean LedStripFirmata::handlePinMode(byte pin, int mode) +{ + if (mode == LED_STRIP && IS_PIN_DIGITAL(pin)) + { + return true; + } + return false; +} + +void LedStripFirmata::reportDone() +{ + Firmata.write(START_SYSEX); + Firmata.write(LED_STRIP_DATA); + Firmata.write(LED_STRIP_CMD_DONE); + Firmata.write(END_SYSEX); +} + +void LedStripFirmata::reportType() +{ + Firmata.write(START_SYSEX); + Firmata.write(LED_STRIP_DATA); + Firmata.write(LED_STRIP_CMD_QUERY); + Firmata.write(ledType()); + Firmata.write(END_SYSEX); +} + + +boolean LedStripFirmata::handleSysex(byte command, byte argc, byte* argv) +{ + if (command != LED_STRIP_DATA) + { + return false; + } + + byte npCommand = argv[0]; + if (!initialized && npCommand != LED_STRIP_CMD_INIT && npCommand != LED_STRIP_CMD_QUERY) + { + // Firmata.sendString("Led Strip Not Initialized: Not Initialized"); + return false; + } + + switch(npCommand) { + case LED_STRIP_CMD_QUERY: + reportType(); + return true; + + default: + return handleStripCommand(npCommand, argc, argv); + } + + return true; + +} + + +LedStripFirmata* ledStripFirmataFactory() +{ + #ifdef NeopixelFirmata_H + return new NeopixelFirmataImpl(); + #endif +} diff --git a/utility/LedStripFirmata.h b/utility/LedStripFirmata.h new file mode 100644 index 00000000..fb21da34 --- /dev/null +++ b/utility/LedStripFirmata.h @@ -0,0 +1,50 @@ +#ifndef LedStripFirmata_H +#define LedStripFirmata_H + +#include +#include "FirmataExt.h" + +#define LED_STRIP_CMD_QUERY 0x00 +#define LED_STRIP_CMD_INIT 0x01 +#define LED_STRIP_CMD_PIXEL 0x02 +#define LED_STRIP_CMD_CLEAR 0x04 +#define LED_STRIP_CMD_SHOW 0x05 +#define LED_STRIP_CMD_BRIGHTNESS 0x06 +#define LED_STRIP_CMD_DONE 0x07 // Response + +#define LED_STRIP_INIT_PARAM_PIN 0x01 +#define LED_STRIP_INIT_PARAM_COUNT 0x02 +#define LED_STRIP_INIT_PARAM_ORDER 0x04 +#define LED_STRIP_INIT_PARAM_SPEED 0x05 + +#define LED_STRIP_PIXEL_PARAM_LOCATION 0x01 +#define LED_STRIP_PIXEL_PARAM_RED 0x03 +#define LED_STRIP_PIXEL_PARAM_GREEN 0x05 +#define LED_STRIP_PIXEL_PARAM_BLUE 0x07 + +#define LED_STRIP_BRIGHTNESS_PARAM_VALUE 0x01 + +#define LED_STRIP_TYPE_NEOPIXEL 0x00 +#define LED_STRIP_TYPE_WS2801 0x01 + +class LedStripFirmata : public FirmataFeature +{ +public: + LedStripFirmata() {} + void handleCapability(byte pin); + boolean handlePinMode(byte pin, int mode); + boolean handleSysex(byte command, byte argc, byte* argv); + virtual void reset() = 0; + +protected: + virtual boolean handleStripCommand(byte command, byte argc, byte* argv) = 0; + void reportDone(); + void reportType(); + virtual byte ledType() = 0; + + boolean initialized = false; +}; + +LedStripFirmata* ledStripFirmataFactory(); + +#endif // LedStripFirmata_H diff --git a/utility/NeopixelFirmata.cpp b/utility/NeopixelFirmata.cpp new file mode 100644 index 00000000..97e6d924 --- /dev/null +++ b/utility/NeopixelFirmata.cpp @@ -0,0 +1,108 @@ +#include "LedStripFirmata.h" +#include "NeopixelFirmata.h" +#include + +#define TOBYTE(loc) ((argv[loc] + (argv[loc+1] << 7))&0xFF) + +NeopixelFirmataImpl::NeopixelFirmataImpl() +{ + pixels = NULL; +} + +boolean NeopixelFirmataImpl::handleStripCommand(byte npCommand, byte argc, byte* argv) +{ + byte tmp; + + switch(npCommand) { + + case LED_STRIP_CMD_INIT: + initialize( + argv[LED_STRIP_INIT_PARAM_PIN], + TOBYTE(LED_STRIP_INIT_PARAM_COUNT), + argv[LED_STRIP_INIT_PARAM_ORDER], + argv[LED_STRIP_INIT_PARAM_SPEED] + ); + break; + + case LED_STRIP_CMD_CLEAR: + pixels->clear(); + break; + + case LED_STRIP_CMD_SHOW: + pixels->show(); + break; + + case LED_STRIP_CMD_BRIGHTNESS: + if (argc>2) { + pixels->setBrightness(TOBYTE(LED_STRIP_BRIGHTNESS_PARAM_VALUE)); + } else { + reportBrightness(); + } + break; + + case LED_STRIP_CMD_PIXEL: + tmp = TOBYTE(LED_STRIP_PIXEL_PARAM_LOCATION); + + if(tmp > pixels->numPixels()) + { + // Firmata.sendString("NeoPixel: Location out of range"); + return false; + } + + setPixel( + tmp, + TOBYTE(LED_STRIP_PIXEL_PARAM_RED), + TOBYTE(LED_STRIP_PIXEL_PARAM_GREEN), + TOBYTE(LED_STRIP_PIXEL_PARAM_BLUE) + ); + break; + + default: + // Firmata.sendString("NeoPixel: Unknown Command"); + return false; + } + + return true; + +} + +void NeopixelFirmataImpl::reset() +{ + if (pixels != NULL) + { + delete pixels; + pixels = NULL; + } +} + +void NeopixelFirmataImpl::initialize(byte pin, byte count, byte order, byte speed) +{ + reset(); + + pixels = new Adafruit_NeoPixel(count, pin, order + speed); + pixels->begin(); + for(int i=0; isetPixelColor(i, 0, 0, 255); + pixels->show(); + delay(50); + } + pixels->clear(); + pixels->show(); + reportDone(); +} + +void NeopixelFirmataImpl::reportBrightness() +{ + byte brightness = pixels->getBrightness(); + Firmata.write(START_SYSEX); + Firmata.write(LED_STRIP_DATA); + Firmata.write(LED_STRIP_CMD_BRIGHTNESS); + Firmata.write(brightness & 0x7F); + Firmata.write((brightness >> 7) & 0x7F); + Firmata.write(END_SYSEX); +} + +void NeopixelFirmataImpl::setPixel(byte location, byte red, byte green, byte blue) +{ + pixels->setPixelColor(location, red, green, blue); +} diff --git a/utility/NeopixelFirmata.h b/utility/NeopixelFirmata.h new file mode 100644 index 00000000..e4fabe40 --- /dev/null +++ b/utility/NeopixelFirmata.h @@ -0,0 +1,26 @@ +#ifndef NeopixelFirmata_H +#define NeopixelFirmata_H + +#include "LedStripFirmata.h" +#include "Adafruit_Neopixel.h" + +class NeopixelFirmataImpl : public LedStripFirmata +{ +public: + NeopixelFirmataImpl(); + virtual void reset(); + +protected: + byte ledType() { return LED_STRIP_TYPE_NEOPIXEL; } + virtual boolean handleStripCommand(byte command, byte argc, byte* argv); + bool initialized; + +private: + Adafruit_NeoPixel* pixels; + void initialize(byte pin, byte count, byte order, byte speed); + void reportBrightness(); + void setPixel(byte position, byte red, byte green, byte blue); +}; + +#endif // NeopixelFirmata_H +