Proposals

From Firmata

Jump to: navigation, search

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:

Image:Firmata_test_screenshot.png


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.

Personal tools