pinephone-keyboard/README.i2c-intf
2021-06-20 01:48:34 +02:00

144 lines
4.8 KiB
Text

I2C interface to the firmware
-----------------------------
To control the operation of the keyboard's firmware, the firmware
exposes some "registers" that the user can read/write using the
two kinds of I2C transfers.
1) set values of consecutive block of registers starting from REG_ADDR:
START TX(DEV_ADDR+WR REG_ADDR [REG_DATA REG+1_DATA REG+2_DATA ...]) STOP
2) read values of consecutive block of registers starting from REG_ADDR:
START TX(DEV_ADDR+WR REG_ADDR) STOP
START TX(DEV_ADDR+RD) RX(REG_ADDR [REG_DATA REG+1_DATA REG+2_DATA ...]) STOP
Device address is 0x15.
Registers
---------
0x00: Device ID1 (0x4b)
0x01: Device ID2 (0x42)
0x02: Firmware revision
0x03: Firmware features
bit 0: USB debugger
bit 1: Flashing mode
bit 2: Self-test features
0x04: System configuration
bit 0: disable KB scanning (1: scanning disabled, 0: scanning enabled)
bit 1: poll mode
1: don't rely on row change detection, poll the matrix periodically
(prevents MCU power down)
0: power down the MCU when no key is pressed, and rely on change
detection on row inupts to wake the MCU up
bit 2: enable USB debug interface
1: enabled
0: disabled
0x06: System command
Writing values into this register causes the firmware to perform
certain one-shot actions:
0x52 ('R') - reset the MCU
0x63 ('c') - run a column self-test
0x72 ('r') - run a row self-test
(results for both tests will be stored in test-result
registers)
0x10: Keyboard data for column 1
...
0x1b: Keyboard data for column 12
0x1c: CRC8 of keyboard data from 0x10-0x0b
0x20: Writing value 0x53 ('S') to this register stops the main app from
jumping to the user app.
0x50: Self-test results (32 bytes)
...
0x6f:
0x70: Flashing mode unlock key
(writing 0x46 to this register unlocks the flashing mode.)
0x71: Flashing control
Writing various commands to this register makes the MCU execute them,
if the MCU is not executing the previous command. Available commands:
0x52 - read a block of data from code ROM
0x57 - write a block of data to code ROM
0x45 - erase the code rom memory block (128B)
0x43 - confirm the validity of the firmware and enable redirection
to it from the main app (this redirection is automatically
disabled before executing the 0x57 command)
This register will ignore further commands as long as the last operation
is still in progress. This register will contain the code of the
currently executed operation, and will be cleared after the operation
finishes. Completion is also signalled by pulsing the INT pin shortly.
If the operation fails, this register will contain value 0xff. If it
succeeds it will contain value 0x00.
0x7d: target address low byte
0x7e: target address high byte
0x7f: CRC8 calculated for the 128B block of data from 0x80-0xff
- this must be written by the user when preparing data for write
operation, MCU checks the CRC8 of the data and compares it against
the value in this register before starting the execution of
0x57 command
- this is updated by the MCU after reading the data from flash memory
0x80: 128B block of EEPROM data (either read from code memory or to be
... written)
0xff
Usage
-----
User can modify register 0x03 to choose how the firmware should operate.
The settings are not persistent across resets.
To read the keyboard matrix status, the user can perform a 13B read transaction
from address 0x10 and calculate CRC8 on the first 12 bytes and compare it with
the 13th byte.
Bit 0 corresponds to row 1, bit 5 to row 6, bits 6 and 7 are always 0.
Flashing
--------
The firmware is split into 3 parts:
0x0000 - 0x2000: Stock USB bootloader
0x2000 - 0x4000: Stock FOSS firmware (flashable from stock bootloader)
0x4000 - 0x8000: User app (optional, flashable over I2C from stock FOSS firmware)
When the stock FOSS firmware runs after MCU powerup or reset, it will wait for 200ms
and listen on I2C. If 0x53 is not written to register 0x20 during that time and
the user's app is flashed and commited, it will redirect interrupt vectors to
0x4000+offset and jump to 0x4000, which will start executing user's app.
User app should always return value 0x00 when reading register 0x20, to make it
easy to distinguish that the "stay in stock app" command succeeded.
Flashing steps:
1) Unlock by writing 0x46 to register 0x70
2) Write address to 0x7d/0x7e
3) Write data to 0x80-0xff and CRC8 to 0x7f
4) Write command 0x57 to 0x71
5) Poll 0x71 for result (either 0x00 or 0xff)
... repeat 2-5 for all memory locations to be flashed
6) Write command 0x43 to reg 0x71
7) Wait for success
Reset the MCU.