DeckCtrl protocol specification

DeckCtrl protocol specification

The DeckCtrl backend implements an I2C-based deck and control discovery mechanism that uses microcontrollers on deck boards (deck controllers) to enable dynamic enumeration of multiple decks. The microcontroller implementing the DeckCtrl protocol is exclusively used for that purpose, deck functionalities are implemented on another chip/microcontroller.

Discovery Sequence

The DeckCtrl backend performs the following sequence during initialization:

1. Reset Phase (Address 0x41)

All deck controllers on the bus listen to the reset address. A read operation to this address causes all controllers to reset their I2C configuration and return to default state.

i2cdevReadReg16(I2C1_DEV, 0x41, 0x0000, 2, dummy_buffer);
vTaskDelay(10);  // Wait for controllers to restart

2. Listening Mode (Address 0x42)

After reset, the unconfigured deck controllers must be told to enter listening mode. In this state, they monitor the bus for address assignment.

i2cdevReadReg16(I2C1_DEV, 0x42, 0x0000, 2, dummy_buffer);

3. Enumeration

For each deck to be discovered:

3a. Read CPU ID (Address 0x43, Register 0x1900)

We read the next unconfigured deck with the lowest ID. The other decks will observe a bus collision and back-off, they will then be ready to be put back in listening mode in step 2.

uint8_t cpu_id[12];
i2cdevReadReg16(I2C1_DEV, 0x43, 0x1900, 12, cpu_id);

Note: This is the core of the discovery protocol, it uses the native anticollision behavior of I2C to be able to detect decks one by one. I2C detects a collision if it tries to let the open-collector data line high while another deck is pulling it low. The deck that wanted it high will detect the line low, assume a collision, and back-off

3b. Assign Address (Address 0x43, Register 0x1800)

Write a unique I2C address to the deck controller. The address range starts at 0x44:

uint8_t deck_address = 0x44 + deck_count;
i2cdevWriteReg16(I2C1_DEV, 0x43, 0x1800, 1, &deck_address);

After receiving its address, the deck removes itself from the default addresses and begins responding only to its assigned address.

3c. Read Deck Information (Assigned Address, Register 0x0000)

Read the deck’s identification and capability information from its newly assigned address:

uint8_t deck_info[21];
i2cdevReadReg16(I2C1_DEV, deck_address, 0x0000, 21, deck_info);

4. Repeat

Return to step 2 (listening mode) to discover the next deck. Continue until no more decks respond.

I2C Address Map

Address Purpose Description
0x41 Reset Broadcast reset to all deck controllers
0x42 Listen Put unconfigured controllers in listening mode
0x43 Default Read CPU ID and assign unique address
0x44-0x4F Assigned Individual deck addresses (up to 12 decks)

The maximum number of decks is configured via CONFIG_DECK_BACKEND_DECKCTRL_MAX_DECKS.

Memory Layout

Register Map

Once configured, the deck-control behaves like an I2C memory with the following memory map:

Register Size Description
0x0000 21 Deck identification information (Read-only)
0x0020 2016 ROM partitions
0x1000 4 GPIO
0x1800 1 Address assignment (write-only)
0x1900 12 CPU unique ID (read-only)

Deck Information Format (Register 0x0000)

The 21-byte deck information block contains:

Offset Size Field Description
0x00 2 Magic Magic number 0xBCDC (big-endian)
0x02 1 Major Version Firmware major version
0x03 1 Minor Version Firmware minor version
0x04 1 Vendor ID Deck vendor ID
0x05 1 Product ID Deck product ID
0x06 1 Board Revision Board revision character
0x07 14 Product Name Null-terminated product name string

Magic Number

All valid DeckCtrl decks must return the magic number 0xBCDC in the first two bytes. This validates that the device is a proper DeckCtrl deck.

Format: Big-endian (0xBC at offset 0, 0xDC at offset 1)

Vendor ID and Product ID

The VID/PID pair uniquely identifies the deck type and is used to match with the appropriate deck driver in firmware. These should match the vid and pid fields in the DeckDriver structure.

Product Name

A human-readable name for the deck (up to 14 characters plus null terminator). This is used for logging and debugging.

Backend Context

Each discovered DeckCtrl deck receives a DeckCtrlContext structure that contains backend-specific data:

typedef struct deckCtrlContext_s {
    uint8_t i2cAddress;  // Assigned I2C address (0x44+)
} DeckCtrlContext;

Deck drivers can access this context through the DeckInfo structure passed to their init() function:

void myDeckInit(DeckInfo *info) {
    DeckCtrlContext *ctx = (DeckCtrlContext *)info->backendContext;
    uint8_t address = ctx->i2cAddress;

    // Use address for I2C communication with the deck
}

ROM Partition formats (address 0x0020)

The space is split in partitions with the following format:

Offset Size Field Description
0x00 2 Length Partition full size, 0x0000 if no more partition
0x02 4 Type Partition type
0x06 Length - 6 Data Partition data

At offset length the next partition is starting. A length of 0x0000 denote the end of the partition table. A length between 1 and 5 included is invalid.

There are no partition type defined yet. This mechanism is designed to allow for future expansion.

GPIO control

Offset Size Field Reset value Description
0x00 2 Direction 0x00 GPIO Direction. 0 for input, 1 for output
0x02 2 Value * GPIO Value