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
0x80A 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:

MessageValueData 1Data 2EffectReply
SET_DTL_PIN_MODE130PIN MODE Set the mode of a digital pin GET_DTL_PIN_MODE
GET_DTL_PIN_MODE 132PIN Get the mode fo a digital pin GET_DTL_PIN_MODE
RAW_DTL_PIN_MODES 135Request a RAW_PIN_MODES reply (debugging) RAW_DTL_PIN_MODES
SET_ALL_DTL_PIN_MODES 136MODE Set all digital pins to the specified mode GET_DTL_PIN_MODE × n
GET_ALL_DTL_PIN_MODES 139Get the current mode of all digital pins GET_DTL_PIN_MODE × n
SET_ALG_PIN_MODE141PIN 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 149Get the input state of all digital pins in INPUT mode GET_DIGITAL_PINS
GET_ANALOG 150PIN 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:

  1. Find the last number used.
  2. Remove the least significant bit
  3. Increment the result by 1.
  4. 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:

  1. Take GET_CURRENT_MODE == 163 (decimal) == 10100011 (binary).
  2. Remove the LSB: 10100011 becomes 1010001
  3. Increment the result by 1: 1010001 + 1 = 1010010
  4. Add the appropriate LSB: 1010010 becomes 10100101

The result gives SET_XBEE_ID == 10100101 (binary) == 165 (decimal)