Bricks firmware
The Basics
The protocol is based on a simple set of messages that are passed between the Arduino and its controller over a serial port.
Each message has a simple format: one identifying byte and one byte specifying the message source, followed by between 0 and 3 data bytes or an unknown number of data bytes and a stop byte, depending on the message type.
Notation
We stick largely to C-compatible syntax. The notation used here which may be unfamiliar, or used differently elsewhere includes the following symbols:
| << | Left bitwise shift |
| >> | Right bitwise shift |
| & | Bitwise AND |
| | | Bitwise OR |
| ~ | Bitwise NOT |
| && | Logical AND |
| == | Equivalence test or statement |
| 0x80 | A hexadecimal number (128) |
The Messages
Message identifiers are a subset of the “command bytes.” Currently, the only
command byte which is not a message identifier is END_BLOCK, which marks the
end of a variable length data set. All command bytes are named constants with
values between 128 and 255. Data bytes must have values in the range [0, 127].
It is easy to check whether a received byte is a command or a data byte.
is_command( b ) = (b >= 128) = (b amp; 128)
is_identifier( b ) = ((b >= 128) and; (b != END_BLOCK))
is_data( b ) = (b < 128)
Messages from the controller to an Arduino may instigate a reply. Since the
message system is asynchronous, this means that a reply message should
arraive back at the controller a short time after the original message was
sent. Messages from the Arduino to the controller never expect replies.
Querying Arduino
This table outlines all of the messages that can be sent to the Arduino:
Message Value Data 1 Data 2 Effect Reply
SET_DTL_PIN_MODE130 PIN MODE Set the mode of a digital pin GET_DTL_PIN_MODE
GET_DTL_PIN_MODE 132 PIN — Get the mode fo a digital pin GET_DTL_PIN_MODE
RAW_DTL_PIN_MODES 135 — — Request a RAW_PIN_MODES reply (debugging) RAW_DTL_PIN_MODES
SET_ALL_DTL_PIN_MODES 136 MODE — Set all digital pins to the specified mode GET_DTL_PIN_MODE × n
GET_ALL_DTL_PIN_MODES 139 — — Get the current mode of all digital pins GET_DTL_PIN_MODE × n
SET_ALG_PIN_MODE141 PIN MODE Set the mode of an analog pin GET_ALG_PIN_MODE
GET_ALG_PIN_MODE142 PIN — Get the mode fo an analog pin GET_ALG_PIN_MODE
SET_ALL_ALG_PIN_MODES 144 MODE — Set all analog pins to the specified mode GET_ALG_PIN_MODE × n
GET_ALL_ALG_PIN_MODES 147 — — Get the current mode of all analog pins GET_ALG_PIN_MODE × n
GET_DIGITAL_PINS 149 — — Get the input state of all digital pins in INPUT mode GET_DIGITAL_PINS
GET_ANALOG 150 PIN — Get the input state of an analog pin GET_ANALOG
GET_ALL_ANALOG 153 — — Get the input state of all analog pins in INPUT mode GET_ANALOG × n
GET_USOUND 154 PIN — Get input from an untrasound sensor GET_USOUND
GET_ALL_USOUND 156 — — Get input from each pin in USOUND mode GET_USOUND × n
SET_PWM 159 PIN — Set the output of a pin that supports PWM mode
SET_CURRENT_MODE 160 MODE — Set the running mode GET_CURRENT_MODE
GET_CURRENT_MODE 163 — — Get the running mode GET_CURRENT_MODE
SET_XBEE_ID 165 ID — Set the ID of this XBee node in the network SET_XBEE_ID
GET_VERSION 255 — — Get the protocol verion that the Arduino is using GET_VERSION
Receiving Data
This table outlines all of the messages that might be received from the Arduino:
Message Value Data Effect
GET_DTL_PIN_MODE 132 PIN MODE — Reports the mode of a digital pin
RAW_DTL_PIN_MODES 135 MODE BITS … END_BLOCK Dumps internal digital pins mode representation
GET_DIGITAL_PINS 149 PINS 0–6 PINS 7–13 — Reports the state from digital INPUT pins
GET_ALG_PIN_MODE 142 PIN MODE — Reports the mode of an analog pin
GET_ANALOG 150 PIN MSB LSB Reports the state from an analog INPUT pin
GET_USOUND 154 PIN MSB LSB Reports the state from a digital USOUND pin
GET_CURRENT_MODE 163 MODE & 0x7F — — Reports the current running mode of the Arduino
SET_XBEE_ID 165 ID & 0x7F — — Reports a changed XBee network ID
ACK_COMMAND 249 CMD & 0x7F — — Notify receipt of command which would otherwise not reply
REPORT_ERROR 252 ERROR — — Report an error on the Arduino
GET_VERSION 255 MAJOR MINOR — Report the protocol version used by the Arduino
Data
This section describes the data bytes. Any byte marked PIN is simply a number
in the range [0, 13] (for digital pins) or [0, 5] (for analog pins).
Pin Modes
Pins may be in one of several modes. They are currently stored using 2 bits per
digital pin, but this is not part of the spec and can be changed at any time
without loss of backwards compatibility. The current selection are:
MODE Value Meaning
INPUT 0 Used for digital input
OUTPUT 1 Used for digital output
PWM 2 Used for PWM output
USOUND 3 Used for ultrasound range sensing
Whenever a pin mode is set on the Arduino, it will send a GET_PIN_MODE
message to the controller with the updated mode. This acts as a confirmation
that it worked and to simplify controller logic.
Running Modes
The firmware may be run in different modes. There are three currently supported:
ACTIVE_MODE, in which the Arduino will periodically send digital pin data
over the serial port; PASSIVE_MODE, in which no data will be send unless
requested by the controller and DELTA_MODE, in which data are sent only when
input is seen to have changed or when it is requested.
A mode is requested using the command SET_CURRENT_MODE and notifications of mode
changes are sent to the controller as GET_CURRENT_MODE messages.
Digital Data
Digital pin data are returned all together in a message beginning
GET_DIGITAL_PINS. Pins which are not in INPUT mode simply have 0 for their
returned values. We can create an integer, P, such that the value of an
INPUT pin, Valx, can be found simply (see here).
P = (pins0-6 | (pins7-13 << 7))
Valx = ((P & (1 << x)) == (1 << x)) = ((P & (1 << x)) != 0)
Ultrasound Data
Ultrasound data can only be retrieved from digital pins in USOUND mode. Trying
to read other pins will result in 0 as the data value. Ultrasound data is
received from messages beginning GET_USOUND. In order to reconstruct the
value, V, from the ultrasound sensor, apply the following equation:
V = ((MSB << 7) | LSB)
See here for an explanation of why we use this formula.
Errors
If the Arduino receives an unrecognised command or some data which is not
valid, or if there is an internal error of some kind, then it will send an
error notification message (beginning REPORT_ERROR) containing an error code.
Currently, the following error codes may be produced:
MODE Value Meaning
ERROR_BAD_PIN 1 Received an invalid pin number
ERROR_TIMEOUT 2 Internal timeout was reached
ERROR_BAD_CMD 4 Received unknown command
ERROR_XBEE_ID 7 Could not get or set the XBee ID
Extending the Protocol
To add a new message to the protocol, you must select an unused message
identifier. The message identifiers are bytes which have their most significant
bit set (they represent numbers greater than 127). They also all have an even
number of bits set. To produce the next usable number, the following approach
has been taken:
- Find the last number used.
- Remove the least significant bit
- Increment the result by 1.
- Add on a new least significant bit which makes the whole contain an even
number of set bits.
As an example, to add the identifier SET_XBEE_ID, the following was done:
- Take
GET_CURRENT_MODE == 163 (decimal) == 10100011 (binary).
- Remove the LSB: 10100011 becomes 1010001
- Increment the result by 1: 1010001 + 1 = 1010010
- Add the appropriate LSB: 1010010 becomes 10100101
The result gives SET_XBEE_ID == 10100101 (binary) == 165 (decimal)
