Proposals
From Firmata
This is a place to propose extensions to the Firmata protocol
Contents |
SysEx
The idea for SysEx is to have a second command space using the first byte after the SysEx Start byte. The key difference is that the data can be of any size, rather than just one or two bytes for standard MIDI messages.
#define RESERVED_COMMAND 0x00 // 2nd SysEx data byte is a chip-specific command (AVR, PIC, TI, etc). #define SERVO_CONFIG 0x70 // set max angle, minPulse, maxPulse, freq #define STRING_DATA 0x71 // a string message with 14-bits per char #define PULSE_DATA 0x74 // pulseIn/pulseOut data message (34 bits) #define SHIFT_DATA 0x75 // shiftOut config/data message (34 bits) #define I2C_REQUEST 0x76 // I2C request messages from a host to an I/O board #define I2C_REPLY 0x77 // I2C reply messages from an I/O board to a host #define I2C_CONFIG 0x78 // Configure special I2C settings such as power pins and delay times #define REPORT_FIRMWARE 0x79 // report name and version of the firmware #define SAMPLING_INTERVAL 0x7A // sampling interval #define SYSEX_NON_REALTIME 0x7E // MIDI Reserved for non-realtime messages #define SYSEX_REALTIME 0x7F // MIDI Reserved for realtime messages
Extended Analog Write
As an alternative to the normal analog write, this extended version allows addressing beyond pin 15, and supports sending analog values with any number of bits. The number of data bits is inferred by the length of the message.
/* extended analog * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 analog message (TBD) * 2 pin (0 to 127) * 3 bits 0-6 (least significant byte) * 4 bits 7-13 * ... additional bytes may be sent if more bits needed * N END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
User Friendly GUI Queries
These queries are intended to allow GUI-based programs to discover the capabilities and current state of any board running Firmata. The idea is to facilitate displaying highly accurate on-screen representation of the board.
GUI test program screenshot:
Firmata with queries (copy to your Arduino libraries directory)
http://www.pjrc.com/teensy/firmata_test/firmata_queries.zip
GUI for Linux
http://www.pjrc.com/teensy/firmata_test/firmata_test
GUI for Mac OS-X
http://www.pjrc.com/teensy/firmata_test/firmata_test.dmg
GUI for Windows
http://www.pjrc.com/teensy/firmata_test/firmata_test.exe
GUI source code
http://www.pjrc.com/teensy/firmata_test/firmata_test.tar.gz
The capabilities query provides a list of all modes supported by all pins, and the resolution used by each mode.
/* capabilities query * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 capabilities query (0x6B) * 2 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
/* capabilities response
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 capabilities response (0x73)
* 2 1st mode supported of pin 0
* 3 1st mode's resolution of pin 0
* 4 2nd mode supported of pin 0
* 5 2nd mode's resolution of pin 0
... additional modes/resolutions, followed by a single 127 to mark the
end of the first pin's modes. Each pin follows with its mode and
127, until all pins implemented.
* N END_SYSEX (0xF7)
*/
Each pin shall have 2 bytes for each supported mode, and a single 127 to mark the end of that pin's data. The number of pins supported shall be inferred by the message length. The GUI should use this query to discover how many pins exist. The list of supported modes may be used to provide a mode configuration menu that only shows the valid choices when the user configures a pin, or disables/grays choices which do not apply. The resolution information may be used to adapt to future implementations where PWM, Analog and others may have different resolution.
Analog messages are numbered 0 to 15, which traditionally refer to the Arduino pins labeled A0, A1, A2, etc. However, these pins are actually configured using "normal" pin numbers in the pin mode message, and when those pins are uses for non-analog functions. The analog mapping query provides the information about which pins (as used with Firmata's pin mode message) correspond to the analog channels.
/* analog mapping query * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 analog mapping query (0x69) * 2 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
/* analog mapping response * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 analog mapping response (0x73) * 2 analog channel corresponding to pin 0, or 127 if pin 0 does not support analog * 3 analog channel corresponding to pin 1, or 127 if pin 1 does not support analog * 4 analog channel corresponding to pin 2, or 127 if pin 2 does not support analog ... etc, one byte for each pin * N END_SYSEX (0xF7) */
The above 2 queries provide static data (should never change for a particular board). Because this information is fixed and should only need to be read once, these messages are designed for a simple implementation in StandardFirmata, rather that bandwidth savings (eg, using packed bit fields).
The pin state query allows the GUI to read the current configuration of any pin.
/* pin state query * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 pin state query (0x6D) * 2 pin (0 to 127) * 3 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
/* pin state response * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 pin state response (0x6E) * 2 pin (0 to 127) * 3 pin mode (the currently configured mode) * 4 pin state, bits 0-6 * 5 (optional) pin state, bits 7-13 * 6 (optional) pin state, bits 14-20 ... additional optional bytes, as many as needed * N END_SYSEX (0xF7) */
The pin "state" is any data written to the pin. For output modes (digital output, PWM, and Servo), the state is any value that has been previously written to the pin. A GUI needs this state to properly initialize any on-screen controls, so their initial settings match whatever the pin is actually doing. For input modes, typically the state is zero. However, for digital inputs, the state is the status of the pullup resistor.
The pin state query can also be used as a verification after sending pin modes or data messages.
Pin Mode Query and Response (old)
Pin mode allows a GUI-based host to read the current mode of each pin (usually at startup), so on-screen controls can be populated with correct information that reflects the actual state of the hardware, and unsupported modes may be grayed out.
/* pin status query * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 pin mode query (0x72) * 2 pin (0 to 127) * 3 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
/* pin status response
* -------------------------------
* 0 START_SYSEX (0xF0) (MIDI System Exclusive)
* 1 pin mode response (0x73)
* 2 pin (0 to 127)
* 3 pin mode (the currently configured mode, or 127 if this pin is not implemented)
* 4 corresponding analog channel (0 to 15, or 127 if none or pin is not implemented)
... additional bytes specify the modes this pin supports. The number
of supported modes is inferred by the message length
* N END_SYSEX (0xF7) (MIDI End of SysEx - EOX)
*/
This proposal is similar to the Report Pin Configuration below, but only a single pin is reported. Reporting all pins would involve a very long message, requiring a large buffer, if implemented with the existing sysex callback mechanism. Reporting a single pin at a time allows for simpler code, small buffers, and little impact to latency for other messages.
pulseIn/pulseOut
/* pulseIn/Out (uses 32-bit value) * ------------------------------- * 0 START_SYSEX (0xF0) (MIDI System Exclusive) * 1 pulseIn/Out (0x74) * 2 dataPin (0-127) * 3 bits 0-6 (least significant byte) * 4 bits 7-13 * 5 bits 14-20 * 6 bits 21-27 * 7 bits 28-34 (most significant byte) * 8 END_SYSEX (0xF7) (MIDI End of SysEx - EOX) */
ShiftOut
Supporting shift registers should be possible without much difficulty now that sysex has been implemented.
/* shiftIn/Out (uses 8-bit value) * ------------------------------ * 0 START_SYSEX (0xF0) * 1 shiftOut (0x75) * 2 dataPin (0-127) * 3 clockPin (0-127) * 4 latchPin (0-127) * 5 msbFirst (boolean) * 6 bits 0-6 (least significant byte) * 7 bit 7 (most significant bit) * n ... (as many byte pairs as needed) * n+1 END_SYSEX (0xF7) */
Or perhaps this should be more like the servo messages, with a SET_PIN_MODE-specific mode, like SHIFT, then a SHIFT_CONFIG message.
/* shiftIn/Out config * ------------------------------ * 0 START_SYSEX (0xF0) * 1 SHIFT_CONFIG * 2 dataPin (0-127) * 3 clockPin (0-127) * 4 latchPin (0-127) * 5 msbFirst (boolean) * 6 END_SYSEX (0xF7) */
/* shiftIn/Out data (total bits chopped to multiple of 8 so extra bits are ignored) * ------------------------------ * 0 START_SYSEX (0xF0) * 1 SHIFT_DATA * 2 dataPin (0-127) * 3 bits 0-6 (least significant byte) * 4 bits 7-13 * 5 bits 14-20 * 6 bits 21-27 * n ... * n+1 END_SYSEX (0xF7) */
Hardware Pin Querying
Get the available pins and resolution that the device supports.
/* hardwareSetup query request * ------------------------------ * 0 START_SYSEX (0xF0) * 1 hardwareSetup (0x??) * 2 END_SYSEX (0xF7) */
/* hardwareSetup data message * ------------------------------ * 0 START_SYSEX (0xF0) * 1 hardwareSetup (0x??) * 2 analog pins (0-127) * 3 analog resolution (0-127) * 4 digital pins (0-127) * 5 PWM resolution (0-127) * 6 PWM pin (0-127) * 7 next PWM pin (0-127) * ... * n END_SYSEX (0xF7) */
Report Available Pin Modes
This is from a proposal by Shigeru. This is tricky because it needs to be a giant bitmask with each bit representing a boolean value of whether that pin mode is supported or not. This is basically like a HID Descriptor. This version removes the "number of pins" value of Shigeru's proposal. The number of pins can be easily derived from the number of bytes.
/* availablePinModes * ------------------------------ * 0 START_SYSEX (0xF0) * 1 availablePinModes (0x??) * 2 The available pin modes for the 0th pin (0b0000000-0b1111111) * 3 The available pin modes for the 1st pin (0b0000000-0b1111111) * ... * n END_SYSEX (0xF7) */
Report Pin Configuration
This is from a proposal by Shigeru, Massimo has also expressed interest in having an API for reporting pin configurations. This version removes the "number of pins" value of Shigeru's proposal. The number of pins can be easily derived from the number of bytes.
/* pinSettings * ------------------------------ * 0 START_SYSEX (0xF0) * 1 pinSettings (0x??) * 2 port mode of the 0th pin (0-6) * 3 resolution of the 0th pin (0-127) * 4 port mode of the 1st pin (0-6) * 5 resolution of the 1st pin (0-127) * ... * n END_SYSEX (0xF7) */
Query Pull-up Resistor Status
When a digital pin is in INPUT mode, setting the pin HIGH will turn on the internal pull-up resistors. It could be useful to query the state of that pin somehow.
SPI
There has been some preliminary work done on including SPI in Firmata. It would most likely be based on SysEx.


