1
0
mirror of https://github.com/arduino/Arduino.git synced 2024-12-10 21:24:12 +01:00

Updating Firmata to r71.

Note that I also changed the extensions of the examples (firmwares) from .pde to .ino and removed the Makefiles (since they assume the pde extension).

http://code.google.com/p/arduino/issues/detail?id=447
This commit is contained in:
David A. Mellis 2011-09-02 14:43:44 -04:00
parent be786b70de
commit 108df37445
15 changed files with 113 additions and 2110 deletions

View File

@ -3,7 +3,13 @@
#ifndef Firmata_Boards_h #ifndef Firmata_Boards_h
#define Firmata_Boards_h #define Firmata_Boards_h
#include <Arduino.h> // for digitalRead, digitalWrite, etc #include <inttypes.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h" // for digitalRead, digitalWrite, etc
#else
#include "WProgram.h"
#endif
// Normally Servo.h must be included before Firmata.h (which then includes // Normally Servo.h must be included before Firmata.h (which then includes
// this file). If Servo.h wasn't included, this allows the code to still // this file). If Servo.h wasn't included, this allows the code to still
@ -120,40 +126,59 @@ writePort(port, value, bitmask): Write an 8 bit port.
// Arduino Duemilanove, Diecimila, and NG // Arduino Duemilanove, Diecimila, and NG
#if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__) #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega328P__)
#if defined(NUM_ANALOG_INPUTS) && NUM_ANALOG_INPUTS == 6
#define TOTAL_ANALOG_PINS 6
#define TOTAL_PINS 20 // 14 digital + 6 analog
#else
#define TOTAL_ANALOG_PINS 8 #define TOTAL_ANALOG_PINS 8
#define TOTAL_PINS 24 // 14 digital + 2 unused + 8 analog #define TOTAL_PINS 22 // 14 digital + 8 analog
#endif
#define VERSION_BLINK_PIN 13 #define VERSION_BLINK_PIN 13
#define IS_PIN_DIGITAL(p) (((p) >= 2 && (p) <= 13) || ((p) >= 16 && (p) <= 21)) #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19)
#define IS_PIN_ANALOG(p) ((p) >= 16 && (p) <= 23) #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) < 14 + TOTAL_ANALOG_PINS)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) <= 13 && (p) - 2 < MAX_SERVOS) #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
#define PIN_TO_DIGITAL(p) (((p) < 16) ? (p) : (p) - 2) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 16) #define PIN_TO_ANALOG(p) ((p) - 14)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) ((p) - 2) #define PIN_TO_SERVO(p) ((p) - 2)
#define ARDUINO_PINOUT_OPTIMIZE 1 #define ARDUINO_PINOUT_OPTIMIZE 1
// Wiring (and board)
#elif defined(WIRING)
#define VERSION_BLINK_PIN WLED
#define IS_PIN_DIGITAL(p) ((p) >= 0 && (p) < TOTAL_PINS)
#define IS_PIN_ANALOG(p) ((p) >= FIRST_ANALOG_PIN && (p) < (FIRST_ANALOG_PIN+TOTAL_ANALOG_PINS))
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) ((p) == SDA || (p) == SCL)
#define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - FIRST_ANALOG_PIN)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) (p)
// old Arduinos // old Arduinos
#elif defined(__AVR_ATmega8__) #elif defined(__AVR_ATmega8__)
#define TOTAL_ANALOG_PINS 6 #define TOTAL_ANALOG_PINS 6
#define TOTAL_PINS 22 // 14 digital + 2 unused + 6 analog #define TOTAL_PINS 20 // 14 digital + 6 analog
#define VERSION_BLINK_PIN 13 #define VERSION_BLINK_PIN 13
#define IS_PIN_DIGITAL(p) (((p) >= 2 && (p) <= 13) || ((p) >= 16 && (p) <= 21)) #define IS_PIN_DIGITAL(p) ((p) >= 2 && (p) <= 19)
#define IS_PIN_ANALOG(p) ((p) >= 16 && (p) <= 21) #define IS_PIN_ANALOG(p) ((p) >= 14 && (p) <= 19)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) <= 13 && (p) - 2 < MAX_SERVOS) #define IS_PIN_SERVO(p) (IS_PIN_DIGITAL(p) && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 18 || (p) == 19)
#define PIN_TO_DIGITAL(p) (((p) < 16) ? (p) : (p) - 2) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 16) #define PIN_TO_ANALOG(p) ((p) - 14)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) ((p) - 2) #define PIN_TO_SERVO(p) ((p) - 2)
#define ARDUINO_PINOUT_OPTIMIZE 1 #define ARDUINO_PINOUT_OPTIMIZE 1
// Arduino Mega // Arduino Mega
#elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) #elif defined(__AVR_ATmega1280__)
#define TOTAL_ANALOG_PINS 16 #define TOTAL_ANALOG_PINS 16
#define TOTAL_PINS 70 // 54 digital + 16 analog #define TOTAL_PINS 70 // 54 digital + 16 analog
#define VERSION_BLINK_PIN 13 #define VERSION_BLINK_PIN 13
@ -161,21 +186,13 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS) #define IS_PIN_ANALOG(p) ((p) >= 54 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 2 && (p) - 2 < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 20 || (p) == 21)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 54) #define PIN_TO_ANALOG(p) ((p) - 54)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
#define PIN_TO_SERVO(p) ((p) - 2) #define PIN_TO_SERVO(p) ((p) - 2)
// Wiring
#elif defined(__AVR_ATmega128__)
#define TOTAL_ANALOG_PINS 8
#define TOTAL_PINS 51
#define VERSION_BLINK_PIN 48
// TODO: hardware abstraction for wiring board
// Teensy 1.0 // Teensy 1.0
#elif defined(__AVR_AT90USB162__) #elif defined(__AVR_AT90USB162__)
#define TOTAL_ANALOG_PINS 0 #define TOTAL_ANALOG_PINS 0
@ -201,7 +218,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_ANALOG(p) ((p) >= 11 && (p) <= 22) #define IS_PIN_ANALOG(p) ((p) >= 11 && (p) <= 22)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 5 || (p) == 6)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11) #define PIN_TO_ANALOG(p) (((p)<22)?21-(p):11)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -217,7 +234,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS) #define IS_PIN_ANALOG(p) ((p) >= 38 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 0 || (p) == 1)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 38) #define PIN_TO_ANALOG(p) ((p) - 38)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -233,7 +250,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS) #define IS_PIN_ANALOG(p) ((p) >= 24 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 16 || (p) == 17)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 24) #define PIN_TO_ANALOG(p) ((p) - 24)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -249,7 +266,7 @@ writePort(port, value, bitmask): Write an 8 bit port.
#define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS) #define IS_PIN_ANALOG(p) ((p) >= 36 && (p) < TOTAL_PINS)
#define IS_PIN_PWM(p) IS_PIN_DIGITAL(p) #define IS_PIN_PWM(p) IS_PIN_DIGITAL(p)
#define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS) #define IS_PIN_SERVO(p) ((p) >= 0 && (p) < MAX_SERVOS)
#define IS_PIN_I2C(p) (0) #define IS_PIN_I2C(p) ((p) == 4 || (p) == 5)
#define PIN_TO_DIGITAL(p) (p) #define PIN_TO_DIGITAL(p) (p)
#define PIN_TO_ANALOG(p) ((p) - 36) #define PIN_TO_ANALOG(p) ((p) - 36)
#define PIN_TO_PWM(p) PIN_TO_DIGITAL(p) #define PIN_TO_PWM(p) PIN_TO_DIGITAL(p)
@ -270,9 +287,9 @@ static inline unsigned char readPort(byte, byte) __attribute__((always_inline, u
static inline unsigned char readPort(byte port, byte bitmask) static inline unsigned char readPort(byte port, byte bitmask)
{ {
#if defined(ARDUINO_PINOUT_OPTIMIZE) #if defined(ARDUINO_PINOUT_OPTIMIZE)
if (port == 0) return PIND & B11111100 & bitmask; // ignore Rx/Tx 0/1 if (port == 0) return (PIND & 0xFC) & bitmask; // ignore Rx/Tx 0/1
if (port == 1) return PINB & B00111111 & bitmask; // pins 8-13 (14,15 are disabled for the crystal) if (port == 1) return ((PINB & 0x3F) | ((PINC & 0x03) << 6)) & bitmask;
if (port == 2) return PINC & bitmask; if (port == 2) return ((PINC & 0x3C) >> 2) & bitmask;
return 0; return 0;
#else #else
unsigned char out=0, pin=port*8; unsigned char out=0, pin=port*8;
@ -297,17 +314,27 @@ static inline unsigned char writePort(byte port, byte value, byte bitmask)
{ {
#if defined(ARDUINO_PINOUT_OPTIMIZE) #if defined(ARDUINO_PINOUT_OPTIMIZE)
if (port == 0) { if (port == 0) {
bitmask = bitmask & 0xFC; // Tx & Rx pins bitmask = bitmask & 0xFC; // do not touch Tx & Rx pins
byte valD = value & bitmask;
byte maskD = ~bitmask;
cli(); cli();
PORTD = (PORTD & ~bitmask) | (bitmask & value); PORTD = (PORTD & maskD) | valD;
sei(); sei();
} else if (port == 1) { } else if (port == 1) {
byte valB = (value & bitmask) & 0x3F;
byte valC = (value & bitmask) >> 6;
byte maskB = ~(bitmask & 0x3F);
byte maskC = ~((bitmask & 0xC0) >> 6);
cli(); cli();
PORTB = (PORTB & ~bitmask) | (bitmask & value); PORTB = (PORTB & maskB) | valB;
PORTC = (PORTC & maskC) | valC;
sei(); sei();
} else if (port == 2) { } else if (port == 2) {
bitmask = bitmask & 0x0F;
byte valC = (value & bitmask) << 2;
byte maskC = ~(bitmask << 2);
cli(); cli();
PORTC = (PORTC & ~bitmask) | (bitmask & value); PORTC = (PORTC & maskC) | valC;
sei(); sei();
} }
#else #else

View File

@ -14,9 +14,8 @@
//* Includes //* Includes
//****************************************************************************** //******************************************************************************
#include "Arduino.h"
#include "HardwareSerial.h"
#include "Firmata.h" #include "Firmata.h"
#include "HardwareSerial.h"
extern "C" { extern "C" {
#include <string.h> #include <string.h>
@ -27,27 +26,27 @@ extern "C" {
//* Support Functions //* Support Functions
//****************************************************************************** //******************************************************************************
void sendValueAsTwo7bitBytes(int value) void FirmataClass::sendValueAsTwo7bitBytes(int value)
{ {
Serial.print(value & B01111111, BYTE); // LSB FirmataSerial.write(value & B01111111); // LSB
Serial.print(value >> 7 & B01111111, BYTE); // MSB FirmataSerial.write(value >> 7 & B01111111); // MSB
} }
void startSysex(void) void FirmataClass::startSysex(void)
{ {
Serial.print(START_SYSEX, BYTE); FirmataSerial.write(START_SYSEX);
} }
void endSysex(void) void FirmataClass::endSysex(void)
{ {
Serial.print(END_SYSEX, BYTE); FirmataSerial.write(END_SYSEX);
} }
//****************************************************************************** //******************************************************************************
//* Constructors //* Constructors
//****************************************************************************** //******************************************************************************
FirmataClass::FirmataClass(void) FirmataClass::FirmataClass(Stream &s) : FirmataSerial(s)
{ {
firmwareVersionCount = 0; firmwareVersionCount = 0;
systemReset(); systemReset();
@ -66,22 +65,27 @@ void FirmataClass::begin(void)
/* begin method for overriding default serial bitrate */ /* begin method for overriding default serial bitrate */
void FirmataClass::begin(long speed) void FirmataClass::begin(long speed)
{ {
#if defined(__AVR_ATmega128__) // Wiring
Serial.begin((uint32_t)speed);
#else
Serial.begin(speed); Serial.begin(speed);
#endif FirmataSerial = Serial;
blinkVersion(); blinkVersion();
delay(300); delay(300);
printVersion(); printVersion();
printFirmwareVersion(); printFirmwareVersion();
} }
void FirmataClass::begin(Stream &s)
{
FirmataSerial = s;
systemReset();
printVersion();
printFirmwareVersion();
}
// output the protocol version message to the serial port // output the protocol version message to the serial port
void FirmataClass::printVersion(void) { void FirmataClass::printVersion(void) {
Serial.print(REPORT_VERSION, BYTE); FirmataSerial.write(REPORT_VERSION);
Serial.print(FIRMATA_MAJOR_VERSION, BYTE); FirmataSerial.write(FIRMATA_MAJOR_VERSION);
Serial.print(FIRMATA_MINOR_VERSION, BYTE); FirmataSerial.write(FIRMATA_MINOR_VERSION);
} }
void FirmataClass::blinkVersion(void) void FirmataClass::blinkVersion(void)
@ -101,9 +105,9 @@ void FirmataClass::printFirmwareVersion(void)
if(firmwareVersionCount) { // make sure that the name has been set before reporting if(firmwareVersionCount) { // make sure that the name has been set before reporting
startSysex(); startSysex();
Serial.print(REPORT_FIRMWARE, BYTE); FirmataSerial.write(REPORT_FIRMWARE);
Serial.print(firmwareVersionVector[0]); // major version number FirmataSerial.write(firmwareVersionVector[0]); // major version number
Serial.print(firmwareVersionVector[1]); // minor version number FirmataSerial.write(firmwareVersionVector[1]); // minor version number
for(i=2; i<firmwareVersionCount; ++i) { for(i=2; i<firmwareVersionCount; ++i) {
sendValueAsTwo7bitBytes(firmwareVersionVector[i]); sendValueAsTwo7bitBytes(firmwareVersionVector[i]);
} }
@ -141,7 +145,7 @@ void FirmataClass::setFirmwareNameAndVersion(const char *name, byte major, byte
int FirmataClass::available(void) int FirmataClass::available(void)
{ {
return Serial.available(); return FirmataSerial.available();
} }
@ -175,7 +179,7 @@ void FirmataClass::processSysexMessage(void)
void FirmataClass::processInput(void) void FirmataClass::processInput(void)
{ {
int inputData = Serial.read(); // this is 'int' to handle -1 when no data int inputData = FirmataSerial.read(); // this is 'int' to handle -1 when no data
int command; int command;
// TODO make sure it handles -1 properly // TODO make sure it handles -1 properly
@ -267,7 +271,7 @@ void FirmataClass::processInput(void)
void FirmataClass::sendAnalog(byte pin, int value) void FirmataClass::sendAnalog(byte pin, int value)
{ {
// pin can only be 0-15, so chop higher bits // pin can only be 0-15, so chop higher bits
Serial.print(ANALOG_MESSAGE | (pin & 0xF), BYTE); FirmataSerial.write(ANALOG_MESSAGE | (pin & 0xF));
sendValueAsTwo7bitBytes(value); sendValueAsTwo7bitBytes(value);
} }
@ -298,9 +302,9 @@ void FirmataClass::sendDigital(byte pin, int value)
// send an 8-bit port in a single digital message (protocol v2) // send an 8-bit port in a single digital message (protocol v2)
void FirmataClass::sendDigitalPort(byte portNumber, int portData) void FirmataClass::sendDigitalPort(byte portNumber, int portData)
{ {
Serial.print(DIGITAL_MESSAGE | (portNumber & 0xF),BYTE); FirmataSerial.write(DIGITAL_MESSAGE | (portNumber & 0xF));
Serial.print((byte)portData % 128, BYTE); // Tx bits 0-6 FirmataSerial.write((byte)portData % 128); // Tx bits 0-6
Serial.print(portData >> 7, BYTE); // Tx bits 7-13 FirmataSerial.write(portData >> 7); // Tx bits 7-13
} }
@ -308,7 +312,7 @@ void FirmataClass::sendSysex(byte command, byte bytec, byte* bytev)
{ {
byte i; byte i;
startSysex(); startSysex();
Serial.print(command, BYTE); FirmataSerial.write(command);
for(i=0; i<bytec; i++) { for(i=0; i<bytec; i++) {
sendValueAsTwo7bitBytes(bytev[i]); sendValueAsTwo7bitBytes(bytev[i]);
} }
@ -437,6 +441,6 @@ void FirmataClass::pin13strobe(int count, int onInterval, int offInterval)
// make one instance for the user to use // make one instance for the user to use
FirmataClass Firmata; FirmataClass Firmata(Serial);

View File

@ -13,16 +13,15 @@
#ifndef Firmata_h #ifndef Firmata_h
#define Firmata_h #define Firmata_h
#include <Arduino.h> #include "Boards.h" /* Hardware Abstraction Layer + Wiring/Arduino */
#include <inttypes.h>
/* Version numbers for the protocol. The protocol is still changing, so these /* Version numbers for the protocol. The protocol is still changing, so these
* version numbers are important. This number can be queried so that host * version numbers are important. This number can be queried so that host
* software can test whether it will be compatible with the currently * software can test whether it will be compatible with the currently
* installed firmware. */ * installed firmware. */
#define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes #define FIRMATA_MAJOR_VERSION 2 // for non-compatible changes
#define FIRMATA_MINOR_VERSION 2 // for backwards compatible changes #define FIRMATA_MINOR_VERSION 3 // for backwards compatible changes
#define FIRMATA_BUGFIX_VERSION 1 // for bugfix releases
#define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages #define MAX_DATA_BYTES 32 // max number of data bytes in non-Sysex messages
@ -66,8 +65,8 @@
#define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL #define SYSEX_SAMPLING_INTERVAL 0x7A // same as SAMPLING_INTERVAL
// pin modes // pin modes
//#define INPUT 0x00 // defined in Arduino.h //#define INPUT 0x00 // defined in wiring.h
//#define OUTPUT 0x01 // defined in Arduino.h //#define OUTPUT 0x01 // defined in wiring.h
#define ANALOG 0x02 // analog pin in analogInput mode #define ANALOG 0x02 // analog pin in analogInput mode
#define PWM 0x03 // digital pin in PWM output mode #define PWM 0x03 // digital pin in PWM output mode
#define SERVO 0x04 // digital pin in Servo output mode #define SERVO 0x04 // digital pin in Servo output mode
@ -88,10 +87,11 @@ extern "C" {
class FirmataClass class FirmataClass
{ {
public: public:
FirmataClass(); FirmataClass(Stream &s);
/* Arduino constructors */ /* Arduino constructors */
void begin(); void begin();
void begin(long); void begin(long);
void begin(Stream &s);
/* querying functions */ /* querying functions */
void printVersion(void); void printVersion(void);
void blinkVersion(void); void blinkVersion(void);
@ -116,6 +116,7 @@ public:
void detach(byte command); void detach(byte command);
private: private:
Stream &FirmataSerial;
/* firmware name and version */ /* firmware name and version */
byte firmwareVersionCount; byte firmwareVersionCount;
byte *firmwareVersionVector; byte *firmwareVersionVector;
@ -141,6 +142,9 @@ private:
void processSysexMessage(void); void processSysexMessage(void);
void systemReset(void); void systemReset(void);
void pin13strobe(int count, int onInterval, int offInterval); void pin13strobe(int count, int onInterval, int offInterval);
void sendValueAsTwo7bitBytes(int value);
void startSysex(void);
void endSysex(void);
}; };
extern FirmataClass Firmata; extern FirmataClass Firmata;
@ -155,8 +159,5 @@ extern FirmataClass Firmata;
*/ */
#define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y) #define setFirmwareVersion(x, y) setFirmwareNameAndVersion(__FILE__, x, y)
/* Hardware Abstraction Layer */
#include "Boards.h"
#endif /* Firmata_h */ #endif /* Firmata_h */

View File

@ -56,7 +56,7 @@ void loop()
byte i; byte i;
for (i=0; i<TOTAL_PORTS; i++) { for (i=0; i<TOTAL_PORTS; i++) {
sendPort(i, readPort(i)); sendPort(i, readPort(i, 0xff));
} }
/* make sure that the FTDI buffer doesn't go over 60 bytes, otherwise you /* make sure that the FTDI buffer doesn't go over 60 bytes, otherwise you
get long, random delays. So only read analogs every 20ms or so */ get long, random delays. So only read analogs every 20ms or so */

View File

@ -1,263 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h

View File

@ -14,12 +14,7 @@ void stringCallback(char *myString)
void sysexCallback(byte command, byte argc, byte*argv) void sysexCallback(byte command, byte argc, byte*argv)
{ {
Serial.write(START_SYSEX); Firmata.sendSysex(command, argc, argv);
Serial.write(command);
for(byte i=0; i<argc; i++) {
Serial.write(argv[i]);
}
Serial.write(END_SYSEX);
} }
void setup() void setup()

View File

@ -1,263 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h

View File

@ -48,7 +48,7 @@ void readAndReportData(byte address, int theRegister, byte numBytes)
{ {
if (theRegister != REGISTER_NOT_SPECIFIED) { if (theRegister != REGISTER_NOT_SPECIFIED) {
Wire.beginTransmission(address); Wire.beginTransmission(address);
Wire.send((byte)theRegister); Wire.write((byte)theRegister);
Wire.endTransmission(); Wire.endTransmission();
delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck delayMicroseconds(i2cReadDelayTime); // delay is necessary for some devices such as WiiNunchuck
} }
@ -63,7 +63,7 @@ void readAndReportData(byte address, int theRegister, byte numBytes)
i2cRxData[0] = address; i2cRxData[0] = address;
i2cRxData[1] = theRegister; i2cRxData[1] = theRegister;
for (int i = 0; i < numBytes; i++) { for (int i = 0; i < numBytes; i++) {
i2cRxData[2 + i] = Wire.receive(); i2cRxData[2 + i] = Wire.read();
} }
// send slave address, register and received bytes // send slave address, register and received bytes
Firmata.sendSysex(I2C_REPLY, numBytes + 2, i2cRxData); Firmata.sendSysex(I2C_REPLY, numBytes + 2, i2cRxData);
@ -95,7 +95,7 @@ void sysexCallback(byte command, byte argc, byte *argv)
Wire.beginTransmission(slaveAddress); Wire.beginTransmission(slaveAddress);
for (byte i = 2; i < argc; i += 2) { for (byte i = 2; i < argc; i += 2) {
data = argv[i] + (argv[i + 1] << 7); data = argv[i] + (argv[i + 1] << 7);
Wire.send(data); Wire.write(data);
} }
Wire.endTransmission(); Wire.endTransmission();
delayMicroseconds(70); // TODO is this needed? delayMicroseconds(70); // TODO is this needed?

View File

@ -1,263 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h

View File

@ -1,263 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h

View File

@ -1,263 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
CC = avr-gcc
CXX = avr-g++
OBJCOPY = avr-objcopy
OBJDUMP = avr-objdump
SIZE = avr-size
NM = avr-nm
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h

View File

@ -52,7 +52,7 @@ void loop()
byte i; byte i;
for (i=0; i<TOTAL_PORTS; i++) { for (i=0; i<TOTAL_PORTS; i++) {
outputPort(i, readPort(i)); outputPort(i, readPort(i, 0xff));
} }
while(Firmata.available()) { while(Firmata.available()) {

View File

@ -1,273 +0,0 @@
# Arduino makefile
#
# This makefile allows you to build sketches from the command line
# without the Arduino environment (or Java).
#
# The Arduino environment does preliminary processing on a sketch before
# compiling it. If you're using this makefile instead, you'll need to do
# a few things differently:
#
# - Give your program's file a .cpp extension (e.g. foo.cpp).
#
# - Put this line at top of your code: #include <WProgram.h>
#
# - Write prototypes for all your functions (or define them before you
# call them). A prototype declares the types of parameters a
# function will take and what type of value it will return. This
# means that you can have a call to a function before the definition
# of the function. A function prototype looks like the first line of
# the function, with a semi-colon at the end. For example:
# int digitalRead(int pin);
#
# Instructions for using the makefile:
#
# 1. Copy this file into the folder with your sketch.
#
# 2. Below, modify the line containing "TARGET" to refer to the name of
# of your program's file without an extension (e.g. TARGET = foo).
#
# 3. Modify the line containg "ARDUINO" to point the directory that
# contains the Arduino core (for normal Arduino installations, this
# is the hardware/cores/arduino sub-directory).
#
# 4. Modify the line containing "PORT" to refer to the filename
# representing the USB or serial connection to your Arduino board
# (e.g. PORT = /dev/tty.USB0). If the exact name of this file
# changes, you can use * as a wildcard (e.g. PORT = /dev/tty.USB*).
#
# 5. At the command line, change to the directory containing your
# program's file and the makefile.
#
# 6. Type "make" and press enter to compile/verify your program.
#
# 7. Type "make upload", reset your Arduino board, and press enter to
# upload your program to the Arduino board.
#
# $Id: Makefile,v 1.7 2007/04/13 05:28:23 eighthave Exp $
PORT = /dev/tty.usbserial-*
TARGET := $(shell pwd | sed 's|.*/\(.*\)|\1|')
ARDUINO = /Applications/arduino
ARDUINO_SRC = $(ARDUINO)/hardware/cores/arduino
ARDUINO_LIB_SRC = $(ARDUINO)/hardware/libraries
ARDUINO_TOOLS = $(ARDUINO)/hardware/tools
INCLUDE = -I$(ARDUINO_SRC) -I$(ARDUINO)/hardware/tools/avr/avr/include \
-I$(ARDUINO_LIB_SRC)/EEPROM \
-I$(ARDUINO_LIB_SRC)/Firmata \
-I$(ARDUINO_LIB_SRC)/Matrix \
-I$(ARDUINO_LIB_SRC)/Servo \
-I$(ARDUINO_LIB_SRC)/Wire \
-I$(ARDUINO_LIB_SRC)
SRC = $(wildcard $(ARDUINO_SRC)/*.c)
CXXSRC = applet/$(TARGET).cpp $(ARDUINO_SRC)/HardwareSerial.cpp \
$(ARDUINO_LIB_SRC)/EEPROM/EEPROM.cpp \
$(ARDUINO_LIB_SRC)/Firmata/Firmata.cpp \
$(ARDUINO_LIB_SRC)/Servo/Servo.cpp \
$(ARDUINO_SRC)/Print.cpp \
$(ARDUINO_SRC)/WMath.cpp
HEADERS = $(wildcard $(ARDUINO_SRC)/*.h) $(wildcard $(ARDUINO_LIB_SRC)/*/*.h)
MCU = atmega168
#MCU = atmega8
F_CPU = 16000000
FORMAT = ihex
UPLOAD_RATE = 19200
# Name of this Makefile (used for "make depend").
MAKEFILE = Makefile
# Debugging format.
# Native formats for AVR-GCC's -g are stabs [default], or dwarf-2.
# AVR (extended) COFF requires stabs, plus an avr-objcopy run.
DEBUG = stabs
OPT = s
# Place -D or -U options here
CDEFS = -DF_CPU=$(F_CPU)
CXXDEFS = -DF_CPU=$(F_CPU)
# Compiler flag to set the C Standard level.
# c89 - "ANSI" C
# gnu89 - c89 plus GCC extensions
# c99 - ISO C99 standard (not yet fully implemented)
# gnu99 - c99 plus GCC extensions
CSTANDARD = -std=gnu99
CDEBUG = -g$(DEBUG)
CWARN = -Wall -Wstrict-prototypes
CTUNING = -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums
#CEXTRA = -Wa,-adhlns=$(<:.c=.lst)
CFLAGS = $(CDEBUG) $(CDEFS) $(INCLUDE) -O$(OPT) $(CWARN) $(CSTANDARD) $(CEXTRA)
CXXFLAGS = $(CDEFS) $(INCLUDE) -O$(OPT)
#ASFLAGS = -Wa,-adhlns=$(<:.S=.lst),-gstabs
LDFLAGS =
# Programming support using avrdude. Settings and variables.
AVRDUDE_PROGRAMMER = stk500
AVRDUDE_PORT = $(PORT)
AVRDUDE_WRITE_FLASH = -U flash:w:applet/$(TARGET).hex
AVRDUDE_FLAGS = -F -p $(MCU) -P $(AVRDUDE_PORT) -c $(AVRDUDE_PROGRAMMER) \
-b $(UPLOAD_RATE) -q -V
# Program settings
ARDUINO_AVR_BIN = $(ARDUINO_TOOLS)/avr/bin
CC = $(ARDUINO_AVR_BIN)/avr-gcc
CXX = $(ARDUINO_AVR_BIN)/avr-g++
OBJCOPY = $(ARDUINO_AVR_BIN)/avr-objcopy
OBJDUMP = $(ARDUINO_AVR_BIN)/avr-objdump
SIZE = $(ARDUINO_AVR_BIN)/avr-size
NM = $(ARDUINO_AVR_BIN)/avr-nm
#AVRDUDE = $(ARDUINO_AVR_BIN)/avrdude
AVRDUDE = avrdude
REMOVE = rm -f
MV = mv -f
# Define all object files.
OBJ = $(SRC:.c=.o) $(CXXSRC:.cpp=.o) $(ASRC:.S=.o)
# Define all listing files.
LST = $(ASRC:.S=.lst) $(CXXSRC:.cpp=.lst) $(SRC:.c=.lst)
# Combine all necessary flags and optional flags.
# Add target processor to flags.
ALL_CFLAGS = -mmcu=$(MCU) -I. $(CFLAGS)
ALL_CXXFLAGS = -mmcu=$(MCU) -I. $(CXXFLAGS)
ALL_ASFLAGS = -mmcu=$(MCU) -I. -x assembler-with-cpp $(ASFLAGS)
# Default target.
all: build
build: applet/$(TARGET).hex
eep: applet/$(TARGET).eep
lss: applet/$(TARGET).lss
sym: applet/$(TARGET).sym
# Convert ELF to COFF for use in debugging / simulating in AVR Studio or VMLAB.
COFFCONVERT=$(OBJCOPY) --debugging \
--change-section-address .data-0x800000 \
--change-section-address .bss-0x800000 \
--change-section-address .noinit-0x800000 \
--change-section-address .eeprom-0x810000
coff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-avr applet/$(TARGET).elf applet/$(TARGET).cof
extcoff: applet/$(TARGET).elf
$(COFFCONVERT) -O coff-ext-avr applet/$(TARGET).elf applet/$(TARGET).cof
.SUFFIXES: .elf .hex .eep .lss .sym .pde
.elf.hex:
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
.elf.eep:
-$(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" \
--change-section-lma .eeprom=0 -O $(FORMAT) $< $@
# Create extended listing file from ELF output file.
.elf.lss:
$(OBJDUMP) -h -S $< > $@
# Create a symbol table from ELF output file.
.elf.sym:
$(NM) -n $< > $@
# Compile: create object files from C++ source files.
.cpp.o: $(HEADERS)
$(CXX) -c $(ALL_CXXFLAGS) $< -o $@
# Compile: create object files from C source files.
.c.o: $(HEADERS)
$(CC) -c $(ALL_CFLAGS) $< -o $@
# Compile: create assembler files from C source files.
.c.s:
$(CC) -S $(ALL_CFLAGS) $< -o $@
# Assemble: create object files from assembler source files.
.S.o:
$(CC) -c $(ALL_ASFLAGS) $< -o $@
applet/$(TARGET).cpp: $(TARGET).pde
test -d applet || mkdir applet
echo '#include "WProgram.h"' > applet/$(TARGET).cpp
echo '#include "avr/interrupt.h"' >> applet/$(TARGET).cpp
sed -n 's|^\(void .*)\).*|\1;|p' $(TARGET).pde | grep -v 'setup()' | \
grep -v 'loop()' >> applet/$(TARGET).cpp
cat $(TARGET).pde >> applet/$(TARGET).cpp
cat $(ARDUINO_SRC)/main.cxx >> applet/$(TARGET).cpp
# Link: create ELF output file from object files.
applet/$(TARGET).elf: applet/$(TARGET).cpp $(OBJ)
$(CC) $(ALL_CFLAGS) $(OBJ) -lm --output $@ $(LDFLAGS)
# $(CC) $(ALL_CFLAGS) $(OBJ) $(ARDUINO_TOOLS)/avr/avr/lib/avr5/crtm168.o --output $@ $(LDFLAGS)
pd_close_serial:
echo 'close;' | /Applications/Pd-extended.app/Contents/Resources/bin/pdsend 34567 || true
# Program the device.
upload: applet/$(TARGET).hex
$(AVRDUDE) $(AVRDUDE_FLAGS) $(AVRDUDE_WRITE_FLASH)
pd_test: build pd_close_serial upload
# Target: clean project.
clean:
$(REMOVE) -- applet/$(TARGET).hex applet/$(TARGET).eep \
applet/$(TARGET).cof applet/$(TARGET).elf $(TARGET).map \
applet/$(TARGET).sym applet/$(TARGET).lss applet/$(TARGET).cpp \
$(OBJ) $(LST) $(SRC:.c=.s) $(SRC:.c=.d) $(CXXSRC:.cpp=.s) $(CXXSRC:.cpp=.d)
rmdir -- applet
depend:
if grep '^# DO NOT DELETE' $(MAKEFILE) >/dev/null; \
then \
sed -e '/^# DO NOT DELETE/,$$d' $(MAKEFILE) > \
$(MAKEFILE).$$$$ && \
$(MV) $(MAKEFILE).$$$$ $(MAKEFILE); \
fi
echo '# DO NOT DELETE THIS LINE -- make depend depends on it.' \
>> $(MAKEFILE); \
$(CC) -M -mmcu=$(MCU) $(CDEFS) $(INCLUDE) $(SRC) $(ASRC) >> $(MAKEFILE)
.PHONY: all build eep lss sym coff extcoff clean depend pd_close_serial pd_test
# for emacs
etags:
make etags_`uname -s`
etags *.pde \
$(ARDUINO_SRC)/*.[ch] \
$(ARDUINO_SRC)/*.cpp \
$(ARDUINO_LIB_SRC)/*/*.[ch] \
$(ARDUINO_LIB_SRC)/*/*.cpp \
$(ARDUINO)/hardware/tools/avr/avr/include/avr/*.[ch] \
$(ARDUINO)/hardware/tools/avr/avr/include/*.[ch]
etags_Darwin:
# etags -a
etags_Linux:
# etags -a /usr/include/*.h linux/input.h /usr/include/sys/*.h
etags_MINGW:
# etags -a /usr/include/*.h /usr/include/sys/*.h
path:
echo $(PATH)
echo $$PATH

View File

@ -323,7 +323,7 @@ void setup()
{ {
byte i; byte i;
Firmata.setFirmwareVersion(2, 2); Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback); Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback); Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);

View File

@ -1,436 +0,0 @@
/*
This introduces modifications on the normal Firmata made for Arduino so that the LED
blinks until receiving the first command over serial.
Copyright (C) 2010 David Cuartielles. All rights reserved.
based at 99.9% on Firmata by HC Steiner according to the following license terms:
Copyright (C) 2006-2008 Hans-Christoph Steiner. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
See file LICENSE.txt for further informations on licensing terms.
formatted using the GNU C formatting and indenting
*/
/*
* TODO: use Program Control to load stored profiles from EEPROM
*/
#include <Servo.h>
#include <Firmata.h>
/*==============================================================================
* GLOBAL VARIABLES
*============================================================================*/
/* has the command arrived? */
boolean firstCommand = false;
int dataOnSerial = 0;
boolean statusLed = false;
/* analog inputs */
int analogInputsToReport = 0; // bitwise array to store pin reporting
/* digital input ports */
byte reportPINs[TOTAL_PORTS]; // 1 = report this port, 0 = silence
byte previousPINs[TOTAL_PORTS]; // previous 8 bits sent
/* pins configuration */
byte pinConfig[TOTAL_PINS]; // configuration of every pin
byte portConfigInputs[TOTAL_PORTS]; // each bit: 1 = pin in INPUT, 0 = anything else
int pinState[TOTAL_PINS]; // any value that has been written
/* timer variables */
unsigned long currentMillis; // store the current value from millis()
unsigned long previousMillis; // for comparison with currentMillis
int samplingInterval = 19; // how often to run the main loop (in ms)
unsigned long toggleMillis;
Servo servos[MAX_SERVOS];
/*==============================================================================
* FUNCTIONS
*============================================================================*/
void toggleLed()
{
if (millis() - toggleMillis > 500) {
statusLed = !statusLed;
digitalWrite(13, statusLed);
toggleMillis = millis();
}
}
void outputPort(byte portNumber, byte portValue, byte forceSend)
{
// pins not configured as INPUT are cleared to zeros
portValue = portValue & portConfigInputs[portNumber];
// only send if the value is different than previously sent
if(forceSend || previousPINs[portNumber] != portValue) {
Firmata.sendDigitalPort(portNumber, portValue);
previousPINs[portNumber] = portValue;
}
}
/* -----------------------------------------------------------------------------
* check all the active digital inputs for change of state, then add any events
* to the Serial output queue using Serial.print() */
void checkDigitalInputs(void)
{
/* Using non-looping code allows constants to be given to readPort().
* The compiler will apply substantial optimizations if the inputs
* to readPort() are compile-time constants. */
if (TOTAL_PORTS > 0 && reportPINs[0]) outputPort(0, readPort(0, portConfigInputs[0]), false);
if (TOTAL_PORTS > 1 && reportPINs[1]) outputPort(1, readPort(1, portConfigInputs[1]), false);
if (TOTAL_PORTS > 2 && reportPINs[2]) outputPort(2, readPort(2, portConfigInputs[2]), false);
if (TOTAL_PORTS > 3 && reportPINs[3]) outputPort(3, readPort(3, portConfigInputs[3]), false);
if (TOTAL_PORTS > 4 && reportPINs[4]) outputPort(4, readPort(4, portConfigInputs[4]), false);
if (TOTAL_PORTS > 5 && reportPINs[5]) outputPort(5, readPort(5, portConfigInputs[5]), false);
if (TOTAL_PORTS > 6 && reportPINs[6]) outputPort(6, readPort(6, portConfigInputs[6]), false);
if (TOTAL_PORTS > 7 && reportPINs[7]) outputPort(7, readPort(7, portConfigInputs[7]), false);
if (TOTAL_PORTS > 8 && reportPINs[8]) outputPort(8, readPort(8, portConfigInputs[8]), false);
if (TOTAL_PORTS > 9 && reportPINs[9]) outputPort(9, readPort(9, portConfigInputs[9]), false);
if (TOTAL_PORTS > 10 && reportPINs[10]) outputPort(10, readPort(10, portConfigInputs[10]), false);
if (TOTAL_PORTS > 11 && reportPINs[11]) outputPort(11, readPort(11, portConfigInputs[11]), false);
if (TOTAL_PORTS > 12 && reportPINs[12]) outputPort(12, readPort(12, portConfigInputs[12]), false);
if (TOTAL_PORTS > 13 && reportPINs[13]) outputPort(13, readPort(13, portConfigInputs[13]), false);
if (TOTAL_PORTS > 14 && reportPINs[14]) outputPort(14, readPort(14, portConfigInputs[14]), false);
if (TOTAL_PORTS > 15 && reportPINs[15]) outputPort(15, readPort(15, portConfigInputs[15]), false);
}
// -----------------------------------------------------------------------------
/* sets the pin mode to the correct state and sets the relevant bits in the
* two bit-arrays that track Digital I/O and PWM status
*/
void setPinModeCallback(byte pin, int mode)
{
if (IS_PIN_SERVO(pin) && mode != SERVO && servos[PIN_TO_SERVO(pin)].attached()) {
servos[PIN_TO_SERVO(pin)].detach();
}
if (IS_PIN_ANALOG(pin)) {
reportAnalogCallback(PIN_TO_ANALOG(pin), mode == ANALOG ? 1 : 0); // turn on/off reporting
}
if (IS_PIN_DIGITAL(pin)) {
if (mode == INPUT) {
portConfigInputs[pin/8] |= (1 << (pin & 7));
} else {
portConfigInputs[pin/8] &= ~(1 << (pin & 7));
}
}
pinState[pin] = 0;
switch(mode) {
case ANALOG:
if (IS_PIN_ANALOG(pin)) {
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
}
pinConfig[pin] = ANALOG;
}
break;
case INPUT:
if (IS_PIN_DIGITAL(pin)) {
pinMode(PIN_TO_DIGITAL(pin), INPUT); // disable output driver
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable internal pull-ups
pinConfig[pin] = INPUT;
}
break;
case OUTPUT:
if (IS_PIN_DIGITAL(pin)) {
digitalWrite(PIN_TO_DIGITAL(pin), LOW); // disable PWM
pinMode(PIN_TO_DIGITAL(pin), OUTPUT);
pinConfig[pin] = OUTPUT;
}
break;
case PWM:
if (IS_PIN_PWM(pin)) {
pinMode(PIN_TO_PWM(pin), OUTPUT);
analogWrite(PIN_TO_PWM(pin), 0);
pinConfig[pin] = PWM;
}
break;
case SERVO:
if (IS_PIN_SERVO(pin)) {
pinConfig[pin] = SERVO;
if (!servos[PIN_TO_SERVO(pin)].attached()) {
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin));
} else {
Firmata.sendString("Servo only on pins from 2 to 13");
}
}
break;
case I2C:
pinConfig[pin] = mode;
Firmata.sendString("I2C mode not yet supported");
break;
default:
Firmata.sendString("Unknown pin mode"); // TODO: put error msgs in EEPROM
}
// TODO: save status to EEPROM here, if changed
}
void analogWriteCallback(byte pin, int value)
{
if (pin < TOTAL_PINS) {
switch(pinConfig[pin]) {
case SERVO:
if (IS_PIN_SERVO(pin))
servos[PIN_TO_SERVO(pin)].write(value);
pinState[pin] = value;
break;
case PWM:
if (IS_PIN_PWM(pin))
analogWrite(PIN_TO_PWM(pin), value);
pinState[pin] = value;
break;
}
}
}
void digitalWriteCallback(byte port, int value)
{
byte pin, lastPin, mask=1, pinWriteMask=0;
if (port < TOTAL_PORTS) {
// create a mask of the pins on this port that are writable.
lastPin = port*8+8;
if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
for (pin=port*8; pin < lastPin; pin++) {
// do not disturb non-digital pins (eg, Rx & Tx)
if (IS_PIN_DIGITAL(pin)) {
// only write to OUTPUT and INPUT (enables pullup)
// do not touch pins in PWM, ANALOG, SERVO or other modes
if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
pinWriteMask |= mask;
pinState[pin] = ((byte)value & mask) ? 1 : 0;
}
}
mask = mask << 1;
}
writePort(port, (byte)value, pinWriteMask);
}
}
// -----------------------------------------------------------------------------
/* sets bits in a bit array (int) to toggle the reporting of the analogIns
*/
//void FirmataClass::setAnalogPinReporting(byte pin, byte state) {
//}
void reportAnalogCallback(byte analogPin, int value)
{
if (analogPin < TOTAL_ANALOG_PINS) {
if(value == 0) {
analogInputsToReport = analogInputsToReport &~ (1 << analogPin);
} else {
analogInputsToReport = analogInputsToReport | (1 << analogPin);
}
}
// TODO: save status to EEPROM here, if changed
}
void reportDigitalCallback(byte port, int value)
{
if (port < TOTAL_PORTS) {
reportPINs[port] = (byte)value;
}
// do not disable analog reporting on these 8 pins, to allow some
// pins used for digital, others analog. Instead, allow both types
// of reporting to be enabled, but check if the pin is configured
// as analog when sampling the analog inputs. Likewise, while
// scanning digital pins, portConfigInputs will mask off values from any
// pins configured as analog
}
/*==============================================================================
* SYSEX-BASED commands
*============================================================================*/
void sysexCallback(byte command, byte argc, byte *argv)
{
switch(command) {
case SERVO_CONFIG:
if(argc > 4) {
// these vars are here for clarity, they'll optimized away by the compiler
byte pin = argv[0];
int minPulse = argv[1] + (argv[2] << 7);
int maxPulse = argv[3] + (argv[4] << 7);
if (IS_PIN_SERVO(pin)) {
// servos are pins from 2 to 13, so offset for array
if (servos[PIN_TO_SERVO(pin)].attached())
servos[PIN_TO_SERVO(pin)].detach();
servos[PIN_TO_SERVO(pin)].attach(PIN_TO_DIGITAL(pin), minPulse, maxPulse);
setPinModeCallback(pin, SERVO);
}
}
break;
case SAMPLING_INTERVAL:
if (argc > 1)
samplingInterval = argv[0] + (argv[1] << 7);
else
Firmata.sendString("Not enough data");
break;
case EXTENDED_ANALOG:
if (argc > 1) {
int val = argv[1];
if (argc > 2) val |= (argv[2] << 7);
if (argc > 3) val |= (argv[3] << 14);
analogWriteCallback(argv[0], val);
}
break;
case CAPABILITY_QUERY:
Serial.write(START_SYSEX);
Serial.write(CAPABILITY_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) {
if (IS_PIN_DIGITAL(pin)) {
Serial.write((byte)INPUT);
Serial.write(1);
Serial.write((byte)OUTPUT);
Serial.write(1);
}
if (IS_PIN_ANALOG(pin)) {
Serial.write(ANALOG);
Serial.write(10);
}
if (IS_PIN_PWM(pin)) {
Serial.write(PWM);
Serial.write(8);
}
if (IS_PIN_SERVO(pin)) {
Serial.write(SERVO);
Serial.write(14);
}
Serial.write(127);
}
Serial.write(END_SYSEX);
break;
case PIN_STATE_QUERY:
if (argc > 0) {
byte pin=argv[0];
Serial.write(START_SYSEX);
Serial.write(PIN_STATE_RESPONSE);
Serial.write(pin);
if (pin < TOTAL_PINS) {
Serial.write((byte)pinConfig[pin]);
Serial.write((byte)pinState[pin] & 0x7F);
if (pinState[pin] & 0xFF80) Serial.write((byte)(pinState[pin] >> 7) & 0x7F);
if (pinState[pin] & 0xC000) Serial.write((byte)(pinState[pin] >> 14) & 0x7F);
}
Serial.write(END_SYSEX);
}
break;
case ANALOG_MAPPING_QUERY:
Serial.write(START_SYSEX);
Serial.write(ANALOG_MAPPING_RESPONSE);
for (byte pin=0; pin < TOTAL_PINS; pin++) {
Serial.write(IS_PIN_ANALOG(pin) ? PIN_TO_ANALOG(pin) : 127);
}
Serial.write(END_SYSEX);
break;
}
}
/*==============================================================================
* SETUP()
*============================================================================*/
void setup()
{
byte i;
Firmata.setFirmwareVersion(2, 2);
Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
Firmata.attach(SET_PIN_MODE, setPinModeCallback);
Firmata.attach(START_SYSEX, sysexCallback);
// TODO: load state from EEPROM here
/* these are initialized to zero by the compiler startup code
for (i=0; i < TOTAL_PORTS; i++) {
reportPINs[i] = false;
portConfigInputs[i] = 0;
previousPINs[i] = 0;
}
*/
for (i=0; i < TOTAL_PINS; i++) {
if (IS_PIN_ANALOG(i)) {
// turns off pullup, configures everything
setPinModeCallback(i, ANALOG);
} else {
// sets the output to 0, configures portConfigInputs
setPinModeCallback(i, OUTPUT);
}
}
// by defult, do not report any analog inputs
analogInputsToReport = 0;
Firmata.begin(57600);
/* send digital inputs to set the initial state on the host computer,
* since once in the loop(), this firmware will only send on change */
for (i=0; i < TOTAL_PORTS; i++) {
outputPort(i, readPort(i, portConfigInputs[i]), true);
}
/* init the toggleLed counter */
toggleMillis = millis();
pinMode(13, OUTPUT);
}
/*==============================================================================
* LOOP()
*============================================================================*/
void loop()
{
byte pin, analogPin;
/* DIGITALREAD - as fast as possible, check for changes and output them to the
* FTDI buffer using Serial.print() */
checkDigitalInputs();
//XXX: hack Firmata to blink until serial command arrives
dataOnSerial = Firmata.available();
if (dataOnSerial > 0 && !firstCommand) {
firstCommand = true;
}
//XXX: do the blink if the first command hasn't arrived yet
// configures pin 13 as output and then back as input
if (!firstCommand) {
toggleLed();
}
/* SERIALREAD - processing incoming messagse as soon as possible, while still
* checking digital inputs. */
while(dataOnSerial) {
Firmata.processInput();
dataOnSerial = Firmata.available();
}
/* SEND FTDI WRITE BUFFER - make sure that the FTDI buffer doesn't go over
* 60 bytes. use a timer to sending an event character every 4 ms to
* trigger the buffer to dump. */
currentMillis = millis();
if (currentMillis - previousMillis > samplingInterval) {
previousMillis += samplingInterval;
/* ANALOGREAD - do all analogReads() at the configured sampling interval */
for(pin=0; pin<TOTAL_PINS; pin++) {
if (IS_PIN_ANALOG(pin) && pinConfig[pin] == ANALOG) {
analogPin = PIN_TO_ANALOG(pin);
if (analogInputsToReport & (1 << analogPin)) {
Firmata.sendAnalog(analogPin, analogRead(analogPin));
}
}
}
}
}