Depot RP2040 Firmware

This page details the firmware which runs on RP2040-based Depot multi-bus adaptor boards. When running, the firmware listens to the UART hosted by the RP2040’s USB connection for the following commands and for read/write indicators.

'A matrix display client and the CPU activity display example running on a Raspberry Pi 400'

Depot in action: the CPU activity display example running on a Raspberry Pi 400

The current version is 1.3.0. Read the release notes.

The buses currently supported:

Caution

Build the firmware with Pico SDK 1.5.0 or above.

Processing Incoming Data

The first received byte is checked by the firmware. If the value is less than 0x80, the code checks for a command, otherwise it processes the bytes as a read or write operation.

Generic Commands

Command

Arguments

Description

#

Set the bus-host’s current mode

?

Get bus-host device info

*

{1|0}

Set the bus-host’s LED state1

!

Respond to connection request

$

Get last device error. Returns an error code byte

1 If SHOW_HEARTBEAT is not defined in CmakeLists.txt, this call will respond with an ERR signal.

I²C Commands

Command

Arguments

Description

c

{bus_index}
{SDA_pin}
{SCL_pin}

Configure the I²C bus. This must be performed before the bus is
initialised. The first argument is 0 or 1; only bit 0 is checked.
The other args are 8-bit values

1

Set I²C bus frequency to 100kHz

4

Set I²C bus frequency to 400kHz

i

Initialise the I²C bus for use

x

Reset the I²C bus

p

Manually issue an I²C STOP signal

s

{bitfield}2

Start an I²C read or write operation targeting a specific device

d

Scan the I²C bus for devices. If the bus is not initialised when this
command is issued, it will be initialised automatically with default
values

2 Bits 7 through 1 are the target device’s I²C address. Bit 0 is the operation required: 1 for read, 0 for write.

1-Wire Commands

Command

Arguments

Description

c

{data_pin}

Configure the 1-Wire bus’ data pint. This must be performed before the
bus is initialised

i

Initialise the 1-Wire bus for use and discover devices

x

Reset the 1-Wire bus

d

Scan the 1-Wire bus for devices. If the bus is not initialised when this
command is issued, it will be initialised automatically with default
values

GPIO Commands

Command

Arguments

Description

g

{bitfield}

Set or get a GPIO pin. The pins can’t be those already used for buses

Button Commands

Command

Arguments

Description

b

{bitfield}

Set or get a Button. The pins can’t be those already in use

Command Responses

Commands are acknowledged with an ACK (0x0F) or an ERR (0xF0). Note that these values may change.

Commands that return arbitrary amounts of data append the data with \r\n as an end-of-sequence marker.

Modes

The multi-bus adaptor starts up in I²C mode, ie. ready for I²C operations. To switch to 1-Wire mode, send the # command followed by a character byte indicating the required mode.

Mode

Code

LED Colour

I²C

'i'

Cyan

1-Wire

'o'

Yellow

None

N/A

Red

Selecting a mode affects a number of operations, including device scans, info requests, reads, writes and bus initialisations.

The Adaptor’s Initial Response

Client code should first issue the connect request command, !.

In versions prior to 1.2.0, the response to this command would be four bytes: OK\r\n, or 4F4B0D0A in hex integers. From version 1.2.0, the adaptor continues to return four bytes, but now the final two bytes are, respectively, the adaptor’s firmware major and minor version numbers: 4F4B0102. Only four bytes are issued, so your code need not check for \r\n.

This data can be used to ensure the adaptor firmware is up to date and to determine what features are supported. For example, if an adaptor responds with OK\r\n, the client knows the firmware is less than 1.2.0 so it should not attempt to access 1-Wire functionality.

Read and Write Operations

The outcome depends on the value of the first byte in the sequence.

If the value is in the range 0x80 to 0xBF, it is a read operation and the number of bytes to read is given by: value - 0x80 + 1.

If the value is in the range 0xC0 to 0xFF, it is a write operation and the number of bytes to write is given by: value - 0xC0 + 1. These bytes follow the state byte.

Only 64 bytes can be requested/written at a time. This is usually sufficient, but for larger amounts, issue subsequent requests for 64 bytes or less.

GPIO

You configure a GPIO pin, or read its value, by issuing the g command followed by up to two bytes of data to indicate the target pin and the desired operation. GPIO features are available in all modes.

The first byte is formatted as follows:

Bit

Role

0-4

The GPIO pin number, 0-31

5

Is the operation a read (1)?

6

Is the pin an output (1) or input (0)?

7

The pin’s state: high (1) or low (0)

For example, to configure pin 11 to a digital output initially set to logic High, you would pass 0xCB, ie. 11001011.

To configure pin 24 as an input, send 0x58, or 01011000. To subsequently read the pin’s value, send 0x38, or 00111000.

The adaptor will respond with ACK or ERR on all configuration, or output state setting operations.

Read operations will return the value read as an 8-bit integer.

Buttons

You configure a GPIO pin as a button by issuing the b command followed by up to two bytes of data to indicate the target pin, the desired operation and the button’s configuration. Button features are available in all modes.

The first byte is formatted as follows:

Bit

Role

0-4

The GPIO pin number, 0-31

5

Is the operation a read (1)?

6

Is the button triggered when released (1) or pressed (0)?

7

The button’s polarity: high (1) or low (0)

For example, to configure pin 11 to button that defaults to logic High and is triggered when released, you would pass 0xCB, ie. 11001011.

Polarity indicates whether the button’s GPIO pin should be connected to an internal pull-up or pull-down resistor. You choose polarity on the basis of how your button is connected. For example, use a pull-down (0) for a button connected to 3V3: when pressed, the GPIO will move from low to high. If the GPIO rests a logic high — it has a pull-up — connect the button to GND.

Set bit 5 to return the current button states. This returns four bytes, with bits 1 through 31 representing the state of the button on that pin. A 1 indicates the button has been triggered; buttons not triggered or not configured are represented by 0.

The adaptor will respond with ACK or ERR on all configuration operations.

Caution

Button state is cleared on read. This is intentional because the goal is to provide basic button usage: ie. to allow applications to ask, was the button triggered? For more complex behaviours, such as supporting press-and-hold repeat key actions, please use the GPIO functionality to directly sample pin state and implement the logic in your application.

Device Scan Format

Requesting a peripheral device scan by issuing the d command in I²C mode returns is a string of I²C addresses separated by full-stops. Each address is a 7-bit value encoded as two-digit hex numbers.

If the adaptor is in 1-Wire mode, the returned string comprises 16 hex pairs for each included 1-Wire device. This is the 1-Wire device’s unique 64-bit ID.

Both strings are terminated by \r\n.

If no peripherals are present, Z\r\n is returned whatever mode is selected.

Adaptor Information Format

Requesting adaptor information by issuing the ? command returns a sequence of integers and strings separated by full stops and followed by \r\n. The sequence of fields is bus dependent.

For I²C mode:

Field

Size

Notes

Is I²C ready?

2

Binary value: 1 == true, 0 == false

Is I²C being used?

2

Binary value: 1 == true, 0 == false

I²C bus ID

2

1 or 0

I²C SDA pin

2-3

0-31 in decimal form

I²C SCL pin

2-3

0-31 in decimal form

I²C bus frequency

2

1 (100kHz) or 4 (400kHz)

I²C address

2-4

8-127 in decimal form

Firmware version

6-12

Major, minor and patch values as separate fields

Firmware build

2-4

1-999

Unique RP20240 ID

17

16-byte value as two-digit hex values

Board type

2-17

Per board ID string, eg. RP-PI-PICO

For 1-Wire mode:

Field

Size

Notes

Is 1-Wire ready?

2

Binary value: 1 == true, 0 == false

1-Wire data pin

2-3

0-31 in decimal form

Firmware version

6-12

Major, minor and patch values as separate fields

Firmware build

2-4

1-999

Unique RP20240 ID

17

16-byte value as two-digit hex values

Board type

2-17

Per board ID string, eg. RP-PI-PICO

Note Size includes the post-value separator.

Error Codes

The following errors are defined in the file errors.h:

Error

Code

GEN_NO_ERROR

0x00

GEN_UNKNOWN_MODE

0x01

GEN_UNKNOWN_COMMAND

0x02

GEN_LED_NOT_ENABLED

0x03

GEN_CANT_CONFIG_BUS

0x04

GEN_CANT_GET_BUS_INFO

0x05

I2C_NOT_READY

0x20

I2C_NOT_STARTED

0x21

I2C_COULD_NOT_WRITE

0x22

I2C_COULD_NOT_READ

0x23

I2C_ALREADY_STOPPED

0x24

I2C_COULD_NOT_CONFIGUREa

0x25

I2C_PINS_ALREADY_IN_USE

0x26

OW_NOT_READY

0x80

OW_NO_DEVICES_FOUND

0x81

OW_COULD_NOT_READ

0x82

OW_COULD_NOT_CONFIGURE

0x85

OW_PIN_ALREADY_IN_USE

0x86

GPIO_ILLEGAL_PIN

0xA0

GPIO_CANT_SET_PIN

0xA5

GPIO_PIN_ALREADY_IN_USE

0xA6

GPIO_CANT_SET_BUTTON

0xA7

The format is as follows:

  • Bits 6-8 — The mode.

  • Bits 1-5 — A mode-specific error code.

Mode

Mode Bits

General

000

I²C

001

SPI

010

UART

011

1-Wire

100

GPIO

101

Reserved

111

Source code

The multi-bus adaptor firmware source code can be found in this GitHub repo.

Build and Deploy the Adaptor Firmware

Note

The following assumes you have the Pico SDK installed on your build machine and that the PICO_SDK_PATH environment variable is set.

  1. Clone the repo.

  2. Navigate to the repo directory.

  3. Run cmake -S . -B firmwarebuild.

  4. Run cmake --build firmwarebuild.

  5. Write the firmware depending on which board you are using:

    • ./deploy.sh /path/to/device firmwarebuild/firmware/pico/firmware_pico_rp2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/qtpy/firmware_qtpy_rp2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/promicro/firmware_promicro.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/tiny/firmware_tiny2040.uf2

    • ./deploy.sh /path/to/device firmwarebuild/firmware/trinkey/firmware_trinkey2040.uf2

The deploy script tricks the RP2040-based board into booting into disk mode, then copies over the newly build firmware. When the copy completes, the RP2040 automatically reboots. This saves of a lot of tedious power-cycling with the BOOT button held down.

Note

From version 1.2.2, Depot’s build system respects the value of the Pico SDK environment variable PICO_BOARD if you have set one. In this case, only firmware for the target board will be built. If the setting references a board not yet supported by Depot, all supported firmware versions will be built.

Supported Boards